diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetFlowInformationProvider.java index bc60175afb6..8f4d8edaef5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetFlowInformationProvider.java @@ -656,9 +656,14 @@ public class JetFlowInformationProvider { else if (element instanceof JetParameter) { PsiElement owner = element.getParent().getParent(); if (owner instanceof JetPrimaryConstructor) { - if (!((JetParameter) element).hasValOrVar() && - !((JetPrimaryConstructor) owner).getContainingClassOrObject().isAnnotation()) { - report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor), ctxt); + if (!((JetParameter) element).hasValOrVar()) { + JetClassOrObject containingClass = ((JetPrimaryConstructor) owner).getContainingClassOrObject(); + DeclarationDescriptor containingClassDescriptor = trace.get( + BindingContext.DECLARATION_TO_DESCRIPTOR, containingClass + ); + if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor)) { + report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor), ctxt); + } } } else if (owner instanceof JetFunction) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClassOrObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClassOrObject.kt index 28f9cc18fb8..c978a50d358 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClassOrObject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetClassOrObject.kt @@ -108,7 +108,7 @@ abstract public class JetClassOrObject : JetTypeParameterListOwnerStub = getBody()?.getSecondaryConstructors().orEmpty() - deprecated(value = "It's no more possible to determine it exactly using AST. Use ClassDescriptor methods instead, e.g. getKind()") + deprecated(value = "It's no more possible to determine it exactly using AST. Use ClassDescriptor.getKind() instead") public fun isAnnotation(): Boolean = getBuiltInAnnotationEntry() != null public fun getBuiltInAnnotationEntry(): JetAnnotationEntry? = getAnnotation(KotlinBuiltIns.FQ_NAMES.annotation.shortName().asString()) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index 9e134960e8e..21a9cbb7d97 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -170,16 +170,6 @@ public class ModifiersChecker { return modifierList != null && modifierList.hasModifier(INNER_KEYWORD); } - @NotNull - public static Visibility getDefaultClassVisibility(@NotNull ClassDescriptor descriptor) { - if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) { - // should be be accessible where containing class is accessible by default - return Visibilities.PUBLIC; - } - return Visibilities.INTERNAL; - } - - public class ModifiersCheckingProcedure { @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java index 572f25a8911..20c69567c1d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.java @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; @@ -226,7 +227,7 @@ public class CallExpressionResolver { if (functionDescriptor instanceof ConstructorDescriptor) { DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); if (DescriptorUtils.isAnnotationClass(containingDescriptor) - && !canInstantiateAnnotationClass(callExpression)) { + && !canInstantiateAnnotationClass(callExpression, context.trace)) { context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression)); } if (DescriptorUtils.isEnumClass(containingDescriptor)) { @@ -273,7 +274,7 @@ public class CallExpressionResolver { return TypeInfoFactoryPackage.noTypeInfo(context); } - private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression) { + private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression, @NotNull BindingTrace trace) { //noinspection unchecked PsiElement parent = PsiTreeUtil.getParentOfType(expression, JetValueArgument.class, JetParameter.class); if (parent instanceof JetValueArgument) { @@ -282,7 +283,8 @@ public class CallExpressionResolver { else if (parent instanceof JetParameter) { JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class); if (jetClass != null) { - return jetClass.isAnnotation(); + DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, jetClass); + return DescriptorUtils.isAnnotationClass(descriptor); } } return false; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/JetClassInfo.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/JetClassInfo.java index 5c8e8ff6215..09a408c8bf0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/JetClassInfo.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/JetClassInfo.java @@ -37,9 +37,6 @@ public class JetClassInfo extends JetClassOrObjectInfo { else if (element.isEnum()) { this.kind = ClassKind.ENUM_CLASS; } - else if (element.isAnnotation()) { - this.kind = ClassKind.ANNOTATION_CLASS; - } else { this.kind = ClassKind.CLASS; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 850de3414b5..30a4f6c9dbb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -78,8 +78,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes private final LazyClassTypeConstructor typeConstructor; private final Modality modality; private final Visibility visibility; - private final ClassKind kind; - private final boolean isInner; + private final NotNullLazyValue kind; + private final NotNullLazyValue isInner; private final Annotations annotations; private final Annotations danglingAnnotations; @@ -119,24 +119,44 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes this.typeConstructor = new LazyClassTypeConstructor(); - this.kind = classLikeInfo.getClassKind(); + final ClassKind syntaxKind = classLikeInfo.getClassKind(); this.isCompanionObject = classLikeInfo instanceof JetObjectInfo && ((JetObjectInfo) classLikeInfo).isCompanionObject(); - JetModifierList modifierList = classLikeInfo.getModifierList(); - if (kind.isSingleton()) { + final JetModifierList modifierList = classLikeInfo.getModifierList(); + if (syntaxKind.isSingleton()) { this.modality = Modality.FINAL; } else { - Modality defaultModality = kind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL; + Modality defaultModality = syntaxKind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL; this.modality = resolveModalityFromModifiers(modifierList, defaultModality); } boolean isLocal = classOrObject != null && JetPsiUtil.isLocal(classOrObject); - this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this)); - this.isInner = isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(this); + Visibility defaultVisibility; + if (syntaxKind == ClassKind.ENUM_ENTRY || (syntaxKind == ClassKind.OBJECT && isCompanionObject)) { + defaultVisibility = Visibilities.PUBLIC; + } + else { + defaultVisibility = Visibilities.INTERNAL; + } + this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, defaultVisibility); StorageManager storageManager = c.getStorageManager(); + final ClassDescriptor descriptor = this; + this.isInner = storageManager.createLazyValue(new Function0() { + @Override + public Boolean invoke() { + return isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(descriptor); + } + }); + + this.kind = storageManager.createLazyValue(new Function0() { + @Override + public ClassKind invoke() { + return (syntaxKind == ClassKind.CLASS && KotlinBuiltIns.isAnnotation(descriptor)) ? ClassKind.ANNOTATION_CLASS : syntaxKind; + } + }); if (modifierList != null) { this.annotations = new LazyAnnotations( @@ -386,7 +406,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @NotNull @Override public ClassKind getKind() { - return kind; + return kind.invoke(); } @NotNull @@ -403,7 +423,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes @Override public boolean isInner() { - return isInner; + return isInner.invoke(); } @Override diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.kt new file mode 100644 index 00000000000..4000e9831ed --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.kt @@ -0,0 +1,25 @@ +// FILE: a.kt + +annotation class annotation + +// FILE: test/b.kt + +package test + +test.annotation class annotation + +kotlin.annotation.annotation class realAnnotation + +realAnnotation class My + +// FILE: other/c.kt + +package other + +annotation class My + +test.annotation class Your + +kotlin.annotation.annotation class His + +My class Our diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.txt b/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.txt new file mode 100644 index 00000000000..e4988f260a7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.txt @@ -0,0 +1,63 @@ +package + +annotation() internal final class annotation { + public constructor annotation() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +package other { + + kotlin.annotation.annotation() internal final class His : kotlin.Annotation { + public constructor His() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + kotlin.annotation.annotation() internal final class My : kotlin.Annotation { + public constructor My() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + other.My() internal final class Our { + public constructor Our() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + test.annotation() internal final class Your { + public constructor Your() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +package test { + + test.realAnnotation() internal final class My { + public constructor My() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + test.annotation() internal final class annotation { + public constructor annotation() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + kotlin.annotation.annotation() internal final class realAnnotation : kotlin.Annotation { + public constructor realAnnotation() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/options/annotation.kt b/compiler/testData/diagnostics/tests/annotations/options/annotation.kt index fd33f6dff3c..c687573ef42 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/annotation.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/annotation.kt @@ -4,14 +4,13 @@ enum class Target { FUNCTION } -target(Target.CLASSIFIER) -public annotation class target(vararg val allowedTargets: Target) +target(Target.CLASSIFIER) +public annotation class target(vararg val allowedTargets: Target) -target(Target.CLASSIFIER) -public annotation(AnnotationRetention.SOURCE) class annotation( +target(Target.CLASSIFIER) +public annotation(AnnotationRetention.SOURCE) class annotation( val retention: AnnotationRetention = AnnotationRetention.RUNTIME, val repeatable: Boolean = false ) -annotation class some - +annotation class some \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/annotation.txt b/compiler/testData/diagnostics/tests/annotations/options/annotation.txt index 6e7bdae469f..de452c1ea83 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/annotation.txt +++ b/compiler/testData/diagnostics/tests/annotations/options/annotation.txt @@ -34,7 +34,7 @@ internal final enum class Target : kotlin.Enum { public final /*synthesized*/ fun values(): kotlin.Array } -target(allowedTargets = {Target.CLASSIFIER}) annotation(retention = AnnotationRetention.SOURCE) public final class annotation : kotlin.Annotation { +target(allowedTargets = {Target.CLASSIFIER}) annotation(retention = AnnotationRetention.SOURCE) public final class annotation { public constructor annotation(/*0*/ retention: kotlin.annotation.AnnotationRetention = ..., /*1*/ repeatable: kotlin.Boolean = ...) internal final val repeatable: kotlin.Boolean internal final val retention: kotlin.annotation.AnnotationRetention @@ -43,14 +43,14 @@ target(allowedTargets = {Target.CLASSIFIER}) annotation(retention = AnnotationRe public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -annotation() internal final class some : kotlin.Annotation { +annotation() internal final class some { public constructor some() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -target(allowedTargets = {Target.CLASSIFIER}) annotation() public final class target : kotlin.Annotation { +target(allowedTargets = {Target.CLASSIFIER}) annotation() public final class target { public constructor target(/*0*/ vararg allowedTargets: Target /*kotlin.Array*/) internal final val allowedTargets: kotlin.Array public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index aeffa27b2eb..46199e8b39d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -669,6 +669,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("AnnotationIdentifier.kt") + public void testAnnotationIdentifier() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/AnnotationIdentifier.kt"); + doTest(fileName); + } + @TestMetadata("annotationInheritance.kt") public void testAnnotationInheritance() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/annotationInheritance.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 4a4169dedf0..c89d6c6701b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -997,6 +997,11 @@ public class KotlinBuiltIns { return FQ_NAMES.array.equals(getFqName(descriptor)); } + public static boolean isAnnotation(@NotNull ClassDescriptor descriptor) { + return DescriptorUtils.getFqName(descriptor) == FQ_NAMES.annotation.toUnsafe() + || containsAnnotation(descriptor, FQ_NAMES.annotation); + } + public static boolean isCloneable(@NotNull ClassDescriptor descriptor) { return FQ_NAMES.cloneable.equals(getFqName(descriptor)); }