[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);
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
+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>()
|
||||
|
||||
// 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_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 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 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 NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by existing<FirSourceElement, KtExpression>(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION)
|
||||
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
|
||||
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() {
|
||||
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = setOf(
|
||||
FirAnnotationArgumentChecker,
|
||||
FirAnnotationClassDeclarationChecker,
|
||||
FirModifierChecker,
|
||||
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
|
||||
annotation class ann(val x: Int)
|
||||
@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
|
||||
annotation class ann(val x: Int)
|
||||
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
|
||||
annotation class ann(val x: Int)
|
||||
@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
|
||||
annotation class ann(val x: Int)
|
||||
class My {
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ annotation class Ann(vararg val i: Boolean)
|
||||
fun foo() {
|
||||
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
|
||||
annotation class Ann(vararg val i: Boolean)
|
||||
fun foo() {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
annotation class AnnE(val i: MyEnum)
|
||||
|
||||
@AnnE(e)
|
||||
@AnnE(<!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>e<!>)
|
||||
class Test
|
||||
|
||||
val e: MyEnum = MyEnum.A
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
annotation class AnnE(val i: MyEnum)
|
||||
|
||||
@AnnE(e)
|
||||
@AnnE(<!ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST!>e<!>)
|
||||
class Test
|
||||
|
||||
val e: MyEnum = MyEnum.A
|
||||
|
||||
+4
-4
@@ -14,12 +14,12 @@ public class Test {
|
||||
annotation class Ann(vararg val i: Int)
|
||||
|
||||
@Ann(
|
||||
Test.i1,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i1<!>,
|
||||
Test.i2,
|
||||
Test.i3,
|
||||
Test.i4,
|
||||
Test.i5,
|
||||
Test.i6,
|
||||
Test().i7
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i5<!>,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test.i6<!>,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>Test().i7<!>
|
||||
)
|
||||
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)
|
||||
|
||||
@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)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ annotation class Ann(vararg val k: KClass<*>)
|
||||
|
||||
inline val <reified T> T.test
|
||||
get() = @Ann(
|
||||
T::class,
|
||||
Array<T>::class,
|
||||
Array<Array<Array<T>>>::class
|
||||
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>T::class<!>,
|
||||
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>Array<T>::class<!>,
|
||||
<!ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR!>Array<Array<Array<T>>>::class<!>
|
||||
) object {}
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ val two = 2
|
||||
@Foo([ONE], [], [])
|
||||
fun test6() {}
|
||||
|
||||
@Foo([ONE + two], [], [])
|
||||
@Foo(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>ONE + two<!>]<!>, [], [])
|
||||
fun test7() {}
|
||||
|
||||
@Foo([two], [], [])
|
||||
@Foo(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>two<!>]<!>, [], [])
|
||||
fun test8() {}
|
||||
@@ -22,5 +22,5 @@ fun main1() {}
|
||||
fun main2() {}
|
||||
|
||||
val q = A()
|
||||
@Ann(q.z)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>q.z<!>)
|
||||
fun main3() {}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ annotation class Ann(
|
||||
Companion.CONST,
|
||||
Nested.CONST,
|
||||
Interface.CONST,
|
||||
a,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||
b()
|
||||
)
|
||||
class A {
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ class A
|
||||
Companion.CONST,
|
||||
Nested.CONST,
|
||||
Interface.CONST,
|
||||
a,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||
b()
|
||||
)
|
||||
constructor() {
|
||||
@@ -36,7 +36,7 @@ constructor() {
|
||||
Companion.CONST,
|
||||
Nested.CONST,
|
||||
Interface.CONST,
|
||||
a,
|
||||
<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>a<!>,
|
||||
b()
|
||||
)
|
||||
constructor(dummy: Int) : this()
|
||||
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
@Repeatable
|
||||
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(i3))
|
||||
@Ann(intArrayOf(i, i2, i3))
|
||||
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>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)))
|
||||
class Test
|
||||
|
||||
@@ -19,6 +19,6 @@ fun foo(): Int = 1
|
||||
@Repeatable
|
||||
annotation class AnnAnn(val i: Array<Ann>)
|
||||
@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
|
||||
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)
|
||||
@Repeatable
|
||||
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)
|
||||
|
||||
@Ann(nonConst, "${nonConst}")
|
||||
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst<!>, <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>"${nonConst}"<!>)
|
||||
fun foo1() {}
|
||||
|
||||
@Ann(nonConst + constConst, "${constConst}")
|
||||
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst + constConst<!>, "${constConst}")
|
||||
fun foo2() {}
|
||||
|
||||
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() {}
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
@Repeatable
|
||||
annotation class Ann(vararg val i: Int)
|
||||
|
||||
@Ann(i)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>)
|
||||
@Ann(i2)
|
||||
@Ann(i3)
|
||||
@Ann(i, i2, i3)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i<!>, i2, <!ANNOTATION_ARGUMENT_MUST_BE_CONST!>i3<!>)
|
||||
@Ann(*intArrayOf(i))
|
||||
@Ann(*intArrayOf(i2))
|
||||
@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
|
||||
|
||||
annotation class Ann1(val arg: KClass<*>)
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user