Annotation / modifier checking for setter parameters / for variables / multi declarations, tests, relevant test changes #KT-9145 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-09-14 20:06:08 +03:00
parent f1fcb14f44
commit 22229af930
19 changed files with 112 additions and 12 deletions
@@ -40,7 +40,8 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
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 JetFunction) { if (annotated is JetDeclarationWithBody) {
// JetFunction or JetPropertyAccessor
for (parameter in annotated.valueParameters) { for (parameter in annotated.valueParameters) {
if (!parameter.hasValOrVar()) { if (!parameter.hasValOrVar()) {
check(parameter, trace) check(parameter, trace)
@@ -168,6 +169,7 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList { private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList {
return when (annotated) { return when (annotated) {
is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
is JetMultiDeclarationEntry -> TargetLists.T_LOCAL_VARIABLE
is JetProperty -> { is JetProperty -> {
if (annotated.isLocal) if (annotated.isLocal)
TargetLists.T_LOCAL_VARIABLE TargetLists.T_LOCAL_VARIABLE
@@ -194,6 +194,15 @@ public class ModifiersChecker {
ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor); ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor);
} }
public void checkModifiersForMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration) {
annotationChecker.check(multiDeclaration, trace, null);
ModifierCheckerCore.INSTANCE$.check(multiDeclaration, trace, null);
for (JetMultiDeclarationEntry multiEntry: multiDeclaration.getEntries()) {
annotationChecker.check(multiEntry, trace, null);
ModifierCheckerCore.INSTANCE$.check(multiEntry, trace, null);
}
}
private void checkNestedClassAllowed(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) { private void checkNestedClassAllowed(@NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
if (modifierListOwner.hasModifier(INNER_KEYWORD)) return; if (modifierListOwner.hasModifier(INNER_KEYWORD)) return;
if (modifierListOwner instanceof JetClass && !(modifierListOwner instanceof JetEnumEntry)) { if (modifierListOwner instanceof JetClass && !(modifierListOwner instanceof JetEnumEntry)) {
@@ -212,7 +212,8 @@ public object ModifierCheckerCore {
} }
public fun check(listOwner: JetModifierListOwner, trace: BindingTrace, descriptor: DeclarationDescriptor?) { public fun check(listOwner: JetModifierListOwner, trace: BindingTrace, descriptor: DeclarationDescriptor?) {
if (listOwner is JetFunction) { if (listOwner is JetDeclarationWithBody) {
// JetFunction or JetPropertyAccessor
for (parameter in listOwner.valueParameters) { for (parameter in listOwner.valueParameters) {
if (!parameter.hasValOrVar()) { if (!parameter.hasValOrVar()) {
check(parameter, trace, null) check(parameter, trace, null)
@@ -392,6 +392,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
JetParameter loopParameter = expression.getLoopParameter(); JetParameter loopParameter = expression.getLoopParameter();
if (loopParameter != null) { if (loopParameter != null) {
VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context); VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(loopParameter, variableDescriptor);
loopScope.addVariableDescriptor(variableDescriptor); loopScope.addVariableDescriptor(variableDescriptor);
} }
@@ -404,6 +405,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration( components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
); );
components.modifiersChecker.withTrace(context.trace).checkModifiersForMultiDeclaration(multiParameter);
} }
} }
@@ -185,6 +185,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
return TypeInfoFactoryPackage.noTypeInfo(context); return TypeInfoFactoryPackage.noTypeInfo(context);
} }
components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context); components.multiDeclarationResolver.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
components.modifiersChecker.withTrace(context.trace).checkModifiersForMultiDeclaration(multiDeclaration);
return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context)); return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context));
} }
@@ -1,3 +1,4 @@
@Target(AnnotationTarget.TYPE)
annotation class My annotation class My
fun foo() { fun foo() {
@@ -2,7 +2,7 @@ package
public fun foo(): kotlin.Unit public fun foo(): kotlin.Unit
kotlin.annotation.annotation() public final class My : kotlin.Annotation { kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) kotlin.annotation.annotation() public final class My : kotlin.Annotation {
public constructor 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 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
@@ -5,10 +5,10 @@ data class A(val x: Int, val y: Int)
fun bar(): Array<A> = null!! fun bar(): Array<A> = null!!
fun foo() { fun foo() {
for (Ann(1) i in 1..100) {} for (@Ann(1) i in 1..100) {}
for (Ann(2) i in 1..100) {} for (@Ann(2) i in 1..100) {}
for (Ann(3) (x, @Ann(4) y) in bar()) {} for (<!WRONG_ANNOTATION_TARGET!>@Ann(3)<!> (x, @Ann(4) y) in bar()) {}
for (<!UNRESOLVED_REFERENCE!>Err<!> (x,y) in bar()) {} for (<!UNRESOLVED_REFERENCE, WRONG_ANNOTATION_TARGET, DEPRECATED_UNESCAPED_ANNOTATION!>Err<!> (x,y) in bar()) {}
} }
@@ -1,7 +1,7 @@
fun foo(<!UNRESOLVED_REFERENCE, DEPRECATED_UNESCAPED_ANNOTATION!>varargs<!> <!UNUSED_PARAMETER!>f<!> : Int) {} fun foo(<!UNRESOLVED_REFERENCE, DEPRECATED_UNESCAPED_ANNOTATION!>varargs<!> <!UNUSED_PARAMETER!>f<!> : Int) {}
var bar : Int = 1 var bar : Int = 1
set(<!UNRESOLVED_REFERENCE!>varargs<!> v) {} set(<!UNRESOLVED_REFERENCE, DEPRECATED_UNESCAPED_ANNOTATION!>varargs<!> v) {}
val x : (Int) -> Int = {<!UNRESOLVED_REFERENCE!>@varargs<!> <!TYPE_MISMATCH!>x<!> <!DEPRECATED_STATIC_ASSERT!>: Int<!> <!SYNTAX!>-> x<!>} val x : (Int) -> Int = {<!UNRESOLVED_REFERENCE!>@varargs<!> <!TYPE_MISMATCH!>x<!> <!DEPRECATED_STATIC_ASSERT!>: Int<!> <!SYNTAX!>-> x<!>}
@@ -4,7 +4,7 @@ annotation class test
fun foo(@test <!UNUSED_PARAMETER!>f<!> : Int) {} fun foo(@test <!UNUSED_PARAMETER!>f<!> : Int) {}
var bar : Int = 1 var bar : Int = 1
set(test v) {} set(@test v) {}
val x : (Int) -> Int = {@test <!TYPE_MISMATCH!>x<!> <!DEPRECATED_STATIC_ASSERT!>: Int<!> <!SYNTAX!>-> x<!>} // todo fix parser annotation on lambda parameter val x : (Int) -> Int = {@test <!TYPE_MISMATCH!>x<!> <!DEPRECATED_STATIC_ASSERT!>: Int<!> <!SYNTAX!>-> x<!>} // todo fix parser annotation on lambda parameter
@@ -1,5 +1,5 @@
fun test(): Any? { fun test(): Any? {
@ann val (a, b) = P(1, 1) <!WRONG_ANNOTATION_TARGET!>@ann<!> val (a, b) = P(1, 1)
return a + b return a + b
} }
@@ -0,0 +1,10 @@
// See KT-9145
@Target(AnnotationTarget.CLASS)
annotation class Ann
fun foo() {
for (<!WRONG_ANNOTATION_TARGET!>@Ann<!> <!WRONG_MODIFIER_TARGET!>private<!> x in 1..100) {
if (x == 1) return
}
}
@@ -0,0 +1,10 @@
package
public fun foo(): kotlin.Unit
kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) kotlin.annotation.annotation() public final class Ann : kotlin.Annotation {
public constructor Ann()
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
}
@@ -0,0 +1,7 @@
@Target(AnnotationTarget.CLASS)
annotation class My
data class Pair(val a: Int, val b: Int)
fun foo(): Int {
val (<!WRONG_ANNOTATION_TARGET!>@My<!> <!WRONG_MODIFIER_TARGET!>private<!> a, <!WRONG_ANNOTATION_TARGET!>@My<!> <!WRONG_MODIFIER_TARGET!>public<!> b) = Pair(12, 34)
return a + b
}
@@ -0,0 +1,22 @@
package
public fun foo(): kotlin.Int
kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) kotlin.annotation.annotation() public 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
}
kotlin.data() public final class Pair {
public constructor Pair(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int)
public final val a: kotlin.Int
public final val b: kotlin.Int
public final /*synthesized*/ fun component1(): kotlin.Int
public final /*synthesized*/ fun component2(): kotlin.Int
public final /*synthesized*/ fun copy(/*0*/ a: kotlin.Int = ..., /*1*/ b: kotlin.Int = ...): Pair
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
}
@@ -0,0 +1,8 @@
// KT-9145
@Target(AnnotationTarget.CLASS)
annotation class Ann
var x: Int
get() = 1
set(<!WRONG_ANNOTATION_TARGET!>@Ann<!> <!WRONG_MODIFIER_TARGET!>private<!> x) { }
@@ -0,0 +1,10 @@
package
public var x: kotlin.Int
kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) kotlin.annotation.annotation() public final class Ann : kotlin.Annotation {
public constructor Ann()
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
}
@@ -1043,6 +1043,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("forParam.kt")
public void testForParam() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/forParam.kt");
doTest(fileName);
}
@TestMetadata("javaDocumented.kt") @TestMetadata("javaDocumented.kt")
public void testJavaDocumented() throws Exception { public void testJavaDocumented() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/javaDocumented.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/javaDocumented.kt");
@@ -1061,6 +1067,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("multiDeclaration.kt")
public void testMultiDeclaration() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/multiDeclaration.kt");
doTest(fileName);
}
@TestMetadata("repeatable.kt") @TestMetadata("repeatable.kt")
public void testRepeatable() throws Exception { public void testRepeatable() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/repeatable.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/repeatable.kt");
@@ -1073,6 +1085,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("setterParam.kt")
public void testSetterParam() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/setterParam.kt");
doTest(fileName);
}
@TestMetadata("target.kt") @TestMetadata("target.kt")
public void testTarget() throws Exception { public void testTarget() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/target.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/target.kt");
@@ -215,8 +215,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) { if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
if (smartCompletion != null) { if (smartCompletion != null) {
@suppress("UNUSED_VARIABLE") // we don't use InheritanceSearcher val (additionalItems, @Suppress("UNUSED_VARIABLE") inheritanceSearcher) = smartCompletion.additionalItems()
val (additionalItems, inheritanceSearcher) = smartCompletion.additionalItems()
// all additional items should have SMART_COMPLETION_ITEM_PRIORITY_KEY to be recognized by SmartCompletionInBasicWeigher // all additional items should have SMART_COMPLETION_ITEM_PRIORITY_KEY to be recognized by SmartCompletionInBasicWeigher
for (item in additionalItems) { for (item in additionalItems) {