[FIR] Support several annotation argument diagnostics
This commit is contained in:
committed by
Mikhail Glukhikh
parent
0c13d3197c
commit
cfc1ebb4be
compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
annotation class Ann(val a: Array<KClass<*>>)
|
||||||
|
|
||||||
|
|
||||||
|
inline val <reified T> T.test
|
||||||
|
get() = @Ann(
|
||||||
|
<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(
|
||||||
|
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>T::class<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>Array<Array<Array<Array<T>>>>::class<!>
|
||||||
|
)<!>
|
||||||
|
) object {}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
FILE: annotationArgumentKClassLiteralTypeError.kt
|
||||||
|
public final annotation class Ann : R|kotlin/Annotation| {
|
||||||
|
public constructor(a: R|kotlin/Array<kotlin/reflect/KClass<*>>|): R|Ann| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<kotlin/reflect/KClass<*>>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<kotlin/reflect/KClass<*>>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val <reified T> R|T|.test: R|<anonymous><T>|
|
||||||
|
public get(): R|<anonymous><T>| {
|
||||||
|
^ @R|Ann|(<implicitArrayOf>(<getClass>(R|T|), <getClass>(Q|kotlin/Array|))) object : R|kotlin/Any| {
|
||||||
|
private constructor(): R|<anonymous><T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
annotation class Ann1(vararg val a: String)
|
||||||
|
annotation class Ann2(val a: IntArray)
|
||||||
|
annotation class Ann3(val a: Array<String>)
|
||||||
|
|
||||||
|
var foo = "a"
|
||||||
|
var bar = 1
|
||||||
|
fun baz() = 2
|
||||||
|
val arr = arrayOf("a", "b")
|
||||||
|
val two = 2
|
||||||
|
const val cnst = 3
|
||||||
|
|
||||||
|
class Class {
|
||||||
|
val a = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Ann1(
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo + bar<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>"$foo $bar"<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>"${baz()} "<!>
|
||||||
|
)
|
||||||
|
@Ann2(
|
||||||
|
<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bar<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>baz()<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bar + cnst<!>
|
||||||
|
)<!>
|
||||||
|
)
|
||||||
|
@Ann3(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>arr<!>)
|
||||||
|
fun test() {}
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
FILE: annotationArgumentMustBeConst.kt
|
||||||
|
public final annotation class Ann1 : R|kotlin/Annotation| {
|
||||||
|
public constructor(vararg a: R|kotlin/Array<out kotlin/String>|): R|Ann1| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<out kotlin/String>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<out kotlin/String>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final annotation class Ann2 : R|kotlin/Annotation| {
|
||||||
|
public constructor(a: R|kotlin/IntArray|): R|Ann2| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/IntArray| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/IntArray|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final annotation class Ann3 : R|kotlin/Annotation| {
|
||||||
|
public constructor(a: R|kotlin/Array<kotlin/String>|): R|Ann3| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<kotlin/String>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<kotlin/String>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final var foo: R|kotlin/String| = String(a)
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||||
|
public final var bar: R|kotlin/Int| = Int(1)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||||
|
public final fun baz(): R|kotlin/Int| {
|
||||||
|
^baz Int(2)
|
||||||
|
}
|
||||||
|
public final val arr: R|kotlin/Array<kotlin/String>| = R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(a), String(b)))
|
||||||
|
public get(): R|kotlin/Array<kotlin/String>|
|
||||||
|
public final val two: R|kotlin/Int| = Int(2)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
public final const val cnst: R|kotlin/Int| = Int(3)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
public final class Class : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Class| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Int| = Int(1)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
|
||||||
|
}
|
||||||
|
@R|Ann1|(vararg(R|/foo|, R|/foo|.R|kotlin/String.plus|(R|/bar|), <strcat>(R|/foo|.R|kotlin/Any.toString|(), String( ), R|/bar|.R|kotlin/Any.toString|()), <strcat>(R|/baz|().R|kotlin/Any.toString|(), String( )))) @R|Ann2|(<implicitArrayOf>(R|/bar|, R|/baz|(), R|/bar|.R|kotlin/Int.plus|(R|/cnst|))) @R|Ann3|(R|/arr|) public final fun test(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
enum class TestEnum {
|
||||||
|
Foo
|
||||||
|
}
|
||||||
|
|
||||||
|
annotation class Ann(vararg val a: TestEnum)
|
||||||
|
|
||||||
|
val foo = TestEnum.Foo
|
||||||
|
var bar = TestEnum.Foo
|
||||||
|
|
||||||
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>foo<!>, <!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>bar<!>)
|
||||||
|
fun test() {}
|
||||||
Vendored
+30
@@ -0,0 +1,30 @@
|
|||||||
|
FILE: annotationArgumentMustBeEnumConst.kt
|
||||||
|
public final enum class TestEnum : R|kotlin/Enum<TestEnum>| {
|
||||||
|
private constructor(): R|TestEnum| {
|
||||||
|
super<R|kotlin/Enum<TestEnum>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static enum entry Foo: R|TestEnum|
|
||||||
|
public final static fun values(): R|kotlin/Array<TestEnum>| {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static fun valueOf(value: R|kotlin/String|): R|TestEnum| {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final annotation class Ann : R|kotlin/Annotation| {
|
||||||
|
public constructor(vararg a: R|kotlin/Array<out TestEnum>|): R|Ann| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<out TestEnum>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<out TestEnum>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val foo: R|TestEnum| = Q|TestEnum|.R|/TestEnum.Foo|
|
||||||
|
public get(): R|TestEnum|
|
||||||
|
public final var bar: R|TestEnum| = Q|TestEnum|.R|/TestEnum.Foo|
|
||||||
|
public get(): R|TestEnum|
|
||||||
|
public set(value: R|TestEnum|): R|kotlin/Unit|
|
||||||
|
@R|Ann|(vararg(R|/foo|, R|/bar|)) public final fun test(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
Vendored
+24
@@ -0,0 +1,24 @@
|
|||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Repeatable
|
||||||
|
annotation class Ann(val a: Array<KClass<*>>)
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
val foo = Foo::class
|
||||||
|
fun bar() = Foo::class
|
||||||
|
|
||||||
|
@Ann(
|
||||||
|
[
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>""::class<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>true::class<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>1::class<!>
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@Ann(
|
||||||
|
[
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>foo<!>,
|
||||||
|
<!ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL!>bar()<!>
|
||||||
|
]
|
||||||
|
)
|
||||||
|
fun test1() {}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
FILE: annotationArgumentMustBeKClassLiteral.kt
|
||||||
|
@R|kotlin/annotation/Repeatable|() public final annotation class Ann : R|kotlin/Annotation| {
|
||||||
|
public constructor(a: R|kotlin/Array<kotlin/reflect/KClass<*>>|): R|Ann| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<kotlin/reflect/KClass<*>>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<kotlin/reflect/KClass<*>>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Foo : R|kotlin/Any| {
|
||||||
|
public constructor(): R|Foo| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val foo: R|kotlin/reflect/KClass<Foo>| = <getClass>(Q|Foo|)
|
||||||
|
public get(): R|kotlin/reflect/KClass<Foo>|
|
||||||
|
public final fun bar(): R|kotlin/reflect/KClass<Foo>| {
|
||||||
|
^bar <getClass>(Q|Foo|)
|
||||||
|
}
|
||||||
|
@R|Ann|(<implicitArrayOf>(<getClass>(String()), <getClass>(Boolean(true)), <getClass>(Int(1)))) @R|Ann|(<implicitArrayOf>(R|/foo|, R|/bar|())) public final fun test1(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
annotation class Ann(val a: Array<String>)
|
||||||
|
|
||||||
|
val foo = ""
|
||||||
|
var bar = 1
|
||||||
|
const val cnst = 2
|
||||||
|
|
||||||
|
@Ann(
|
||||||
|
<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(
|
||||||
|
<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>foo<!>,
|
||||||
|
<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>foo + cnst.toString()<!>
|
||||||
|
)<!>
|
||||||
|
)
|
||||||
|
fun test() {}
|
||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
FILE: nonConstValInAnnotationArgument.kt
|
||||||
|
public final annotation class Ann : R|kotlin/Annotation| {
|
||||||
|
public constructor(a: R|kotlin/Array<kotlin/String>|): R|Ann| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final val a: R|kotlin/Array<kotlin/String>| = R|<local>/a|
|
||||||
|
public get(): R|kotlin/Array<kotlin/String>|
|
||||||
|
|
||||||
|
}
|
||||||
|
public final val foo: R|kotlin/String| = String()
|
||||||
|
public get(): R|kotlin/String|
|
||||||
|
public final var bar: R|kotlin/Int| = Int(1)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||||
|
public final const val cnst: R|kotlin/Int| = Int(2)
|
||||||
|
public get(): R|kotlin/Int|
|
||||||
|
@R|Ann|(<implicitArrayOf>(R|/foo|, R|/foo|.R|kotlin/String.plus|(R|/cnst|.R|kotlin/Any.toString|()))) public final fun test(): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
Generated
+25
@@ -916,6 +916,26 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentKClassLiteralTypeError.kt")
|
||||||
|
public void testAnnotationArgumentKClassLiteralTypeError() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeConst.kt")
|
||||||
|
public void testAnnotationArgumentMustBeConst() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeEnumConst.kt")
|
||||||
|
public void testAnnotationArgumentMustBeEnumConst() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeKClassLiteral.kt")
|
||||||
|
public void testAnnotationArgumentMustBeKClassLiteral() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotationClassMember.kt")
|
@TestMetadata("annotationClassMember.kt")
|
||||||
public void testAnnotationClassMember() throws Exception {
|
public void testAnnotationClassMember() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
|
||||||
@@ -1011,6 +1031,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
||||||
|
public void testNonConstValInAnnotationArgument() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("notASupertype.kt")
|
@TestMetadata("notASupertype.kt")
|
||||||
public void testNotASupertype() throws Exception {
|
public void testNotASupertype() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
||||||
|
|||||||
+25
@@ -916,6 +916,26 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentKClassLiteralTypeError.kt")
|
||||||
|
public void testAnnotationArgumentKClassLiteralTypeError() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeConst.kt")
|
||||||
|
public void testAnnotationArgumentMustBeConst() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeEnumConst.kt")
|
||||||
|
public void testAnnotationArgumentMustBeEnumConst() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotationArgumentMustBeKClassLiteral.kt")
|
||||||
|
public void testAnnotationArgumentMustBeKClassLiteral() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotationClassMember.kt")
|
@TestMetadata("annotationClassMember.kt")
|
||||||
public void testAnnotationClassMember() throws Exception {
|
public void testAnnotationClassMember() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationClassMember.kt");
|
||||||
@@ -1011,6 +1031,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/methodOfAnyImplementedInInterface.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonConstValInAnnotationArgument.kt")
|
||||||
|
public void testNonConstValInAnnotationArgument() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("notASupertype.kt")
|
@TestMetadata("notASupertype.kt")
|
||||||
public void testNotASupertype() throws Exception {
|
public void testNotASupertype() throws Exception {
|
||||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
||||||
|
|||||||
+245
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions.PLUS
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_OPERATION_NAMES
|
||||||
|
|
||||||
|
object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration !is FirAnnotationContainer) return
|
||||||
|
for (declarationOfAnnotation in declaration.annotations) {
|
||||||
|
for ((arg, _) in declarationOfAnnotation.argumentMapping ?: continue) {
|
||||||
|
val expression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
||||||
|
|
||||||
|
checkAnnotationArgumentWithSubElements(expression, context.session, reporter)
|
||||||
|
?.let { reporter.report(getFirSourceElement(expression), it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAnnotationArgumentWithSubElements(
|
||||||
|
expression: FirExpression,
|
||||||
|
session: FirSession,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
): FirDiagnosticFactory0<FirSourceElement, KtExpression>? {
|
||||||
|
when (expression) {
|
||||||
|
is FirArrayOfCall -> {
|
||||||
|
var usedNonConst = false
|
||||||
|
|
||||||
|
for (arg in expression.argumentList.arguments) {
|
||||||
|
val sourceForReport = getFirSourceElement(arg)
|
||||||
|
|
||||||
|
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter)) {
|
||||||
|
null -> {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if (err != FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL) usedNonConst = true
|
||||||
|
reporter.report(sourceForReport, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedNonConst) return FirErrors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION
|
||||||
|
}
|
||||||
|
is FirVarargArgumentsExpression -> {
|
||||||
|
for (arg in expression.arguments)
|
||||||
|
checkAnnotationArgumentWithSubElements(arg, session, reporter)
|
||||||
|
?.let { reporter.report(getFirSourceElement(arg), it) }
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
return checkAnnotationArgument(expression, session)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAnnotationArgument(
|
||||||
|
expression: FirExpression,
|
||||||
|
session: FirSession,
|
||||||
|
): FirDiagnosticFactory0<FirSourceElement, KtExpression>? {
|
||||||
|
val expressionSymbol = expression.toResolvedCallableSymbol()
|
||||||
|
?.fir
|
||||||
|
val classKindOfParent = (expressionSymbol
|
||||||
|
?.getReferencedClass(session) as? FirRegularClass)
|
||||||
|
?.classKind
|
||||||
|
|
||||||
|
when {
|
||||||
|
expression is FirConstExpression<*>
|
||||||
|
|| expressionSymbol is FirEnumEntry
|
||||||
|
|| (expressionSymbol as? FirMemberDeclaration)?.isConst == true
|
||||||
|
|| expressionSymbol is FirConstructor && classKindOfParent == ClassKind.ANNOTATION_CLASS -> {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
classKindOfParent == ClassKind.ENUM_CLASS -> {
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
||||||
|
}
|
||||||
|
expression is FirComparisonExpression -> {
|
||||||
|
return checkAnnotationArgument(expression.compareToCall, session)
|
||||||
|
}
|
||||||
|
expression is FirIntegerOperatorCall -> {
|
||||||
|
for (exp in (expression as FirCall).arguments.plus(expression.dispatchReceiver))
|
||||||
|
checkAnnotationArgument(exp, session).let { return it }
|
||||||
|
}
|
||||||
|
expression is FirStringConcatenationCall || expression is FirEqualityOperatorCall -> {
|
||||||
|
for (exp in (expression as FirCall).arguments)
|
||||||
|
checkAnnotationArgument(exp, session).let { return it }
|
||||||
|
}
|
||||||
|
(expression is FirGetClassCall) -> {
|
||||||
|
var coneType = (expression as? FirCall)
|
||||||
|
?.argument
|
||||||
|
?.typeRef
|
||||||
|
?.coneType
|
||||||
|
|
||||||
|
if (coneType is ConeClassErrorType)
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
|
||||||
|
while (coneType?.classId == StandardClassIds.Array)
|
||||||
|
coneType = (coneType.lowerBoundIfFlexible().typeArguments.first() as? ConeKotlinTypeProjection)?.type ?: break
|
||||||
|
|
||||||
|
return when {
|
||||||
|
coneType is ConeTypeParameterType ->
|
||||||
|
FirErrors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR
|
||||||
|
(expression as FirCall).argument !is FirResolvedQualifier ->
|
||||||
|
FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||||
|
else ->
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expressionSymbol == null -> {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
expressionSymbol is FirField -> {
|
||||||
|
//TODO: fix checking of Java fields initializer
|
||||||
|
if (
|
||||||
|
!(expressionSymbol as FirMemberDeclaration).status.isStatic
|
||||||
|
|| (expressionSymbol as FirMemberDeclaration).status.modality != Modality.FINAL
|
||||||
|
)
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
}
|
||||||
|
expression is FirFunctionCall -> {
|
||||||
|
val calleeReference = expression.calleeReference
|
||||||
|
if (calleeReference is FirErrorNamedReference)
|
||||||
|
return null
|
||||||
|
if (expression.typeRef.coneType.classId == StandardClassIds.KClass)
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||||
|
|
||||||
|
//TODO: UNRESOLVED REFERENCE
|
||||||
|
if (expression.dispatchReceiver is FirThisReceiverExpression)
|
||||||
|
return null
|
||||||
|
|
||||||
|
when (calleeReference.name) {
|
||||||
|
TO_STRING ->
|
||||||
|
return checkAnnotationArgument(expression.dispatchReceiver, session)
|
||||||
|
in BINARY_OPERATION_NAMES, in UNARY_OPERATION_NAMES -> {
|
||||||
|
val receiverClassId = expression.dispatchReceiver.typeRef.coneType.classId
|
||||||
|
|
||||||
|
for (exp in (expression as FirCall).arguments.plus(expression.dispatchReceiver)) {
|
||||||
|
val expClassId = exp.typeRef.coneType.classId
|
||||||
|
|
||||||
|
if (calleeReference.name == PLUS
|
||||||
|
&& expClassId != receiverClassId
|
||||||
|
&& (expClassId !in StandardClassIds.primitiveTypes || receiverClassId !in StandardClassIds.primitiveTypes)
|
||||||
|
)
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
|
||||||
|
checkAnnotationArgument(exp, session)?.let { return it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expression is FirQualifiedAccessExpression -> {
|
||||||
|
|
||||||
|
when {
|
||||||
|
(expressionSymbol as FirProperty).isLocal || expressionSymbol.symbol.callableId.className?.isRoot == false ->
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
expression.typeRef.coneType.classId == StandardClassIds.KClass ->
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||||
|
|
||||||
|
//TODO: UNRESOLVED REFERENCE
|
||||||
|
expression.dispatchReceiver is FirThisReceiverExpression ->
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return when ((expressionSymbol as? FirProperty)?.initializer) {
|
||||||
|
is FirConstExpression<*> -> {
|
||||||
|
if ((expressionSymbol as? FirVariable)?.isVal == true)
|
||||||
|
FirErrors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION
|
||||||
|
else
|
||||||
|
FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
}
|
||||||
|
is FirGetClassCall ->
|
||||||
|
FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||||
|
else ->
|
||||||
|
FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirTypedDeclaration?.getReferencedClass(session: FirSession): FirSymbolOwner<*>? =
|
||||||
|
this?.returnTypeRef
|
||||||
|
?.coneTypeSafe<ConeLookupTagBasedType>()
|
||||||
|
?.lookupTag
|
||||||
|
?.toSymbol(session)
|
||||||
|
?.fir
|
||||||
|
|
||||||
|
private fun getFirSourceElement(expression: FirExpression): FirSourceElement? =
|
||||||
|
when {
|
||||||
|
expression is FirFunctionCall && expression.calleeReference.name == TO_STRING ->
|
||||||
|
getParentOfFirSourceElement(getParentOfFirSourceElement(expression.source))
|
||||||
|
expression is FirFunctionCall ->
|
||||||
|
expression.source
|
||||||
|
(expression as? FirQualifiedAccess)?.explicitReceiver != null ->
|
||||||
|
getParentOfFirSourceElement(expression.source)
|
||||||
|
else ->
|
||||||
|
expression.source
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getParentOfFirSourceElement(source: FirSourceElement?): FirSourceElement? =
|
||||||
|
when (source) {
|
||||||
|
is FirPsiSourceElement<*> ->
|
||||||
|
source.psi.parent.toFirPsiSourceElement()
|
||||||
|
is FirLightSourceElement -> {
|
||||||
|
val elementOfParent = source.tree.getParent(source.element)
|
||||||
|
?: source.element
|
||||||
|
|
||||||
|
elementOfParent.toFirLightSourceElement(elementOfParent.startOffset, elementOfParent.endOffset, source.tree)
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
source
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
|
||||||
|
source: T?,
|
||||||
|
factory: FirDiagnosticFactory0<T, P>
|
||||||
|
) {
|
||||||
|
source?.let { report(factory.on(it)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-3
@@ -80,14 +80,19 @@ object FirErrors {
|
|||||||
val SEALED_CLASS_CONSTRUCTOR_CALL by error0<FirSourceElement, PsiElement>()
|
val SEALED_CLASS_CONSTRUCTOR_CALL by error0<FirSourceElement, PsiElement>()
|
||||||
|
|
||||||
// Annotations
|
// Annotations
|
||||||
|
val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR)
|
||||||
|
val ANNOTATION_ARGUMENT_MUST_BE_CONST by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST)
|
||||||
|
val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST)
|
||||||
|
val ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL)
|
||||||
val ANNOTATION_CLASS_MEMBER by existing<FirSourceElement, PsiElement>(Errors.ANNOTATION_CLASS_MEMBER)
|
val ANNOTATION_CLASS_MEMBER by existing<FirSourceElement, PsiElement>(Errors.ANNOTATION_CLASS_MEMBER)
|
||||||
val ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT)
|
val ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT)
|
||||||
|
val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER)
|
||||||
val LOCAL_ANNOTATION_CLASS_ERROR by existing<FirSourceElement, KtClassOrObject>(Errors.LOCAL_ANNOTATION_CLASS_ERROR)
|
val LOCAL_ANNOTATION_CLASS_ERROR by existing<FirSourceElement, KtClassOrObject>(Errors.LOCAL_ANNOTATION_CLASS_ERROR)
|
||||||
val MISSING_VAL_ON_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
|
val MISSING_VAL_ON_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
|
||||||
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER)
|
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by existing<FirSourceElement, KtExpression>(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION)
|
||||||
val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER)
|
|
||||||
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER)
|
|
||||||
val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>()
|
val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>()
|
||||||
|
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER)
|
||||||
|
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER)
|
||||||
|
|
||||||
// Exposed visibility group
|
// Exposed visibility group
|
||||||
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
||||||
|
|||||||
+1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
|||||||
|
|
||||||
object CommonDeclarationCheckers : DeclarationCheckers() {
|
object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = setOf(
|
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = setOf(
|
||||||
|
FirAnnotationArgumentChecker,
|
||||||
FirAnnotationClassDeclarationChecker,
|
FirAnnotationClassDeclarationChecker,
|
||||||
FirModifierChecker,
|
FirModifierChecker,
|
||||||
FirManyCompanionObjectsChecker,
|
FirManyCompanionObjectsChecker,
|
||||||
|
|||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
// Functions can be recursively annotated
|
|
||||||
annotation class ann(val x: Int)
|
|
||||||
@ann(bar()) fun foo() = 1
|
|
||||||
@ann(foo()) fun bar() = 2
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// Functions can be recursively annotated
|
// Functions can be recursively annotated
|
||||||
annotation class ann(val x: Int)
|
annotation class ann(val x: Int)
|
||||||
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bar()<!>) fun foo() = 1
|
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bar()<!>) fun foo() = 1
|
||||||
|
|||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
// Function parameter CAN be recursively annotated
|
|
||||||
annotation class ann(val x: Int)
|
|
||||||
fun foo(@ann(foo(1)) x: Int): Int = x
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// Function parameter CAN be recursively annotated
|
// Function parameter CAN be recursively annotated
|
||||||
annotation class ann(val x: Int)
|
annotation class ann(val x: Int)
|
||||||
fun foo(@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo(1)<!>) x: Int): Int = x
|
fun foo(@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo(1)<!>) x: Int): Int = x
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
// Functions can be recursively annotated
|
|
||||||
annotation class ann(val x: Int)
|
|
||||||
@ann(foo()) fun foo() = 1
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// Functions can be recursively annotated
|
// Functions can be recursively annotated
|
||||||
annotation class ann(val x: Int)
|
annotation class ann(val x: Int)
|
||||||
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo()<!>) fun foo() = 1
|
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo()<!>) fun foo() = 1
|
||||||
-5
@@ -1,5 +0,0 @@
|
|||||||
// Properties can be recursively annotated
|
|
||||||
annotation class ann(val x: Int)
|
|
||||||
class My {
|
|
||||||
@ann(x) val x: Int = 1
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// Properties can be recursively annotated
|
// Properties can be recursively annotated
|
||||||
annotation class ann(val x: Int)
|
annotation class ann(val x: Int)
|
||||||
class My {
|
class My {
|
||||||
|
|||||||
+1
-1
@@ -2,5 +2,5 @@ annotation class Ann(vararg val i: Boolean)
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
val bool1 = true
|
val bool1 = true
|
||||||
|
|
||||||
@Ann(bool1) val a = bool1
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bool1<!>) val a = bool1
|
||||||
}
|
}
|
||||||
-16
@@ -1,16 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
|
||||||
annotation class Ann(vararg val i: Boolean)
|
|
||||||
fun foo() {
|
|
||||||
val a1 = 1 > 2
|
|
||||||
val a2 = 1 == 2
|
|
||||||
val a3 = a1 == a2
|
|
||||||
val a4 = a1 > a2
|
|
||||||
|
|
||||||
@Ann(
|
|
||||||
a1,
|
|
||||||
a2,
|
|
||||||
a3,
|
|
||||||
a1 > a2,
|
|
||||||
a1 == a2
|
|
||||||
) val b = 1
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||||
annotation class Ann(vararg val i: Boolean)
|
annotation class Ann(vararg val i: Boolean)
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
annotation class AnnE(val i: MyEnum)
|
annotation class AnnE(val i: MyEnum)
|
||||||
|
|
||||||
@AnnE(e)
|
@AnnE(<!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>e<!>)
|
||||||
class Test
|
class Test
|
||||||
|
|
||||||
val e: MyEnum = MyEnum.A
|
val e: MyEnum = MyEnum.A
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
annotation class AnnE(val i: MyEnum)
|
annotation class AnnE(val i: MyEnum)
|
||||||
|
|
||||||
@AnnE(e)
|
@AnnE(<!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>e<!>)
|
||||||
class Test
|
class Test
|
||||||
|
|
||||||
val e: MyEnum = MyEnum.A
|
val e: MyEnum = MyEnum.A
|
||||||
|
|||||||
+4
-4
@@ -14,12 +14,12 @@ public class Test {
|
|||||||
annotation class Ann(vararg val i: Int)
|
annotation class Ann(vararg val i: Int)
|
||||||
|
|
||||||
@Ann(
|
@Ann(
|
||||||
Test.i1,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i1<!>,
|
||||||
Test.i2,
|
Test.i2,
|
||||||
Test.i3,
|
Test.i3,
|
||||||
Test.i4,
|
Test.i4,
|
||||||
Test.i5,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i5<!>,
|
||||||
Test.i6,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i6<!>,
|
||||||
Test().i7
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test().i7<!>
|
||||||
)
|
)
|
||||||
class A
|
class A
|
||||||
|
|||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
annotation class Ann(vararg val i: Int)
|
|
||||||
|
|
||||||
@Ann(
|
|
||||||
i1,
|
|
||||||
i2,
|
|
||||||
i3,
|
|
||||||
i4,
|
|
||||||
i5,
|
|
||||||
i6
|
|
||||||
)
|
|
||||||
class Test
|
|
||||||
|
|
||||||
var i1 = 1 // var
|
|
||||||
const val i2 = 1 // val
|
|
||||||
val i3 = i1 // val with var in initializer
|
|
||||||
const val i4 = i2 // val with val in initializer
|
|
||||||
var i5 = i1 // var with var in initializer
|
|
||||||
var i6 = i2 // var with val in initializer
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
annotation class Ann(vararg val i: Int)
|
annotation class Ann(vararg val i: Int)
|
||||||
|
|
||||||
@Ann(
|
@Ann(
|
||||||
|
|||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
annotation class AnnE(val i: String)
|
|
||||||
|
|
||||||
enum class MyEnum {
|
|
||||||
A
|
|
||||||
}
|
|
||||||
|
|
||||||
@AnnE("1" + MyEnum.A)
|
|
||||||
class Test
|
|
||||||
|
|
||||||
@AnnE("1" + MyEnum::class)
|
|
||||||
class Test2
|
|
||||||
|
|
||||||
@AnnE("1" + AnnE("23"))
|
|
||||||
class Test3
|
|
||||||
|
|
||||||
@AnnE("1" + arrayOf("23", "34"))
|
|
||||||
class Test4
|
|
||||||
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
annotation class AnnE(val i: String)
|
annotation class AnnE(val i: String)
|
||||||
|
|
||||||
enum class MyEnum {
|
enum class MyEnum {
|
||||||
|
|||||||
Vendored
-28
@@ -1,28 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
|
||||||
annotation class Ann(vararg val i: String)
|
|
||||||
|
|
||||||
const val topLevel = "topLevel"
|
|
||||||
|
|
||||||
fun foo() {
|
|
||||||
val a1 = "a"
|
|
||||||
val a2 = "b"
|
|
||||||
val a3 = a1 + a2
|
|
||||||
|
|
||||||
val a4 = 1
|
|
||||||
val a5 = 1.0
|
|
||||||
|
|
||||||
@Ann(
|
|
||||||
a1,
|
|
||||||
a2,
|
|
||||||
a3,
|
|
||||||
"$topLevel",
|
|
||||||
"$a1",
|
|
||||||
"$a1 $topLevel",
|
|
||||||
"$a4",
|
|
||||||
"$a5",
|
|
||||||
a1 + a2,
|
|
||||||
"a" + a2,
|
|
||||||
"a" + topLevel,
|
|
||||||
"a" + a4
|
|
||||||
) val b = 1
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||||
annotation class Ann(vararg val i: String)
|
annotation class Ann(vararg val i: String)
|
||||||
|
|
||||||
|
|||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
// !LANGUAGE: +ProhibitTypeParametersInClassLiteralsInAnnotationArguments
|
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
annotation class Ann(val k: KClass<*>)
|
|
||||||
annotation class AnnArray(val kk: Array<KClass<*>>)
|
|
||||||
|
|
||||||
object AnObject
|
|
||||||
|
|
||||||
class C {
|
|
||||||
companion object
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo() = "foo"
|
|
||||||
|
|
||||||
@Ann("foo"::class)
|
|
||||||
fun test1() {}
|
|
||||||
|
|
||||||
@Ann(String::class)
|
|
||||||
fun test2() {}
|
|
||||||
|
|
||||||
@Ann(AnObject::class)
|
|
||||||
fun test4() {}
|
|
||||||
|
|
||||||
@Ann(C::class)
|
|
||||||
fun test5() {}
|
|
||||||
|
|
||||||
@Ann(C.Companion::class)
|
|
||||||
fun test6() {}
|
|
||||||
|
|
||||||
@Ann(foo()::class)
|
|
||||||
fun test7() {}
|
|
||||||
|
|
||||||
@AnnArray(arrayOf(""::class, String::class, AnObject::class))
|
|
||||||
fun test8() {}
|
|
||||||
|
|
||||||
inline val <reified T> T.test9
|
|
||||||
get() = @AnnArray(arrayOf(
|
|
||||||
T::class,
|
|
||||||
Array<T>::class,
|
|
||||||
Array<Array<Array<T>>>::class
|
|
||||||
)) object {}
|
|
||||||
|
|
||||||
inline val <reified T> T.test10
|
|
||||||
get() = @AnnArray([T::class]) object {}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +ProhibitTypeParametersInClassLiteralsInAnnotationArguments
|
// !LANGUAGE: +ProhibitTypeParametersInClassLiteralsInAnnotationArguments
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|||||||
+3
-3
@@ -6,7 +6,7 @@ annotation class Ann(vararg val k: KClass<*>)
|
|||||||
|
|
||||||
inline val <reified T> T.test
|
inline val <reified T> T.test
|
||||||
get() = @Ann(
|
get() = @Ann(
|
||||||
T::class,
|
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>T::class<!>,
|
||||||
Array<T>::class,
|
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>Array<T>::class<!>,
|
||||||
Array<Array<Array<T>>>::class
|
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>Array<Array<Array<T>>>::class<!>
|
||||||
) object {}
|
) object {}
|
||||||
|
|||||||
+2
-2
@@ -24,8 +24,8 @@ val two = 2
|
|||||||
@Foo([ONE], [], [])
|
@Foo([ONE], [], [])
|
||||||
fun test6() {}
|
fun test6() {}
|
||||||
|
|
||||||
@Foo([ONE + two], [], [])
|
@Foo(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>ONE + two<!>]<!>, [], [])
|
||||||
fun test7() {}
|
fun test7() {}
|
||||||
|
|
||||||
@Foo([two], [], [])
|
@Foo(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>two<!>]<!>, [], [])
|
||||||
fun test8() {}
|
fun test8() {}
|
||||||
@@ -22,5 +22,5 @@ fun main1() {}
|
|||||||
fun main2() {}
|
fun main2() {}
|
||||||
|
|
||||||
val q = A()
|
val q = A()
|
||||||
@Ann(q.z)
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>q.z<!>)
|
||||||
fun main3() {}
|
fun main3() {}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ annotation class Ann(
|
|||||||
Companion.CONST,
|
Companion.CONST,
|
||||||
Nested.CONST,
|
Nested.CONST,
|
||||||
Interface.CONST,
|
Interface.CONST,
|
||||||
a,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||||
b()
|
b()
|
||||||
)
|
)
|
||||||
class A {
|
class A {
|
||||||
|
|||||||
+2
-2
@@ -23,7 +23,7 @@ class A
|
|||||||
Companion.CONST,
|
Companion.CONST,
|
||||||
Nested.CONST,
|
Nested.CONST,
|
||||||
Interface.CONST,
|
Interface.CONST,
|
||||||
a,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||||
b()
|
b()
|
||||||
)
|
)
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -36,7 +36,7 @@ constructor() {
|
|||||||
Companion.CONST,
|
Companion.CONST,
|
||||||
Nested.CONST,
|
Nested.CONST,
|
||||||
Interface.CONST,
|
Interface.CONST,
|
||||||
a,
|
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||||
b()
|
b()
|
||||||
)
|
)
|
||||||
constructor(dummy: Int) : this()
|
constructor(dummy: Int) : this()
|
||||||
|
|||||||
+4
-4
@@ -2,10 +2,10 @@
|
|||||||
@Repeatable
|
@Repeatable
|
||||||
annotation class Ann(val i: IntArray)
|
annotation class Ann(val i: IntArray)
|
||||||
|
|
||||||
@Ann(intArrayOf(i))
|
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>)<!>)
|
||||||
@Ann(intArrayOf(i2))
|
@Ann(intArrayOf(i2))
|
||||||
@Ann(intArrayOf(i3))
|
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)<!>)
|
||||||
@Ann(intArrayOf(i, i2, i3))
|
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>, i2, <!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)<!>)
|
||||||
@Ann(<!INAPPLICABLE_CANDIDATE!>intArrayOf<!>(intArrayOf(i, i2, i3)))
|
@Ann(<!INAPPLICABLE_CANDIDATE!>intArrayOf<!>(intArrayOf(i, i2, i3)))
|
||||||
class Test
|
class Test
|
||||||
|
|
||||||
@@ -19,6 +19,6 @@ fun foo(): Int = 1
|
|||||||
@Repeatable
|
@Repeatable
|
||||||
annotation class AnnAnn(val i: Array<Ann>)
|
annotation class AnnAnn(val i: Array<Ann>)
|
||||||
@AnnAnn(arrayOf(Ann(intArrayOf(1))))
|
@AnnAnn(arrayOf(Ann(intArrayOf(1))))
|
||||||
@AnnAnn(arrayOf(iAnn))
|
@AnnAnn(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>arrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>iAnn<!>)<!>)
|
||||||
class TestAnn
|
class TestAnn
|
||||||
val iAnn = Ann(intArrayOf(1))
|
val iAnn = Ann(intArrayOf(1))
|
||||||
|
|||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
@Retention(AnnotationRetention.SOURCE)
|
|
||||||
@Repeatable
|
|
||||||
annotation class Ann(val i: Int)
|
|
||||||
annotation class AnnIA(val ia: IntArray)
|
|
||||||
annotation class AnnSA(val sa: Array<String>)
|
|
||||||
|
|
||||||
@Ann(MyClass().i)
|
|
||||||
@Ann(i)
|
|
||||||
@Ann(i2)
|
|
||||||
@AnnIA(ia)
|
|
||||||
@AnnSA(sa)
|
|
||||||
class Test {
|
|
||||||
val i = 1
|
|
||||||
@Ann(i) val i2 = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 1
|
|
||||||
val i2 = foo()
|
|
||||||
|
|
||||||
fun foo(): Int = 1
|
|
||||||
|
|
||||||
@AnnSA(emptyArray())
|
|
||||||
class MyClass {
|
|
||||||
val i = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
val ia: IntArray = intArrayOf(1, 2)
|
|
||||||
val sa: Array<String> = arrayOf("a", "b")
|
|
||||||
|
|
||||||
annotation class Ann2
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
@Repeatable
|
@Repeatable
|
||||||
annotation class Ann(val i: Int)
|
annotation class Ann(val i: Int)
|
||||||
|
|||||||
+3
-3
@@ -4,13 +4,13 @@ const val constConst = nonConst * nonConst + 2
|
|||||||
|
|
||||||
annotation class Ann(val x: Int, val y: String)
|
annotation class Ann(val x: Int, val y: String)
|
||||||
|
|
||||||
@Ann(nonConst, "${nonConst}")
|
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst<!>, <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>"${nonConst}"<!>)
|
||||||
fun foo1() {}
|
fun foo1() {}
|
||||||
|
|
||||||
@Ann(nonConst + constConst, "${constConst}")
|
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst + constConst<!>, "${constConst}")
|
||||||
fun foo2() {}
|
fun foo2() {}
|
||||||
|
|
||||||
annotation class ArrayAnn(val x: IntArray)
|
annotation class ArrayAnn(val x: IntArray)
|
||||||
|
|
||||||
@ArrayAnn(intArrayOf(1, constConst, nonConst))
|
@ArrayAnn(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(1, constConst, <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst<!>)<!>)
|
||||||
fun foo3() {}
|
fun foo3() {}
|
||||||
|
|||||||
+3
-3
@@ -2,10 +2,10 @@
|
|||||||
@Repeatable
|
@Repeatable
|
||||||
annotation class Ann(vararg val i: Int)
|
annotation class Ann(vararg val i: Int)
|
||||||
|
|
||||||
@Ann(i)
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>)
|
||||||
@Ann(i2)
|
@Ann(i2)
|
||||||
@Ann(i3)
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||||
@Ann(i, i2, i3)
|
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>, i2, <!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||||
@Ann(*intArrayOf(i))
|
@Ann(*intArrayOf(i))
|
||||||
@Ann(*intArrayOf(i2))
|
@Ann(*intArrayOf(i2))
|
||||||
@Ann(*intArrayOf(i3))
|
@Ann(*intArrayOf(i3))
|
||||||
|
|||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
annotation class Ann1(val arg: KClass<*>)
|
|
||||||
annotation class Ann2(vararg val arg: KClass<*>)
|
|
||||||
annotation class Ann3(val arg: Array<KClass<*>>)
|
|
||||||
|
|
||||||
class A1
|
|
||||||
class A2
|
|
||||||
|
|
||||||
@Ann1(A1::class)
|
|
||||||
@Ann2(A1::class, A2::class)
|
|
||||||
@Ann3(arrayOf(A1::class, A2::class))
|
|
||||||
class MyClass1
|
|
||||||
|
|
||||||
@Ann1(<!UNRESOLVED_REFERENCE!>A3<!>::class)
|
|
||||||
class MyClass2
|
|
||||||
|
|
||||||
val x = A1::class
|
|
||||||
@Ann1(x)
|
|
||||||
class MyClass3
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
annotation class Ann1(val arg: KClass<*>)
|
annotation class Ann1(val arg: KClass<*>)
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ object OperatorNameConventions {
|
|||||||
@JvmField val NEXT = Name.identifier("next")
|
@JvmField val NEXT = Name.identifier("next")
|
||||||
@JvmField val HAS_NEXT = Name.identifier("hasNext")
|
@JvmField val HAS_NEXT = Name.identifier("hasNext")
|
||||||
|
|
||||||
|
@JvmField val TO_STRING = Name.identifier("toString")
|
||||||
|
|
||||||
@JvmField val COMPONENT_REGEX = Regex("component\\d+")
|
@JvmField val COMPONENT_REGEX = Regex("component\\d+")
|
||||||
|
|
||||||
@JvmField val AND = Name.identifier("and")
|
@JvmField val AND = Name.identifier("and")
|
||||||
|
|||||||
Reference in New Issue
Block a user