Convert kotlin.Deprecated back into a no-arg java.lang.Deprecated if applicable

This at least maintains consistency with the Java extractor, although we lose its arguments if any were supplied Java-side.
This commit is contained in:
Chris Smowton
2022-11-22 16:19:41 +00:00
parent 658c7a20cf
commit 8bbb34a498
7 changed files with 99 additions and 3 deletions

View File

@@ -498,8 +498,19 @@ open class KotlinFileExtractor(
extractEnumTypeAccesses: Boolean,
contextLabel: String? = null
): Label<out DbExpr> {
val isConvertedJavaDeprecatedAnnotation = (constructorCall.type as? IrSimpleType)?.classFqName?.asString() == "kotlin.Deprecated" &&
constructorCall.source is JavaSourceElement
val extractType =
(
if (isConvertedJavaDeprecatedAnnotation)
pluginContext.referenceClass(FqName("java.lang.Deprecated"))?.defaultType
else
null
) ?: erase(constructorCall.type)
// Erase the type here because the JVM lowering erases the annotation type, and so the Java extractor will see it in erased form.
val t = useType(erase(constructorCall.type))
val t = useType(extractType)
val annotationContextLabel = contextLabel ?: "{${t.javaResult.id}}"
val id = tw.getLabelFor<DbDeclannotation>("@\"annotation;{$parent};$annotationContextLabel\"")
tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx)
@@ -508,7 +519,11 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(constructorCall)
tw.writeHasLocation(id, locId)
for (i in 0 until constructorCall.valueArgumentsCount) {
// If this is `java.lang.Deprecated`, extract an annotation without parameters -- whatever the original source
// may have supplied has been lost.
val paramCount = if (isConvertedJavaDeprecatedAnnotation) 0 else constructorCall.valueArgumentsCount
for (i in 0 until paramCount) {
val param = constructorCall.symbol.owner.valueParameters[i]
val prop = constructorCall.symbol.owner.parentAsClass.declarations
.filterIsInstance<IrProperty>()

View File

@@ -18,6 +18,12 @@ User.java:
# 4| 2: [ExprStmt] <Expr>;
# 4| 0: [ClassInstanceExpr] new Annotated(...)
# 4| -3: [TypeAccess] Annotated
# 4| 3: [ExprStmt] <Expr>;
# 4| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByJava(...)
# 4| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByJava
# 4| 4: [ExprStmt] <Expr>;
# 4| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByJava(...)
# 4| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByJava
ktUser.kt:
# 0| [CompilationUnit] ktUser
# 1| 1: [Class] KtUser
@@ -32,6 +38,20 @@ ktUser.kt:
# 4| 1: [LocalVariableDeclExpr] a
# 4| 0: [ClassInstanceExpr] new AnnotatedUsedByKotlin(...)
# 4| -3: [TypeAccess] AnnotatedUsedByKotlin
# 5| 1: [LocalVariableDeclStmt] var ...;
# 5| 1: [LocalVariableDeclExpr] b
# 5| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByKotlin(...)
# 5| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByKotlin
# 6| 2: [LocalVariableDeclStmt] var ...;
# 6| 1: [LocalVariableDeclExpr] c
# 6| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByKotlin(...)
# 6| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByKotlin
# 8| 3: [ExprStmt] <Expr>;
# 8| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
# 8| 0: [TypeAccess] Unit
# 8| 1: [MethodAccess] isJavaLetter(...)
# 8| -1: [TypeAccess] Character
# 8| 0: [CharacterLiteral] a
test.kt:
# 0| [CompilationUnit] test
# 4| 1: [Interface] Ann1
@@ -235,6 +255,36 @@ test.kt:
# 27| 5: [BlockStmt] { ... }
# 27| 0: [SuperConstructorInvocationStmt] super(...)
# 35| 1: [BlockStmt] { ... }
# 37| 10: [Class] HasJavaDeprecatedAnnotationUsedByJava
#-----| -3: (Annotations)
# 37| 1: [Annotation] Deprecated
# 38| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByJava
# 37| 5: [BlockStmt] { ... }
# 37| 0: [SuperConstructorInvocationStmt] super(...)
# 38| 1: [BlockStmt] { ... }
# 40| 11: [Class] HasKotlinDeprecatedAnnotationUsedByJava
#-----| -3: (Annotations)
# 40| 1: [Annotation] Deprecated
# 0| 1: [StringLiteral] "Kotlin deprecation message 1"
# 41| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByJava
# 40| 5: [BlockStmt] { ... }
# 40| 0: [SuperConstructorInvocationStmt] super(...)
# 41| 1: [BlockStmt] { ... }
# 43| 12: [Class] HasJavaDeprecatedAnnotationUsedByKotlin
#-----| -3: (Annotations)
# 43| 1: [Annotation] Deprecated
# 44| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByKotlin
# 43| 5: [BlockStmt] { ... }
# 43| 0: [SuperConstructorInvocationStmt] super(...)
# 44| 1: [BlockStmt] { ... }
# 46| 13: [Class] HasKotlinDeprecatedAnnotationUsedByKotlin
#-----| -3: (Annotations)
# 46| 1: [Annotation] Deprecated
# 0| 1: [StringLiteral] "Kotlin deprecation message 2"
# 47| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByKotlin
# 46| 5: [BlockStmt] { ... }
# 46| 0: [SuperConstructorInvocationStmt] super(...)
# 47| 1: [BlockStmt] { ... }
# 0| [TypeLiteral] String.class
# 0| 0: [TypeAccess] String
# 0| [ArrayInit] {...}

View File

@@ -1,7 +1,7 @@
public class User {
public static void user(Ann1 a1, Ann2 a2) {
a1.x(); a2.z(); new Annotated();
a1.x(); a2.z(); new Annotated(); new HasJavaDeprecatedAnnotationUsedByJava(); new HasKotlinDeprecatedAnnotationUsedByJava();
}
}

View File

@@ -0,0 +1,5 @@
| HasJavaDeprecatedAnnotationUsedByJava | java.lang.Deprecated |
| HasJavaDeprecatedAnnotationUsedByKotlin | java.lang.Deprecated |
| HasKotlinDeprecatedAnnotationUsedByJava | kotlin.Deprecated |
| HasKotlinDeprecatedAnnotationUsedByKotlin | kotlin.Deprecated |
| isJavaLetter | java.lang.Deprecated |

View File

@@ -0,0 +1,11 @@
import java
from Annotatable a, Annotation ann
where
(
a.(Method).hasQualifiedName("java.lang", "Character", "isJavaLetter") or
a.(ClassOrInterface).fromSource()
) and
ann = a.getAnAnnotation() and
ann.getType().getName() = "Deprecated"
select a.toString(), a.getAnAnnotation().getType().getQualifiedName()

View File

@@ -2,6 +2,10 @@ public class KtUser {
fun user() {
val a = AnnotatedUsedByKotlin()
val b = HasJavaDeprecatedAnnotationUsedByKotlin()
val c = HasKotlinDeprecatedAnnotationUsedByKotlin()
// Use a Java-defined function carrying a java.lang.Deprecated annotation:
java.lang.Character.isJavaLetter('a')
}
}

View File

@@ -34,3 +34,14 @@ class Annotated { }
@AnnWithDefaults
class AnnotatedUsedByKotlin { }
@java.lang.Deprecated
class HasJavaDeprecatedAnnotationUsedByJava
@kotlin.Deprecated("Kotlin deprecation message 1")
class HasKotlinDeprecatedAnnotationUsedByJava
@java.lang.Deprecated
class HasJavaDeprecatedAnnotationUsedByKotlin
@kotlin.Deprecated("Kotlin deprecation message 2")
class HasKotlinDeprecatedAnnotationUsedByKotlin