Annotations on object literals are now correctly resolved #KT-9320 Fixed
This commit is contained in:
@@ -108,6 +108,16 @@ public abstract class AnnotationCodegen {
|
|||||||
"Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated;
|
"Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (annotated instanceof ClassDescriptor
|
||||||
|
&& !applicableTargets.contains(KotlinTarget.CLASS)
|
||||||
|
&& !applicableTargets.contains(KotlinTarget.ANNOTATION_CLASS)) {
|
||||||
|
ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
|
||||||
|
if (classDescriptor.getVisibility() == Visibilities.LOCAL) {
|
||||||
|
assert applicableTargets.contains(KotlinTarget.EXPRESSION) :
|
||||||
|
"Inconsistent target list for object literal annotation: " + applicableTargets + " on " + annotated;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String descriptor = genAnnotation(annotation);
|
String descriptor = genAnnotation(annotation);
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
|
|||||||
+11
-2
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||||
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
|
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
|
||||||
@@ -172,8 +173,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
|||||||
return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
|
return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Annotation entries are taken from both own annotations (if any) and object literal annotations (if any)
|
||||||
|
List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
|
||||||
|
if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
|
||||||
|
// TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
|
||||||
|
annotationEntries.addAll(KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
|
||||||
|
}
|
||||||
if (modifierList != null) {
|
if (modifierList != null) {
|
||||||
|
annotationEntries.addAll(modifierList.getAnnotationEntries());
|
||||||
|
}
|
||||||
|
if (!annotationEntries.isEmpty()) {
|
||||||
this.annotations = new LazyAnnotations(
|
this.annotations = new LazyAnnotations(
|
||||||
new LazyAnnotationsContext(
|
new LazyAnnotationsContext(
|
||||||
c.getAnnotationResolver(),
|
c.getAnnotationResolver(),
|
||||||
@@ -186,7 +195,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
|||||||
return getOuterScope();
|
return getOuterScope();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifierList.getAnnotationEntries()
|
annotationEntries
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+4
-1
@@ -1587,7 +1587,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KotlinTypeInfo visitAnnotatedExpression(KtAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
public KotlinTypeInfo visitAnnotatedExpression(KtAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
|
if (!(expression.getBaseExpression() instanceof KtObjectLiteralExpression)) {
|
||||||
|
// annotations on object literals are resolved later inside LazyClassDescriptor
|
||||||
|
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
|
||||||
|
}
|
||||||
|
|
||||||
KtExpression baseExpression = expression.getBaseExpression();
|
KtExpression baseExpression = expression.getBaseExpression();
|
||||||
if (baseExpression == null) {
|
if (baseExpression == null) {
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
annotation class Ann(val v: String = "???")
|
||||||
|
@Ann open class My
|
||||||
|
fun box(): String {
|
||||||
|
val v = @Ann("OK") object: My() {}
|
||||||
|
val klass = v.javaClass
|
||||||
|
|
||||||
|
val annotations = klass.annotations
|
||||||
|
// Ann, kotlin.Metadata, kotlin.jvm.internal.KotlinClass
|
||||||
|
if (annotations.size != 3) return "Fail annotations size is ${annotations.size}: ${annotations.toList()}"
|
||||||
|
val annotation = annotations.filterIsInstance<Ann>().firstOrNull()
|
||||||
|
?: return "Fail no @Ann: ${annotations.toList()}"
|
||||||
|
|
||||||
|
return annotation.v
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
@Ann open class My
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class AnnExpr
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val v = @Ann @AnnExpr object: My() {}
|
||||||
|
val w = @Ann @AnnExpr { v: My -> v.hashCode() }
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
@java.lang.annotation.Retention
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinClass
|
||||||
|
public abstract class Ann
|
||||||
|
|
||||||
|
@kotlin.annotation.Target
|
||||||
|
@java.lang.annotation.Retention
|
||||||
|
@java.lang.annotation.Target
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinClass
|
||||||
|
public abstract class AnnExpr
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinClass
|
||||||
|
public final class Kt9320Kt$foo$v$1 {
|
||||||
|
inner class Kt9320Kt$foo$v$1
|
||||||
|
method <init>(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.jvm.internal.KotlinSyntheticClass
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinFunction
|
||||||
|
final class Kt9320Kt$foo$w$1 {
|
||||||
|
public final static field INSTANCE: Kt9320Kt$foo$w$1
|
||||||
|
inner class Kt9320Kt$foo$w$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public final @Ann method invoke(@org.jetbrains.annotations.NotNull p0: My): int
|
||||||
|
public synthetic method invoke(p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinFileFacade
|
||||||
|
public final class Kt9320Kt {
|
||||||
|
inner class Kt9320Kt$foo$v$1
|
||||||
|
inner class Kt9320Kt$foo$w$1
|
||||||
|
public final static method foo(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ann
|
||||||
|
@kotlin.Metadata
|
||||||
|
@kotlin.jvm.internal.KotlinClass
|
||||||
|
public class My {
|
||||||
|
public method <init>(): void
|
||||||
|
}
|
||||||
@@ -15,6 +15,5 @@ fun foo(arg: Int): My {
|
|||||||
bar @FunAnn { arg }
|
bar @FunAnn { arg }
|
||||||
bar @ExprAnn { arg }
|
bar @ExprAnn { arg }
|
||||||
val x = @FunAnn fun() = arg
|
val x = @FunAnn fun() = arg
|
||||||
// TODO: KT-9320: ClsAnn does not appear in bytecode
|
|
||||||
return (@ClsAnn object: My() {})
|
return (@ClsAnn object: My() {})
|
||||||
}
|
}
|
||||||
@@ -41,6 +41,7 @@ final class LiteralsKt$foo$2 {
|
|||||||
public synthetic method invoke(): java.lang.Object
|
public synthetic method invoke(): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ClsAnn
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
@kotlin.jvm.internal.KotlinClass
|
@kotlin.jvm.internal.KotlinClass
|
||||||
public final class LiteralsKt$foo$3 {
|
public final class LiteralsKt$foo$3 {
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt9320.kt")
|
||||||
|
public void testKt9320() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/kt9320.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("literals.kt")
|
@TestMetadata("literals.kt")
|
||||||
public void testLiterals() throws Exception {
|
public void testLiterals() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/literals.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/literals.kt");
|
||||||
|
|||||||
+6
@@ -64,6 +64,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedObjectLiteral.kt")
|
||||||
|
public void testAnnotatedObjectLiteral() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/annotatedObjectLiteral.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotationsOnDefault.kt")
|
@TestMetadata("annotationsOnDefault.kt")
|
||||||
public void testAnnotationsOnDefault() throws Exception {
|
public void testAnnotationsOnDefault() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/annotationsOnDefault.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user