Class is an annotation iff it is annotated by kotlin.annotation.annotation, or is kotlin.annotation.annotation itself.

JetClassOrObject.isAnnotation() is no more in use during resolve. Additional test.
This commit is contained in:
Mikhail Glukhikh
2015-07-28 18:20:19 +03:00
parent d71217eb5c
commit a072550931
12 changed files with 151 additions and 39 deletions
@@ -656,9 +656,14 @@ public class JetFlowInformationProvider {
else if (element instanceof JetParameter) { else if (element instanceof JetParameter) {
PsiElement owner = element.getParent().getParent(); PsiElement owner = element.getParent().getParent();
if (owner instanceof JetPrimaryConstructor) { if (owner instanceof JetPrimaryConstructor) {
if (!((JetParameter) element).hasValOrVar() && if (!((JetParameter) element).hasValOrVar()) {
!((JetPrimaryConstructor) owner).getContainingClassOrObject().isAnnotation()) { JetClassOrObject containingClass = ((JetPrimaryConstructor) owner).getContainingClassOrObject();
report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor), ctxt); 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) { else if (owner instanceof JetFunction) {
@@ -108,7 +108,7 @@ abstract public class JetClassOrObject : JetTypeParameterListOwnerStub<KotlinCla
public fun getSecondaryConstructors(): List<JetSecondaryConstructor> = getBody()?.getSecondaryConstructors().orEmpty() public fun getSecondaryConstructors(): List<JetSecondaryConstructor> = 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 isAnnotation(): Boolean = getBuiltInAnnotationEntry() != null
public fun getBuiltInAnnotationEntry(): JetAnnotationEntry? = getAnnotation(KotlinBuiltIns.FQ_NAMES.annotation.shortName().asString()) public fun getBuiltInAnnotationEntry(): JetAnnotationEntry? = getAnnotation(KotlinBuiltIns.FQ_NAMES.annotation.shortName().asString())
@@ -170,16 +170,6 @@ public class ModifiersChecker {
return modifierList != null && modifierList.hasModifier(INNER_KEYWORD); 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 { public class ModifiersCheckingProcedure {
@NotNull @NotNull
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
@@ -226,7 +227,7 @@ public class CallExpressionResolver {
if (functionDescriptor instanceof ConstructorDescriptor) { if (functionDescriptor instanceof ConstructorDescriptor) {
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
if (DescriptorUtils.isAnnotationClass(containingDescriptor) if (DescriptorUtils.isAnnotationClass(containingDescriptor)
&& !canInstantiateAnnotationClass(callExpression)) { && !canInstantiateAnnotationClass(callExpression, context.trace)) {
context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression)); context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression));
} }
if (DescriptorUtils.isEnumClass(containingDescriptor)) { if (DescriptorUtils.isEnumClass(containingDescriptor)) {
@@ -273,7 +274,7 @@ public class CallExpressionResolver {
return TypeInfoFactoryPackage.noTypeInfo(context); return TypeInfoFactoryPackage.noTypeInfo(context);
} }
private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression) { private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression, @NotNull BindingTrace trace) {
//noinspection unchecked //noinspection unchecked
PsiElement parent = PsiTreeUtil.getParentOfType(expression, JetValueArgument.class, JetParameter.class); PsiElement parent = PsiTreeUtil.getParentOfType(expression, JetValueArgument.class, JetParameter.class);
if (parent instanceof JetValueArgument) { if (parent instanceof JetValueArgument) {
@@ -282,7 +283,8 @@ public class CallExpressionResolver {
else if (parent instanceof JetParameter) { else if (parent instanceof JetParameter) {
JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class); JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
if (jetClass != null) { if (jetClass != null) {
return jetClass.isAnnotation(); DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, jetClass);
return DescriptorUtils.isAnnotationClass(descriptor);
} }
} }
return false; return false;
@@ -37,9 +37,6 @@ public class JetClassInfo extends JetClassOrObjectInfo<JetClass> {
else if (element.isEnum()) { else if (element.isEnum()) {
this.kind = ClassKind.ENUM_CLASS; this.kind = ClassKind.ENUM_CLASS;
} }
else if (element.isAnnotation()) {
this.kind = ClassKind.ANNOTATION_CLASS;
}
else { else {
this.kind = ClassKind.CLASS; this.kind = ClassKind.CLASS;
} }
@@ -78,8 +78,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final LazyClassTypeConstructor typeConstructor; private final LazyClassTypeConstructor typeConstructor;
private final Modality modality; private final Modality modality;
private final Visibility visibility; private final Visibility visibility;
private final ClassKind kind; private final NotNullLazyValue<ClassKind> kind;
private final boolean isInner; private final NotNullLazyValue<Boolean> isInner;
private final Annotations annotations; private final Annotations annotations;
private final Annotations danglingAnnotations; private final Annotations danglingAnnotations;
@@ -119,24 +119,44 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.typeConstructor = new LazyClassTypeConstructor(); this.typeConstructor = new LazyClassTypeConstructor();
this.kind = classLikeInfo.getClassKind(); final ClassKind syntaxKind = classLikeInfo.getClassKind();
this.isCompanionObject = classLikeInfo instanceof JetObjectInfo && ((JetObjectInfo) classLikeInfo).isCompanionObject(); this.isCompanionObject = classLikeInfo instanceof JetObjectInfo && ((JetObjectInfo) classLikeInfo).isCompanionObject();
JetModifierList modifierList = classLikeInfo.getModifierList(); final JetModifierList modifierList = classLikeInfo.getModifierList();
if (kind.isSingleton()) { if (syntaxKind.isSingleton()) {
this.modality = Modality.FINAL; this.modality = Modality.FINAL;
} }
else { else {
Modality defaultModality = kind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL; Modality defaultModality = syntaxKind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL;
this.modality = resolveModalityFromModifiers(modifierList, defaultModality); this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
} }
boolean isLocal = classOrObject != null && JetPsiUtil.isLocal(classOrObject); boolean isLocal = classOrObject != null && JetPsiUtil.isLocal(classOrObject);
this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this)); Visibility defaultVisibility;
this.isInner = isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(this); 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(); StorageManager storageManager = c.getStorageManager();
final ClassDescriptor descriptor = this;
this.isInner = storageManager.createLazyValue(new Function0<Boolean>() {
@Override
public Boolean invoke() {
return isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(descriptor);
}
});
this.kind = storageManager.createLazyValue(new Function0<ClassKind>() {
@Override
public ClassKind invoke() {
return (syntaxKind == ClassKind.CLASS && KotlinBuiltIns.isAnnotation(descriptor)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
}
});
if (modifierList != null) { if (modifierList != null) {
this.annotations = new LazyAnnotations( this.annotations = new LazyAnnotations(
@@ -386,7 +406,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
@NotNull @NotNull
@Override @Override
public ClassKind getKind() { public ClassKind getKind() {
return kind; return kind.invoke();
} }
@NotNull @NotNull
@@ -403,7 +423,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
@Override @Override
public boolean isInner() { public boolean isInner() {
return isInner; return isInner.invoke();
} }
@Override @Override
@@ -0,0 +1,25 @@
// FILE: a.kt
<!NOT_AN_ANNOTATION_CLASS!>annotation<!> class annotation
// FILE: test/b.kt
package test
<!NOT_AN_ANNOTATION_CLASS!>test.annotation<!> class annotation
kotlin.annotation.annotation class realAnnotation
realAnnotation class My
// FILE: other/c.kt
package other
annotation class My
<!NOT_AN_ANNOTATION_CLASS!>test.annotation<!> class Your
kotlin.annotation.annotation class His
My class Our
@@ -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
}
}
@@ -4,14 +4,13 @@ enum class Target {
FUNCTION FUNCTION
} }
target(Target.CLASSIFIER) <!NOT_AN_ANNOTATION_CLASS!>target(Target.CLASSIFIER)<!>
public annotation class target(vararg val allowedTargets: Target) public <!NOT_AN_ANNOTATION_CLASS!>annotation<!> class target(vararg val allowedTargets: Target)
target(Target.CLASSIFIER) <!NOT_AN_ANNOTATION_CLASS!>target(Target.CLASSIFIER)<!>
public annotation(AnnotationRetention.SOURCE) class annotation( public <!NOT_AN_ANNOTATION_CLASS!>annotation(AnnotationRetention.SOURCE)<!> class annotation(
val retention: AnnotationRetention = AnnotationRetention.RUNTIME, val retention: AnnotationRetention = AnnotationRetention.RUNTIME,
val repeatable: Boolean = false val repeatable: Boolean = false
) )
annotation class some <!NOT_AN_ANNOTATION_CLASS!>annotation<!> class some
@@ -34,7 +34,7 @@ internal final enum class Target : kotlin.Enum<Target> {
public final /*synthesized*/ fun values(): kotlin.Array<Target> public final /*synthesized*/ fun values(): kotlin.Array<Target>
} }
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 = ...) public constructor annotation(/*0*/ retention: kotlin.annotation.AnnotationRetention = ..., /*1*/ repeatable: kotlin.Boolean = ...)
internal final val repeatable: kotlin.Boolean internal final val repeatable: kotlin.Boolean
internal final val retention: kotlin.annotation.AnnotationRetention 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 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 constructor some()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean 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 hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String 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<out Target>*/) public constructor target(/*0*/ vararg allowedTargets: Target /*kotlin.Array<out Target>*/)
internal final val allowedTargets: kotlin.Array<out Target> internal final val allowedTargets: kotlin.Array<out Target>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -669,6 +669,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); 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") @TestMetadata("annotationInheritance.kt")
public void testAnnotationInheritance() throws Exception { public void testAnnotationInheritance() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/annotationInheritance.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/annotationInheritance.kt");
@@ -997,6 +997,11 @@ public class KotlinBuiltIns {
return FQ_NAMES.array.equals(getFqName(descriptor)); 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) { public static boolean isCloneable(@NotNull ClassDescriptor descriptor) {
return FQ_NAMES.cloneable.equals(getFqName(descriptor)); return FQ_NAMES.cloneable.equals(getFqName(descriptor));
} }