Allow to use emptyArray in annotation as argument
#KT-14236 Fixed
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,7 +56,8 @@ public class CompileTimeConstantUtils {
|
||||
"kotlin.charArrayOf",
|
||||
"kotlin.shortArrayOf",
|
||||
"kotlin.byteArrayOf",
|
||||
"kotlin.booleanArrayOf"
|
||||
"kotlin.booleanArrayOf",
|
||||
"kotlin.emptyArray"
|
||||
);
|
||||
|
||||
public static void checkConstructorParametersType(@NotNull List<KtParameter> parameters, @NotNull BindingTrace trace) {
|
||||
@@ -110,7 +111,7 @@ public class CompileTimeConstantUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isArrayMethodCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
public static boolean isArrayFunctionCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
return ARRAY_CALL_NAMES.contains(DescriptorUtils.getFqName(resolvedCall.getCandidateDescriptor()).asString());
|
||||
}
|
||||
|
||||
|
||||
+16
-14
@@ -166,23 +166,24 @@ class ConstantExpressionEvaluator(
|
||||
trace: BindingTrace
|
||||
): Pair<List<KtExpression>, KotlinType?>? {
|
||||
val resolvedCall = expression.getResolvedCall(trace.bindingContext)
|
||||
if (resolvedCall == null || !CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
|
||||
if (resolvedCall == null || !CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val argumentEntry = resolvedCall.valueArguments.entries.single()
|
||||
|
||||
val elementType = argumentEntry.key.varargElementType ?: return null
|
||||
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
||||
val componentType = builtIns.getArrayElementType(returnType)
|
||||
|
||||
val result = arrayListOf<KtExpression>()
|
||||
for (valueArgument in argumentEntry.value.arguments) {
|
||||
val valueArgumentExpression = valueArgument.getArgumentExpression()
|
||||
if (valueArgumentExpression != null) {
|
||||
result.add(valueArgumentExpression)
|
||||
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
||||
for (valueArgument in resolvedValueArgument.arguments) {
|
||||
val valueArgumentExpression = valueArgument.getArgumentExpression()
|
||||
if (valueArgumentExpression != null) {
|
||||
result.add(valueArgumentExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Pair<List<KtExpression>, KotlinType>(result, elementType)
|
||||
return Pair<List<KtExpression>, KotlinType>(result, componentType)
|
||||
}
|
||||
|
||||
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
|
||||
@@ -646,13 +647,14 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
|
||||
val resultingDescriptor = call.resultingDescriptor
|
||||
|
||||
// arrayOf()
|
||||
if (CompileTimeConstantUtils.isArrayMethodCall(call)) {
|
||||
val varargType = resultingDescriptor.valueParameters.first().varargElementType!!
|
||||
// arrayOf() or emptyArray()
|
||||
if (CompileTimeConstantUtils.isArrayFunctionCall(call)) {
|
||||
val returnType = resultingDescriptor.returnType ?: return null
|
||||
val componentType = constantExpressionEvaluator.builtIns.getArrayElementType(returnType)
|
||||
|
||||
val arguments = call.valueArguments.values.flatMap { resolveArguments(it.arguments, varargType) }
|
||||
val arguments = call.valueArguments.values.flatMap { resolveArguments(it.arguments, componentType) }
|
||||
|
||||
return factory.createArrayValue(arguments.map { it.toConstantValue(varargType) }, resultingDescriptor.returnType!!).
|
||||
return factory.createArrayValue(arguments.map { it.toConstantValue(componentType) }, resultingDescriptor.returnType!!).
|
||||
wrap(
|
||||
usesVariableAsConstant = arguments.any { it.usesVariableAsConstant },
|
||||
usesNonConstValAsConstant = arguments.any { it.usesNonConstValAsConstant }
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
annotation class Anno(val x: Array<String> = emptyArray())
|
||||
|
||||
@Anno fun test1() = 1
|
||||
@Anno(arrayOf("K")) fun test2() = 2
|
||||
|
||||
fun box(): String {
|
||||
return if (test1() + test2() == 3) "OK" else "Fail"
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
@java.lang.annotation.Retention
|
||||
@kotlin.Metadata
|
||||
public annotation class Anno {
|
||||
public abstract method x(): java.lang.String[]
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class AnnotationWithEmptyArrayKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static @Anno method test1(): int
|
||||
public final static @Anno method test2(): int
|
||||
}
|
||||
+1
@@ -19,6 +19,7 @@ val i2 = foo()
|
||||
|
||||
fun foo(): Int = 1
|
||||
|
||||
@AnnSA(emptyArray())
|
||||
class MyClass {
|
||||
val i = 1
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public final annotation class AnnSA : kotlin.Annotation {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class MyClass {
|
||||
@AnnSA(sa = {}) public final class MyClass {
|
||||
public constructor MyClass()
|
||||
public final val i: kotlin.Int = 1
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
+6
@@ -5845,6 +5845,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationWithEmptyArray.kt")
|
||||
public void testAnnotationWithEmptyArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/annotationWithEmptyArray.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
||||
|
||||
@@ -5845,6 +5845,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationWithEmptyArray.kt")
|
||||
public void testAnnotationWithEmptyArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/annotationWithEmptyArray.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -500,7 +500,7 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
val argumentExpression = argument.getArgumentExpression() ?: return@forEachDescendantOfType
|
||||
val resolvedCall = argumentExpression.getResolvedCall(argumentExpression.analyze(BodyResolveMode.PARTIAL)) ?: return@forEachDescendantOfType
|
||||
val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return@forEachDescendantOfType
|
||||
if (CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
|
||||
if (CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
||||
argumentsToExpand.add(argument to callExpression.valueArguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6614,6 +6614,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationWithEmptyArray.kt")
|
||||
public void testAnnotationWithEmptyArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/annotationWithEmptyArray.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
||||
|
||||
Reference in New Issue
Block a user