From cfc1ebb4beca960eb28133cca31c5c4be428aeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B8=D1=85=D0=BE=D0=BB=D0=B5=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=9C=D0=B8=D1=85=D0=B0=D0=B8=D0=BB?= Date: Sun, 13 Sep 2020 15:44:09 +0300 Subject: [PATCH] [FIR] Support several annotation argument diagnostics --- ...nnotationArgumentKClassLiteralTypeError.kt | 12 + ...notationArgumentKClassLiteralTypeError.txt | 20 ++ .../annotationArgumentMustBeConst.kt | 31 +++ .../annotationArgumentMustBeConst.txt | 54 ++++ .../annotationArgumentMustBeEnumConst.kt | 11 + .../annotationArgumentMustBeEnumConst.txt | 30 +++ .../annotationArgumentMustBeKClassLiteral.kt | 24 ++ .../annotationArgumentMustBeKClassLiteral.txt | 23 ++ .../nonConstValInAnnotationArgument.kt | 13 + .../nonConstValInAnnotationArgument.txt | 19 ++ .../fir/FirDiagnosticsTestGenerated.java | 25 ++ ...DiagnosticsWithLightTreeTestGenerated.java | 25 ++ .../FirAnnotationArgumentChecker.kt | 245 ++++++++++++++++++ .../fir/analysis/diagnostics/FirErrors.kt | 11 +- .../fir/checkers/CommonDeclarationCheckers.kt | 1 + ...yRecursivelyAnnotatedGlobalFunction.fir.kt | 4 - ...uallyRecursivelyAnnotatedGlobalFunction.kt | 1 + ...cursivelyAnnotatedFunctionParameter.fir.kt | 3 - .../RecursivelyAnnotatedFunctionParameter.kt | 1 + .../RecursivelyAnnotatedGlobalFunction.fir.kt | 3 - .../RecursivelyAnnotatedGlobalFunction.kt | 1 + .../RecursivelyAnnotatedProperty.fir.kt | 5 - .../RecursivelyAnnotatedProperty.kt | 1 + .../booleanLocalVal.fir.kt | 2 +- .../compareAndEquals.fir.kt | 16 -- .../compareAndEquals.kt | 1 + .../enumConst_after.fir.kt | 2 +- .../enumConst_before.fir.kt | 2 +- .../javaProperties.fir.kt | 8 +- .../kotlinProperties.fir.kt | 18 -- .../kotlinProperties.kt | 1 + .../standaloneInExpression.fir.kt | 18 -- .../standaloneInExpression.kt | 1 + .../strings.fir.kt | 28 -- .../strings.kt | 1 + .../classLiteral/inAnnotationArguments.fir.kt | 45 ---- .../classLiteral/inAnnotationArguments.kt | 1 + .../inAnnotationArguments_noTypeParams.fir.kt | 6 +- .../argumentsOfAnnotation.fir.kt | 4 +- .../tests/modifiers/const/fromJava.fir.kt | 2 +- .../classHeader/annotationOnClass.fir.kt | 2 +- .../annotationOnConstructors.fir.kt | 4 +- .../array.fir.kt | 8 +- .../simple.fir.kt | 30 --- .../simple.kt | 1 + .../useOfNonConstVal.fir.kt | 6 +- .../vararg.fir.kt | 6 +- .../kClass/kClassInAnnotation.fir.kt | 20 -- .../annotations/kClass/kClassInAnnotation.kt | 1 + .../kotlin/util/OperatorNameConventions.kt | 2 + 50 files changed, 580 insertions(+), 219 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.txt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.fir.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.fir.kt delete mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt new file mode 100644 index 00000000000..40907b25bfa --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.kt @@ -0,0 +1,12 @@ +import kotlin.reflect.KClass + +annotation class Ann(val a: Array>) + + +inline val T.test + get() = @Ann( + arrayOf( + T::class, + Array>>>::class + ) + ) object {} diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.txt new file mode 100644 index 00000000000..fa58d460db5 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentKClassLiteralTypeError.txt @@ -0,0 +1,20 @@ +FILE: annotationArgumentKClassLiteralTypeError.kt + public final annotation class Ann : R|kotlin/Annotation| { + public constructor(a: R|kotlin/Array>|): R|Ann| { + super() + } + + public final val a: R|kotlin/Array>| = R|/a| + public get(): R|kotlin/Array>| + + } + public final val R|T|.test: R|| + public get(): R|| { + ^ @R|Ann|(((R|T|), (Q|kotlin/Array|))) object : R|kotlin/Any| { + private constructor(): R|| { + super() + } + + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt new file mode 100644 index 00000000000..ff628194b16 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.kt @@ -0,0 +1,31 @@ +annotation class Ann1(vararg val a: String) +annotation class Ann2(val a: IntArray) +annotation class Ann3(val a: Array) + +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( + foo, + foo + bar, + "$foo $bar", + "${baz()} " +) +@Ann2( + intArrayOf( + bar, + baz(), + bar + cnst + ) +) +@Ann3(arr) +fun test() {} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.txt new file mode 100644 index 00000000000..10badb64dd3 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeConst.txt @@ -0,0 +1,54 @@ +FILE: annotationArgumentMustBeConst.kt + public final annotation class Ann1 : R|kotlin/Annotation| { + public constructor(vararg a: R|kotlin/Array|): R|Ann1| { + super() + } + + public final val a: R|kotlin/Array| = R|/a| + public get(): R|kotlin/Array| + + } + public final annotation class Ann2 : R|kotlin/Annotation| { + public constructor(a: R|kotlin/IntArray|): R|Ann2| { + super() + } + + public final val a: R|kotlin/IntArray| = R|/a| + public get(): R|kotlin/IntArray| + + } + public final annotation class Ann3 : R|kotlin/Annotation| { + public constructor(a: R|kotlin/Array|): R|Ann3| { + super() + } + + public final val a: R|kotlin/Array| = R|/a| + public get(): R|kotlin/Array| + + } + 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| = R|kotlin/arrayOf|(vararg(String(a), String(b))) + public get(): R|kotlin/Array| + 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() + } + + 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|), (R|/foo|.R|kotlin/Any.toString|(), String( ), R|/bar|.R|kotlin/Any.toString|()), (R|/baz|().R|kotlin/Any.toString|(), String( )))) @R|Ann2|((R|/bar|, R|/baz|(), R|/bar|.R|kotlin/Int.plus|(R|/cnst|))) @R|Ann3|(R|/arr|) public final fun test(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt new file mode 100644 index 00000000000..18506224a43 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.kt @@ -0,0 +1,11 @@ +enum class TestEnum { + Foo +} + +annotation class Ann(vararg val a: TestEnum) + +val foo = TestEnum.Foo +var bar = TestEnum.Foo + +@Ann(foo, bar) +fun test() {} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.txt new file mode 100644 index 00000000000..80b651cce37 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeEnumConst.txt @@ -0,0 +1,30 @@ +FILE: annotationArgumentMustBeEnumConst.kt + public final enum class TestEnum : R|kotlin/Enum| { + private constructor(): R|TestEnum| { + super|>() + } + + public final static enum entry Foo: R|TestEnum| + public final static fun values(): R|kotlin/Array| { + } + + 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|): R|Ann| { + super() + } + + public final val a: R|kotlin/Array| = R|/a| + public get(): R|kotlin/Array| + + } + 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| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt new file mode 100644 index 00000000000..e04ed99f525 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.kt @@ -0,0 +1,24 @@ +import kotlin.reflect.KClass + +@Repeatable +annotation class Ann(val a: Array>) + +class Foo + +val foo = Foo::class +fun bar() = Foo::class + +@Ann( + [ + ""::class, + true::class, + 1::class + ] +) +@Ann( + [ + foo, + bar() + ] +) +fun test1() {} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.txt new file mode 100644 index 00000000000..64d02c7943b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/annotationArgumentMustBeKClassLiteral.txt @@ -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>|): R|Ann| { + super() + } + + public final val a: R|kotlin/Array>| = R|/a| + public get(): R|kotlin/Array>| + + } + public final class Foo : R|kotlin/Any| { + public constructor(): R|Foo| { + super() + } + + } + public final val foo: R|kotlin/reflect/KClass| = (Q|Foo|) + public get(): R|kotlin/reflect/KClass| + public final fun bar(): R|kotlin/reflect/KClass| { + ^bar (Q|Foo|) + } + @R|Ann|(((String()), (Boolean(true)), (Int(1)))) @R|Ann|((R|/foo|, R|/bar|())) public final fun test1(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt new file mode 100644 index 00000000000..ed82693076a --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt @@ -0,0 +1,13 @@ +annotation class Ann(val a: Array) + +val foo = "" +var bar = 1 +const val cnst = 2 + +@Ann( + arrayOf( + foo, + foo + cnst.toString() + ) +) +fun test() {} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.txt new file mode 100644 index 00000000000..fb134019b74 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.txt @@ -0,0 +1,19 @@ +FILE: nonConstValInAnnotationArgument.kt + public final annotation class Ann : R|kotlin/Annotation| { + public constructor(a: R|kotlin/Array|): R|Ann| { + super() + } + + public final val a: R|kotlin/Array| = R|/a| + public get(): R|kotlin/Array| + + } + 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|((R|/foo|, R|/foo|.R|kotlin/String.plus|(R|/cnst|.R|kotlin/Any.toString|()))) public final fun test(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 6b637485446..63378574e3f 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -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); } + @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") public void testAnnotationClassMember() throws Exception { 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"); } + @TestMetadata("nonConstValInAnnotationArgument.kt") + public void testNonConstValInAnnotationArgument() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt"); + } + @TestMetadata("notASupertype.kt") public void testNotASupertype() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 56866a6e745..f559591d863 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -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); } + @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") public void testAnnotationClassMember() throws Exception { 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"); } + @TestMetadata("nonConstValInAnnotationArgument.kt") + public void testNonConstValInAnnotationArgument() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/nonConstValInAnnotationArgument.kt"); + } + @TestMetadata("notASupertype.kt") public void testNotASupertype() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt"); diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt new file mode 100644 index 00000000000..133d09265b6 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt @@ -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? { + 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? { + 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() + ?.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 DiagnosticReporter.report( + source: T?, + factory: FirDiagnosticFactory0 + ) { + source?.let { report(factory.on(it)) } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 45e39f3187e..eabe8e6d156 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -80,14 +80,19 @@ object FirErrors { val SEALED_CLASS_CONSTRUCTOR_CALL by error0() // Annotations + val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by existing(Errors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR) + val ANNOTATION_ARGUMENT_MUST_BE_CONST by existing(Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST) + val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by existing(Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST) + val ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL by existing(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL) val ANNOTATION_CLASS_MEMBER by existing(Errors.ANNOTATION_CLASS_MEMBER) val ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT by existing(Errors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT) + val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER) val LOCAL_ANNOTATION_CLASS_ERROR by existing(Errors.LOCAL_ANNOTATION_CLASS_ERROR) val MISSING_VAL_ON_ANNOTATION_PARAMETER by existing(Errors.MISSING_VAL_ON_ANNOTATION_PARAMETER) - val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER) - val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER) - val VAR_ANNOTATION_PARAMETER by existing(Errors.VAR_ANNOTATION_PARAMETER) + val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by existing(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION) val NOT_AN_ANNOTATION_CLASS by error1() + val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER) + val VAR_ANNOTATION_PARAMETER by existing(Errors.VAR_ANNOTATION_PARAMETER) // Exposed visibility group val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3() diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt index 51f3fe69164..dd5aab40c41 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonDeclarationCheckers.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* object CommonDeclarationCheckers : DeclarationCheckers() { override val basicDeclarationCheckers: Set = setOf( + FirAnnotationArgumentChecker, FirAnnotationClassDeclarationChecker, FirModifierChecker, FirManyCompanionObjectsChecker, diff --git a/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.fir.kt b/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.fir.kt deleted file mode 100644 index 6ea315c899a..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.fir.kt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.kt b/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.kt index 5de3c6691ba..3a877de7fbe 100644 --- a/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.kt +++ b/compiler/testData/diagnostics/tests/annotations/MutuallyRecursivelyAnnotatedGlobalFunction.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // Functions can be recursively annotated annotation class ann(val x: Int) @ann(bar()) fun foo() = 1 diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.fir.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.fir.kt deleted file mode 100644 index 1319481c187..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.fir.kt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.kt index ee6020f9fe6..5882f54d9c3 100644 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.kt +++ b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedFunctionParameter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // Function parameter CAN be recursively annotated annotation class ann(val x: Int) fun foo(@ann(foo(1)) x: Int): Int = x \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.fir.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.fir.kt deleted file mode 100644 index b99a231e627..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -// Functions can be recursively annotated -annotation class ann(val x: Int) -@ann(foo()) fun foo() = 1 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.kt index 2bac172e2b9..75524907d87 100644 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.kt +++ b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedGlobalFunction.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // Functions can be recursively annotated annotation class ann(val x: Int) @ann(foo()) fun foo() = 1 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.fir.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.fir.kt deleted file mode 100644 index 0f5f8a50c52..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -// Properties can be recursively annotated -annotation class ann(val x: Int) -class My { - @ann(x) val x: Int = 1 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.kt b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.kt index beb12e52cc1..cb0fff775d8 100644 --- a/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.kt +++ b/compiler/testData/diagnostics/tests/annotations/RecursivelyAnnotatedProperty.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // Properties can be recursively annotated annotation class ann(val x: Int) class My { diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/booleanLocalVal.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/booleanLocalVal.fir.kt index 332422e5e47..fb0c2cf59db 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/booleanLocalVal.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/booleanLocalVal.fir.kt @@ -2,5 +2,5 @@ annotation class Ann(vararg val i: Boolean) fun foo() { val bool1 = true - @Ann(bool1) val a = bool1 + @Ann(bool1) val a = bool1 } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.fir.kt deleted file mode 100644 index 5156c7bbb89..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.fir.kt +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.kt index 69999eb86f0..cdaf335608b 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/compareAndEquals.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE annotation class Ann(vararg val i: Boolean) fun foo() { diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_after.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_after.fir.kt index 49fab029968..1c36d4fd575 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_after.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_after.fir.kt @@ -2,7 +2,7 @@ annotation class AnnE(val i: MyEnum) -@AnnE(e) +@AnnE(e) class Test val e: MyEnum = MyEnum.A diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_before.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_before.fir.kt index 5992022f709..7840c246f04 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_before.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/enumConst_before.fir.kt @@ -2,7 +2,7 @@ annotation class AnnE(val i: MyEnum) -@AnnE(e) +@AnnE(e) class Test val e: MyEnum = MyEnum.A diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/javaProperties.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/javaProperties.fir.kt index 9d6c13de8c3..f810b02afcf 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/javaProperties.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/javaProperties.fir.kt @@ -14,12 +14,12 @@ public class Test { annotation class Ann(vararg val i: Int) @Ann( - Test.i1, + Test.i1, Test.i2, Test.i3, Test.i4, - Test.i5, - Test.i6, - Test().i7 + Test.i5, + Test.i6, + Test().i7 ) class A diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.fir.kt deleted file mode 100644 index b580df33fee..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.fir.kt +++ /dev/null @@ -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 diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.kt index 4597228b1f9..cd9a835f81b 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/kotlinProperties.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL annotation class Ann(vararg val i: Int) @Ann( diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.fir.kt deleted file mode 100644 index 5283fe5f70a..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.fir.kt +++ /dev/null @@ -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 - diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.kt index abb407b4f6c..f9f9e533d54 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/standaloneInExpression.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL annotation class AnnE(val i: String) enum class MyEnum { diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.fir.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.fir.kt deleted file mode 100644 index a90f4b533c0..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.fir.kt +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.kt index 1a8e9a41743..b30dd6329aa 100644 --- a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.kt +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant/strings.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE annotation class Ann(vararg val i: String) diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.fir.kt deleted file mode 100644 index 1d6b7d698a9..00000000000 --- a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.fir.kt +++ /dev/null @@ -1,45 +0,0 @@ -// !LANGUAGE: +ProhibitTypeParametersInClassLiteralsInAnnotationArguments - -import kotlin.reflect.KClass - -annotation class Ann(val k: KClass<*>) -annotation class AnnArray(val kk: Array>) - -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 T.test9 - get() = @AnnArray(arrayOf( - T::class, - Array::class, - Array>>::class - )) object {} - -inline val T.test10 - get() = @AnnArray([T::class]) object {} diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt index e0613fb96ec..7bb6e4c4ecd 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +ProhibitTypeParametersInClassLiteralsInAnnotationArguments import kotlin.reflect.KClass diff --git a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments_noTypeParams.fir.kt b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments_noTypeParams.fir.kt index c5a135c4bfc..a8f7a202158 100644 --- a/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments_noTypeParams.fir.kt +++ b/compiler/testData/diagnostics/tests/classLiteral/inAnnotationArguments_noTypeParams.fir.kt @@ -6,7 +6,7 @@ annotation class Ann(vararg val k: KClass<*>) inline val T.test get() = @Ann( - T::class, - Array::class, - Array>>::class + T::class, + Array::class, + Array>>::class ) object {} diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.fir.kt b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.fir.kt index 9bcc0a4d510..8d8a92f1776 100644 --- a/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.fir.kt +++ b/compiler/testData/diagnostics/tests/collectionLiterals/argumentsOfAnnotation.fir.kt @@ -24,8 +24,8 @@ val two = 2 @Foo([ONE], [], []) fun test6() {} -@Foo([ONE + two], [], []) +@Foo([ONE + two], [], []) fun test7() {} -@Foo([two], [], []) +@Foo([two], [], []) fun test8() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/modifiers/const/fromJava.fir.kt b/compiler/testData/diagnostics/tests/modifiers/const/fromJava.fir.kt index 7fad716d109..34e6e03db52 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/fromJava.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/const/fromJava.fir.kt @@ -22,5 +22,5 @@ fun main1() {} fun main2() {} val q = A() -@Ann(q.z) +@Ann(q.z) fun main3() {} diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnClass.fir.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnClass.fir.kt index 68ffc3d5a0a..a53fac7af81 100644 --- a/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnClass.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnClass.fir.kt @@ -22,7 +22,7 @@ annotation class Ann( Companion.CONST, Nested.CONST, Interface.CONST, - a, + a, b() ) class A { diff --git a/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnConstructors.fir.kt b/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnConstructors.fir.kt index d26e5b7c9d0..1fa3d69969f 100644 --- a/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnConstructors.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/classHeader/annotationOnConstructors.fir.kt @@ -23,7 +23,7 @@ class A Companion.CONST, Nested.CONST, Interface.CONST, - a, + a, b() ) constructor() { @@ -36,7 +36,7 @@ constructor() { Companion.CONST, Nested.CONST, Interface.CONST, - a, + a, b() ) constructor(dummy: Int) : this() diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt index 37d863e9cb7..58e77fcb919 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/array.fir.kt @@ -2,10 +2,10 @@ @Repeatable annotation class Ann(val i: IntArray) -@Ann(intArrayOf(i)) +@Ann(intArrayOf(i)) @Ann(intArrayOf(i2)) -@Ann(intArrayOf(i3)) -@Ann(intArrayOf(i, i2, i3)) +@Ann(intArrayOf(i3)) +@Ann(intArrayOf(i, i2, i3)) @Ann(intArrayOf(intArrayOf(i, i2, i3))) class Test @@ -19,6 +19,6 @@ fun foo(): Int = 1 @Repeatable annotation class AnnAnn(val i: Array) @AnnAnn(arrayOf(Ann(intArrayOf(1)))) -@AnnAnn(arrayOf(iAnn)) +@AnnAnn(arrayOf(iAnn)) class TestAnn val iAnn = Ann(intArrayOf(1)) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.fir.kt deleted file mode 100644 index d380508fa01..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.fir.kt +++ /dev/null @@ -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) - -@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 = arrayOf("a", "b") - -annotation class Ann2 diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.kt index 2c0dfd40dcc..1d1bb33a310 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/simple.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL @Retention(AnnotationRetention.SOURCE) @Repeatable annotation class Ann(val i: Int) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/useOfNonConstVal.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/useOfNonConstVal.fir.kt index 469e224f7a9..bb32f0b8cb2 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/useOfNonConstVal.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/useOfNonConstVal.fir.kt @@ -4,13 +4,13 @@ const val constConst = nonConst * nonConst + 2 annotation class Ann(val x: Int, val y: String) -@Ann(nonConst, "${nonConst}") +@Ann(nonConst, "${nonConst}") fun foo1() {} -@Ann(nonConst + constConst, "${constConst}") +@Ann(nonConst + constConst, "${constConst}") fun foo2() {} annotation class ArrayAnn(val x: IntArray) -@ArrayAnn(intArrayOf(1, constConst, nonConst)) +@ArrayAnn(intArrayOf(1, constConst, nonConst)) fun foo3() {} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt index 12305a83376..76eabfc83a1 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.fir.kt @@ -2,10 +2,10 @@ @Repeatable annotation class Ann(vararg val i: Int) -@Ann(i) +@Ann(i) @Ann(i2) -@Ann(i3) -@Ann(i, i2, i3) +@Ann(i3) +@Ann(i, i2, i3) @Ann(*intArrayOf(i)) @Ann(*intArrayOf(i2)) @Ann(*intArrayOf(i3)) diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.fir.kt deleted file mode 100644 index 640ea5cfb18..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.fir.kt +++ /dev/null @@ -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>) - -class A1 -class A2 - -@Ann1(A1::class) -@Ann2(A1::class, A2::class) -@Ann3(arrayOf(A1::class, A2::class)) -class MyClass1 - -@Ann1(A3::class) -class MyClass2 - -val x = A1::class -@Ann1(x) -class MyClass3 diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.kt index bbe61924099..4dbb45c3d86 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/kClass/kClassInAnnotation.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL import kotlin.reflect.KClass annotation class Ann1(val arg: KClass<*>) diff --git a/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt b/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt index a130592e8cc..48accef1627 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt @@ -33,6 +33,8 @@ object OperatorNameConventions { @JvmField val NEXT = Name.identifier("next") @JvmField val HAS_NEXT = Name.identifier("hasNext") + @JvmField val TO_STRING = Name.identifier("toString") + @JvmField val COMPONENT_REGEX = Regex("component\\d+") @JvmField val AND = Name.identifier("and")