From 082469aee45235b7af64d6f95c859fd8a752bedd Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 16 Oct 2015 15:14:16 +0300 Subject: [PATCH] Resolve annotations on type parameters of functions and properties --- .../kotlin/resolve/AnnotationChecker.kt | 5 +- .../kotlin/resolve/DeclarationsChecker.java | 1 - .../kotlin/resolve/DescriptorResolver.java | 15 +++--- .../resolve/FunctionDescriptorResolver.kt | 2 +- .../ExpressionTypingVisitorForStatements.java | 4 -- .../AnnotationForFunctionTypeParameter.kt | 6 +-- .../AnnotationsForPropertyTypeParameter.kt | 6 +-- .../annotations/options/targets/typeParams.kt | 38 +++++++++++++ .../options/targets/typeParams.txt | 54 +++++++++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 +++ 10 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 8d96efcd7a1..2df7becdea5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -35,13 +35,16 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil public class AnnotationChecker(private val additionalCheckers: Iterable) { public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) { - if (annotated is JetTypeParameter) return // TODO: support type parameter annotations val actualTargets = getActualTargetList(annotated, descriptor) checkEntries(annotated.annotationEntries, actualTargets, trace) if (annotated is JetCallableDeclaration) { annotated.typeReference?.let { check(it, trace) } annotated.receiverTypeReference?.let { check(it, trace) } } + if (annotated is JetTypeParameterListOwner && annotated is JetCallableDeclaration) { + // TODO: support type parameter annotations for type parameters on classes and properties + annotated.typeParameters.forEach { check(it, trace) } + } if (annotated is JetTypeReference) { annotated.typeElement?.typeArgumentsAsTypes?.filterNotNull()?.forEach { check(it, trace) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java index e95c9cb48ea..46b1a785645 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java @@ -353,7 +353,6 @@ public class DeclarationsChecker { if (typeParameter != null) { DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); } - annotationChecker.check(jetTypeParameter, trace, null); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index f210a5ad6b7..11d4e95d88c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -386,13 +386,15 @@ public class DescriptorResolver { public List resolveTypeParametersForCallableDescriptor( DeclarationDescriptor containingDescriptor, LexicalWritableScope extensibleScope, + LexicalScope scopeForAnnotationsResolve, List typeParameters, BindingTrace trace ) { List result = new ArrayList(); for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { JetTypeParameter typeParameter = typeParameters.get(i); - result.add(resolveTypeParameterForCallableDescriptor(containingDescriptor, extensibleScope, typeParameter, i, trace)); + result.add(resolveTypeParameterForCallableDescriptor( + containingDescriptor, extensibleScope, scopeForAnnotationsResolve, typeParameter, i, trace)); } return result; } @@ -400,6 +402,7 @@ public class DescriptorResolver { private TypeParameterDescriptorImpl resolveTypeParameterForCallableDescriptor( DeclarationDescriptor containingDescriptor, LexicalWritableScope extensibleScope, + LexicalScope scopeForAnnotationsResolve, JetTypeParameter typeParameter, int index, BindingTrace trace @@ -409,12 +412,12 @@ public class DescriptorResolver { trace.report(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY.on(typeParameter)); } - // TODO: Support annotation for type parameters - AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(typeParameter, trace); + Annotations annotations = + annotationResolver.resolveAnnotationsWithArguments(scopeForAnnotationsResolve, typeParameter.getModifierList(), trace); TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification( containingDescriptor, - Annotations.Companion.getEMPTY(), + annotations, typeParameter.hasModifier(JetTokens.REIFIED_KEYWORD), typeParameter.getVariance(), JetPsiUtil.safeName(typeParameter.getName()), @@ -771,8 +774,8 @@ public class DescriptorResolver { LexicalWritableScope writableScope = new LexicalWritableScope( scope, containingDeclaration, false, null, new TraceBasedRedeclarationHandler(trace), "Scope with type parameters of a property"); - typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(propertyDescriptor, writableScope, typeParameters, - trace); + typeParameterDescriptors = resolveTypeParametersForCallableDescriptor( + propertyDescriptor, writableScope, scope, typeParameters, trace); writableScope.changeLockLevel(WritableScope.LockLevel.READING); resolveGenericBounds(property, propertyDescriptor, writableScope, typeParameterDescriptors, trace); scopeWithTypeParameters = writableScope; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index 10b3102f929..70d3b71daf1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -147,7 +147,7 @@ class FunctionDescriptorResolver( TraceBasedRedeclarationHandler(trace), "Function descriptor header scope") val typeParameterDescriptors = descriptorResolver. - resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, function.getTypeParameters(), trace) + resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, scope, function.getTypeParameters(), trace) innerScope.changeLockLevel(WritableScope.LockLevel.BOTH) descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java index 418009c12d4..fd246e16b10 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java @@ -128,10 +128,6 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.getDelegate())); } - for (JetTypeParameter typeParameter : property.getTypeParameters()) { - AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(typeParameter, context.trace); - } - VariableDescriptor propertyDescriptor = components.descriptorResolver. resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace); JetExpression initializer = property.getInitializer(); diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt index 83cab8cd4ed..bdf7f9c3805 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationForFunctionTypeParameter.kt @@ -1,12 +1,12 @@ annotation class A1 annotation class A2(val some: Int = 12) -fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> topFun() = 12 +fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> topFun() = 12 class SomeClass { - fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> method() = 12 + fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> method() = 12 fun foo() { - fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> innerFun() = 12 + fun <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> innerFun() = 12 } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt b/compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt index df4c0e3a99f..ac6e1774733 100644 --- a/compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt +++ b/compiler/testData/diagnostics/tests/annotations/AnnotationsForPropertyTypeParameter.kt @@ -1,12 +1,12 @@ annotation class A1 annotation class A2(val some: Int = 12) -val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> T.topProp: Int get() = 12 +val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> T.topProp: Int get() = 12 class SomeClass { - val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> T.field: Int get() = 12 + val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> T.field: Int get() = 12 fun foo() { - val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> localVal = 12 + val <@A1 @A2(3) @A2 @A1(12) @A2("Test") T> localVal = 12 } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.kt new file mode 100644 index 00000000000..3f435d0d25c --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.kt @@ -0,0 +1,38 @@ +//!DIAGNOSTICS: -UNUSED_PARAMETER + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class A + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class B(val i: Int = 12) + + +fun <@A @B(3) T> topFun() = 12 + +class Class1 { + fun <@A @B(3)T> method() = 12 + + fun foo() { + fun <@A @B(3) T> innerFun() = 12 + } +} + +val <@A @B(3) T> T.topProp: Int get() = 12 + +class Class2 { + val <@A @B(3) T> T.field: Int get() = 12 +} + + +@A fun foo() {} +@A class D +fun foo(i: @A Int) { + @A val i = 1 +} +fun test(t: @A T): T = t + + +@Target(AnnotationTarget.TYPE) +internal annotation class C + +fun <@C T> test2(t: T): T = t \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.txt b/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.txt new file mode 100644 index 00000000000..0302134adf0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.txt @@ -0,0 +1,54 @@ +package + +public val T.topProp: kotlin.Int +@A() public fun foo(): kotlin.Unit +public fun foo(/*0*/ i: @A() kotlin.Int): kotlin.Unit +public fun test(/*0*/ t: @A() T): T +public fun test2(/*0*/ t: T): T +public fun topFun(): kotlin.Int + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.annotation() public final class A : kotlin.Annotation { + public constructor A() + 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.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.annotation() public final class B : kotlin.Annotation { + public constructor B(/*0*/ i: kotlin.Int = ...) + public final val i: kotlin.Int + 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.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.annotation() internal final class C : kotlin.Annotation { + public constructor C() + 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 +} + +public final class Class1 { + public constructor Class1() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun method(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Class2 { + public constructor Class2() + public final val T.field: kotlin.Int + 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 +} + +@A() public final class D { + public constructor D() + 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/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 37adfcc2b79..0e844f0392e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -1354,6 +1354,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("typeParams.kt") + public void testTypeParams() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/targets/typeParams.kt"); + doTest(fileName); + } + @TestMetadata("typeargs.kt") public void testTypeargs() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/targets/typeargs.kt");