Resolve annotations on type parameters of functions and properties
This commit is contained in:
@@ -35,13 +35,16 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
|||||||
public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
|
public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
|
||||||
|
|
||||||
public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) {
|
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)
|
val actualTargets = getActualTargetList(annotated, descriptor)
|
||||||
checkEntries(annotated.annotationEntries, actualTargets, trace)
|
checkEntries(annotated.annotationEntries, actualTargets, trace)
|
||||||
if (annotated is JetCallableDeclaration) {
|
if (annotated is JetCallableDeclaration) {
|
||||||
annotated.typeReference?.let { check(it, trace) }
|
annotated.typeReference?.let { check(it, trace) }
|
||||||
annotated.receiverTypeReference?.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) {
|
if (annotated is JetTypeReference) {
|
||||||
annotated.typeElement?.typeArgumentsAsTypes?.filterNotNull()?.forEach { check(it, trace) }
|
annotated.typeElement?.typeArgumentsAsTypes?.filterNotNull()?.forEach { check(it, trace) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,7 +353,6 @@ public class DeclarationsChecker {
|
|||||||
if (typeParameter != null) {
|
if (typeParameter != null) {
|
||||||
DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter);
|
DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter);
|
||||||
}
|
}
|
||||||
annotationChecker.check(jetTypeParameter, trace, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -386,13 +386,15 @@ public class DescriptorResolver {
|
|||||||
public List<TypeParameterDescriptorImpl> resolveTypeParametersForCallableDescriptor(
|
public List<TypeParameterDescriptorImpl> resolveTypeParametersForCallableDescriptor(
|
||||||
DeclarationDescriptor containingDescriptor,
|
DeclarationDescriptor containingDescriptor,
|
||||||
LexicalWritableScope extensibleScope,
|
LexicalWritableScope extensibleScope,
|
||||||
|
LexicalScope scopeForAnnotationsResolve,
|
||||||
List<JetTypeParameter> typeParameters,
|
List<JetTypeParameter> typeParameters,
|
||||||
BindingTrace trace
|
BindingTrace trace
|
||||||
) {
|
) {
|
||||||
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
|
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
|
||||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||||
JetTypeParameter typeParameter = typeParameters.get(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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -400,6 +402,7 @@ public class DescriptorResolver {
|
|||||||
private TypeParameterDescriptorImpl resolveTypeParameterForCallableDescriptor(
|
private TypeParameterDescriptorImpl resolveTypeParameterForCallableDescriptor(
|
||||||
DeclarationDescriptor containingDescriptor,
|
DeclarationDescriptor containingDescriptor,
|
||||||
LexicalWritableScope extensibleScope,
|
LexicalWritableScope extensibleScope,
|
||||||
|
LexicalScope scopeForAnnotationsResolve,
|
||||||
JetTypeParameter typeParameter,
|
JetTypeParameter typeParameter,
|
||||||
int index,
|
int index,
|
||||||
BindingTrace trace
|
BindingTrace trace
|
||||||
@@ -409,12 +412,12 @@ public class DescriptorResolver {
|
|||||||
trace.report(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY.on(typeParameter));
|
trace.report(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY.on(typeParameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support annotation for type parameters
|
Annotations annotations =
|
||||||
AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(typeParameter, trace);
|
annotationResolver.resolveAnnotationsWithArguments(scopeForAnnotationsResolve, typeParameter.getModifierList(), trace);
|
||||||
|
|
||||||
TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||||
containingDescriptor,
|
containingDescriptor,
|
||||||
Annotations.Companion.getEMPTY(),
|
annotations,
|
||||||
typeParameter.hasModifier(JetTokens.REIFIED_KEYWORD),
|
typeParameter.hasModifier(JetTokens.REIFIED_KEYWORD),
|
||||||
typeParameter.getVariance(),
|
typeParameter.getVariance(),
|
||||||
JetPsiUtil.safeName(typeParameter.getName()),
|
JetPsiUtil.safeName(typeParameter.getName()),
|
||||||
@@ -771,8 +774,8 @@ public class DescriptorResolver {
|
|||||||
LexicalWritableScope writableScope = new LexicalWritableScope(
|
LexicalWritableScope writableScope = new LexicalWritableScope(
|
||||||
scope, containingDeclaration, false, null, new TraceBasedRedeclarationHandler(trace),
|
scope, containingDeclaration, false, null, new TraceBasedRedeclarationHandler(trace),
|
||||||
"Scope with type parameters of a property");
|
"Scope with type parameters of a property");
|
||||||
typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(propertyDescriptor, writableScope, typeParameters,
|
typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(
|
||||||
trace);
|
propertyDescriptor, writableScope, scope, typeParameters, trace);
|
||||||
writableScope.changeLockLevel(WritableScope.LockLevel.READING);
|
writableScope.changeLockLevel(WritableScope.LockLevel.READING);
|
||||||
resolveGenericBounds(property, propertyDescriptor, writableScope, typeParameterDescriptors, trace);
|
resolveGenericBounds(property, propertyDescriptor, writableScope, typeParameterDescriptors, trace);
|
||||||
scopeWithTypeParameters = writableScope;
|
scopeWithTypeParameters = writableScope;
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ class FunctionDescriptorResolver(
|
|||||||
TraceBasedRedeclarationHandler(trace), "Function descriptor header scope")
|
TraceBasedRedeclarationHandler(trace), "Function descriptor header scope")
|
||||||
|
|
||||||
val typeParameterDescriptors = descriptorResolver.
|
val typeParameterDescriptors = descriptorResolver.
|
||||||
resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, function.getTypeParameters(), trace)
|
resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, scope, function.getTypeParameters(), trace)
|
||||||
innerScope.changeLockLevel(WritableScope.LockLevel.BOTH)
|
innerScope.changeLockLevel(WritableScope.LockLevel.BOTH)
|
||||||
descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace)
|
descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace)
|
||||||
|
|
||||||
|
|||||||
-4
@@ -128,10 +128,6 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.getDelegate()));
|
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.getDelegate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetTypeParameter typeParameter : property.getTypeParameters()) {
|
|
||||||
AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(typeParameter, context.trace);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableDescriptor propertyDescriptor = components.descriptorResolver.
|
VariableDescriptor propertyDescriptor = components.descriptorResolver.
|
||||||
resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace);
|
resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace);
|
||||||
JetExpression initializer = property.getInitializer();
|
JetExpression initializer = property.getInitializer();
|
||||||
|
|||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
annotation class A1
|
annotation class A1
|
||||||
annotation class A2(val some: Int = 12)
|
annotation class A2(val some: Int = 12)
|
||||||
|
|
||||||
fun <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> topFun() = 12
|
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> topFun() = 12
|
||||||
|
|
||||||
class SomeClass {
|
class SomeClass {
|
||||||
fun <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> method() = 12
|
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> method() = 12
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
fun <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> innerFun() = 12
|
fun <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> innerFun() = 12
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
annotation class A1
|
annotation class A1
|
||||||
annotation class A2(val some: Int = 12)
|
annotation class A2(val some: Int = 12)
|
||||||
|
|
||||||
val <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> T.topProp: Int get() = 12
|
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> T.topProp: Int get() = 12
|
||||||
|
|
||||||
class SomeClass {
|
class SomeClass {
|
||||||
val <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> T.field: Int get() = 12
|
val <<!WRONG_ANNOTATION_TARGET!>@A1<!> <!WRONG_ANNOTATION_TARGET!>@A2(3)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A1(<!TOO_MANY_ARGUMENTS!>12<!>)<!> <!WRONG_ANNOTATION_TARGET, REPEATED_ANNOTATION!>@A2(<!TYPE_MISMATCH!>"Test"<!>)<!> T> T.field: Int get() = 12
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val <<!UNSUPPORTED!>@A1<!> <!UNSUPPORTED!>@A2(3)<!> <!UNSUPPORTED!>@A2<!> <!UNSUPPORTED!>@A1(12)<!> <!UNSUPPORTED!>@A2("Test")<!> T> <!UNUSED_VARIABLE!>localVal<!> = 12
|
val <<!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>(3)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!><!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A1<!>(12)<!> <!WRONG_ANNOTATION_TARGET!>@<!DEBUG_INFO_MISSING_UNRESOLVED!>A2<!>("Test")<!> T> <!UNUSED_VARIABLE!>localVal<!> = 12
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+38
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<!WRONG_ANNOTATION_TARGET!>@A<!> fun foo() {}
|
||||||
|
<!WRONG_ANNOTATION_TARGET!>@A<!> class D
|
||||||
|
fun foo(i: <!WRONG_ANNOTATION_TARGET!>@A<!> Int) {
|
||||||
|
<!WRONG_ANNOTATION_TARGET!>@A<!> val <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 1
|
||||||
|
}
|
||||||
|
fun <T> test(t: <!WRONG_ANNOTATION_TARGET!>@A<!> T): T = t
|
||||||
|
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
internal annotation class C
|
||||||
|
|
||||||
|
fun <<!WRONG_ANNOTATION_TARGET!>@C<!> T> test2(t: T): T = t
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val </*0*/ T> T.topProp: kotlin.Int
|
||||||
|
@A() public fun foo(): kotlin.Unit
|
||||||
|
public fun foo(/*0*/ i: @A() kotlin.Int): kotlin.Unit
|
||||||
|
public fun </*0*/ T> test(/*0*/ t: @A() T): T
|
||||||
|
public fun </*0*/ T> test2(/*0*/ t: T): T
|
||||||
|
public fun </*0*/ T> 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 </*0*/ T> method(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Class2 {
|
||||||
|
public constructor Class2()
|
||||||
|
public final val </*0*/ T> 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
|
||||||
|
}
|
||||||
@@ -1354,6 +1354,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("typeargs.kt")
|
||||||
public void testTypeargs() throws Exception {
|
public void testTypeargs() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/targets/typeargs.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/targets/typeargs.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user