From 414881403be88b51a80577167f02da21c353bb6b Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Mon, 20 Sep 2021 23:05:31 -0700 Subject: [PATCH] FIR IDE: handle annotation array values properly --- .../evaluate/KtFirConstantValueConverter.kt | 53 +++++++++++++------ ...ileTimeConstantEvaluatorTestGenerated.java | 18 +++++++ ...nnotationInAnnotation_collectionLiteral.kt | 2 +- ...notationInAnnotation_collectionLiteral.txt | 2 +- ...onInAnnotation_collectionLiteral_spread.kt | 6 +++ ...nInAnnotation_collectionLiteral_spread.txt | 6 +++ ...nAnnotation_multipleAnnotations_arrayOf.kt | 2 +- ...n_multipleAnnotations_collectionLiteral.kt | 2 +- ..._multipleAnnotations_collectionLiteral.txt | 2 +- .../annotationInAnnotation_single.kt | 6 +++ .../annotationInAnnotation_single.txt | 5 ++ .../annotationInAnnotation_vararg.kt | 6 +++ .../annotationInAnnotation_vararg.txt | 6 +++ 13 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.txt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.txt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.txt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/KtFirConstantValueConverter.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/KtFirConstantValueConverter.kt index 2a18a300127..a95c7a5b351 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/KtFirConstantValueConverter.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/KtFirConstantValueConverter.kt @@ -11,13 +11,13 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.realPsi +import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.psi.KtCallElement -import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.ArrayFqNames internal object KtFirConstantValueConverter { @@ -39,18 +39,37 @@ internal object KtFirConstantValueConverter { firConstExpression.convertConstantExpression() private fun FirConstExpression.convertConstantExpression(): KtLiteralConstantValue = - KtLiteralConstantValue(kind, value, realPsi as? KtElement) + KtLiteralConstantValue(kind, value, psi as? KtElement) private fun Collection.convertConstantExpression( session: FirSession, ): Collection = mapNotNull { it.convertConstantExpression(session) } - private fun Collection.toArrayConstantValueIfNecessary(kotlinOrigin: KtElement?): KtConstantValue { - return if (size == 1) - single() - else + // Refer to KtLightAnnotationParameterList#checkIfToArrayConversionExpected + private fun ValueArgument?.arrayConversionExpected(): Boolean { + return when { + this == null -> false + this is KtValueArgument && isSpread -> { + // Anno(*[1,2,3]) + false + } + else -> { + // Anno(a = [1,2,3]) v.s. Anno(1) or Anno(1,2,3) + !isNamed() + } + } + } + + private fun Collection.toArrayConstantValueIfNecessary(kotlinOrigin: KtElement?): KtConstantValue? { + val valueArgument = if (kotlinOrigin is ValueArgument) kotlinOrigin else + (kotlinOrigin?.parents?.firstOrNull { it is ValueArgument } as? ValueArgument) + val wrap = valueArgument?.arrayConversionExpected() ?: false + return if (wrap) { KtArrayConstantValue(this, kotlinOrigin) + } else { + singleOrNull() + } } fun toConstantValue( @@ -67,13 +86,15 @@ internal object KtFirConstantValueConverter { is FirNamedArgumentExpression -> { expression.convertConstantExpression(session) } + is FirSpreadArgumentExpression -> { + expression.convertConstantExpression(session) + } is FirVarargArgumentsExpression -> { - arguments.convertConstantExpression(session) - .toArrayConstantValueIfNecessary(realPsi as? KtElement) + arguments.convertConstantExpression(session).toArrayConstantValueIfNecessary(psi as? KtElement) } is FirArrayOfCall -> { - argumentList.arguments.convertConstantExpression(session) - .toArrayConstantValueIfNecessary(realPsi as? KtElement) + // Desugared collection literals. + KtArrayConstantValue(argumentList.arguments.convertConstantExpression(session), psi as? KtElement) } is FirFunctionCall -> { val reference = calleeReference as? FirResolvedNamedReference ?: return null @@ -88,14 +109,14 @@ internal object KtFirConstantValueConverter { KtAnnotationConstantValue( resolvedSymbol.callableId.classId, toNamedConstantValue(resultMap, session), - this.realPsi as? KtCallElement + psi as? KtCallElement ) } else null } is FirNamedFunctionSymbol -> { + // arrayOf call with a single vararg argument. if (resolvedSymbol.callableId.asSingleFqName() in ArrayFqNames.ARRAY_CALL_FQ_NAMES) - argumentList.arguments.convertConstantExpression(session) - .toArrayConstantValueIfNecessary(realPsi as? KtElement) + argumentList.arguments.single().convertConstantExpression(session) else null } else -> null @@ -105,7 +126,7 @@ internal object KtFirConstantValueConverter { val reference = calleeReference as? FirResolvedNamedReference ?: return null when (val resolvedSymbol = reference.resolvedSymbol) { is FirEnumEntrySymbol -> { - KtEnumEntryConstantValue(resolvedSymbol.callableId, realPsi as? KtElement) + KtEnumEntryConstantValue(resolvedSymbol.callableId, psi as? KtElement) } else -> null } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/CompileTimeConstantEvaluatorTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/CompileTimeConstantEvaluatorTestGenerated.java index 925129495a3..2e67efed3fc 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/CompileTimeConstantEvaluatorTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/CompileTimeConstantEvaluatorTestGenerated.java @@ -36,6 +36,12 @@ public class CompileTimeConstantEvaluatorTestGenerated extends AbstractCompileTi runTest("analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.kt"); } + @Test + @TestMetadata("annotationInAnnotation_collectionLiteral_spread.kt") + public void testAnnotationInAnnotation_collectionLiteral_spread() throws Exception { + runTest("analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.kt"); + } + @Test @TestMetadata("annotationInAnnotation_multipleAnnotations_arrayOf.kt") public void testAnnotationInAnnotation_multipleAnnotations_arrayOf() throws Exception { @@ -48,6 +54,18 @@ public class CompileTimeConstantEvaluatorTestGenerated extends AbstractCompileTi runTest("analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt"); } + @Test + @TestMetadata("annotationInAnnotation_single.kt") + public void testAnnotationInAnnotation_single() throws Exception { + runTest("analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.kt"); + } + + @Test + @TestMetadata("annotationInAnnotation_vararg.kt") + public void testAnnotationInAnnotation_vararg() throws Exception { + runTest("analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.kt"); + } + @Test @TestMetadata("enumAsAnnotationValue.kt") public void testEnumAsAnnotationValue() throws Exception { diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.kt index 9e33acf14d3..15f4fc4a545 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.kt +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.kt @@ -2,5 +2,5 @@ annotation class Annotation(vararg val strings: String) annotation class AnnotationInner(val value: Annotation) -@AnnotationInner(Annotation(["v1", "v2"])) +@AnnotationInner(Annotation(strings = ["v1", "v2"])) class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.txt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.txt index 8f09acbeb6f..34052840426 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.txt +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral.txt @@ -1,4 +1,4 @@ -expression: Annotation(["v1", "v2"]) +expression: Annotation(strings = ["v1", "v2"]) constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [ KtLiteralConstantValue(constantValueKind=String, value=v1) KtLiteralConstantValue(constantValueKind=String, value=v2) diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.kt new file mode 100644 index 00000000000..cc87edfcb08 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.kt @@ -0,0 +1,6 @@ +annotation class Annotation(vararg val strings: String) + +annotation class AnnotationInner(val value: Annotation) + +@AnnotationInner(Annotation(*["v1", "v2"])) +class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.txt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.txt new file mode 100644 index 00000000000..89a9a5ef30f --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_collectionLiteral_spread.txt @@ -0,0 +1,6 @@ +expression: Annotation(*["v1", "v2"]) +constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [ + KtLiteralConstantValue(constantValueKind=String, value=v1) + KtLiteralConstantValue(constantValueKind=String, value=v2) +])) +constant: null diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_arrayOf.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_arrayOf.kt index 1c4d30e3931..01db66c82eb 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_arrayOf.kt +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_arrayOf.kt @@ -2,5 +2,5 @@ annotation class Annotation(vararg val strings: String) annotation class AnnotationArray(vararg val annos: Annotation) -@AnnotationArray(annos = arrayOf(Annotation("v1", "v2"), Annotation(strings = arrayOf("v3", "v4")))) +@AnnotationArray(annos = arrayOf(Annotation("v1", "v2"), Annotation(strings = arrayOf("v3", "v4")))) class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt index e788ac1f8ee..c53905c8594 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt @@ -2,5 +2,5 @@ annotation class Annotation(vararg val strings: String) annotation class AnnotationArray(vararg val annos: Annotation) -@AnnotationArray([Annotation("v1", "v2"), Annotation(["v3", "v4"])]) +@AnnotationArray(annos = [Annotation("v1", "v2"), Annotation(strings = ["v3", "v4"])]) class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.txt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.txt index f93fb649626..6bd64da777b 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.txt +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_multipleAnnotations_collectionLiteral.txt @@ -1,4 +1,4 @@ -expression: [Annotation("v1", "v2"), Annotation(["v3", "v4"])] +expression: [Annotation("v1", "v2"), Annotation(strings = ["v3", "v4"])] constant_value: KtArrayConstantValue [ KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [ KtLiteralConstantValue(constantValueKind=String, value=v1) diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.kt new file mode 100644 index 00000000000..884ece65d6d --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.kt @@ -0,0 +1,6 @@ +annotation class Annotation(vararg val strings: String) + +annotation class AnnotationInner(val value: Annotation) + +@AnnotationInner(Annotation("v1")) +class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.txt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.txt new file mode 100644 index 00000000000..23c56a30705 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_single.txt @@ -0,0 +1,5 @@ +expression: Annotation("v1") +constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [ + KtLiteralConstantValue(constantValueKind=String, value=v1) +])) +constant: null diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.kt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.kt new file mode 100644 index 00000000000..9604251ed9f --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.kt @@ -0,0 +1,6 @@ +annotation class Annotation(vararg val strings: String) + +annotation class AnnotationInner(val value: Annotation) + +@AnnotationInner(Annotation("v1", "v2")) +class C diff --git a/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.txt b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.txt new file mode 100644 index 00000000000..fe091abbb46 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantEvaluator/annotationInAnnotation_vararg.txt @@ -0,0 +1,6 @@ +expression: Annotation("v1", "v2") +constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [ + KtLiteralConstantValue(constantValueKind=String, value=v1) + KtLiteralConstantValue(constantValueKind=String, value=v2) +])) +constant: null