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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -56,7 +56,8 @@ public class CompileTimeConstantUtils {
|
|||||||
"kotlin.charArrayOf",
|
"kotlin.charArrayOf",
|
||||||
"kotlin.shortArrayOf",
|
"kotlin.shortArrayOf",
|
||||||
"kotlin.byteArrayOf",
|
"kotlin.byteArrayOf",
|
||||||
"kotlin.booleanArrayOf"
|
"kotlin.booleanArrayOf",
|
||||||
|
"kotlin.emptyArray"
|
||||||
);
|
);
|
||||||
|
|
||||||
public static void checkConstructorParametersType(@NotNull List<KtParameter> parameters, @NotNull BindingTrace trace) {
|
public static void checkConstructorParametersType(@NotNull List<KtParameter> parameters, @NotNull BindingTrace trace) {
|
||||||
@@ -110,7 +111,7 @@ public class CompileTimeConstantUtils {
|
|||||||
return false;
|
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());
|
return ARRAY_CALL_NAMES.contains(DescriptorUtils.getFqName(resolvedCall.getCandidateDescriptor()).asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-14
@@ -166,23 +166,24 @@ class ConstantExpressionEvaluator(
|
|||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
): Pair<List<KtExpression>, KotlinType?>? {
|
): Pair<List<KtExpression>, KotlinType?>? {
|
||||||
val resolvedCall = expression.getResolvedCall(trace.bindingContext)
|
val resolvedCall = expression.getResolvedCall(trace.bindingContext)
|
||||||
if (resolvedCall == null || !CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
|
if (resolvedCall == null || !CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val argumentEntry = resolvedCall.valueArguments.entries.single()
|
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
||||||
|
val componentType = builtIns.getArrayElementType(returnType)
|
||||||
val elementType = argumentEntry.key.varargElementType ?: return null
|
|
||||||
|
|
||||||
val result = arrayListOf<KtExpression>()
|
val result = arrayListOf<KtExpression>()
|
||||||
for (valueArgument in argumentEntry.value.arguments) {
|
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
||||||
val valueArgumentExpression = valueArgument.getArgumentExpression()
|
for (valueArgument in resolvedValueArgument.arguments) {
|
||||||
if (valueArgumentExpression != null) {
|
val valueArgumentExpression = valueArgument.getArgumentExpression()
|
||||||
result.add(valueArgumentExpression)
|
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 {
|
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
|
||||||
@@ -646,13 +647,14 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
|
|
||||||
val resultingDescriptor = call.resultingDescriptor
|
val resultingDescriptor = call.resultingDescriptor
|
||||||
|
|
||||||
// arrayOf()
|
// arrayOf() or emptyArray()
|
||||||
if (CompileTimeConstantUtils.isArrayMethodCall(call)) {
|
if (CompileTimeConstantUtils.isArrayFunctionCall(call)) {
|
||||||
val varargType = resultingDescriptor.valueParameters.first().varargElementType!!
|
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(
|
wrap(
|
||||||
usesVariableAsConstant = arguments.any { it.usesVariableAsConstant },
|
usesVariableAsConstant = arguments.any { it.usesVariableAsConstant },
|
||||||
usesNonConstValAsConstant = arguments.any { it.usesNonConstValAsConstant }
|
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
|
fun foo(): Int = 1
|
||||||
|
|
||||||
|
@AnnSA(emptyArray())
|
||||||
class MyClass {
|
class MyClass {
|
||||||
val i = 1
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class MyClass {
|
@AnnSA(sa = {}) public final class MyClass {
|
||||||
public constructor MyClass()
|
public constructor MyClass()
|
||||||
public final val i: kotlin.Int = 1
|
public final val i: kotlin.Int = 1
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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);
|
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")
|
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
||||||
|
|||||||
@@ -5845,6 +5845,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 argumentExpression = argument.getArgumentExpression() ?: return@forEachDescendantOfType
|
||||||
val resolvedCall = argumentExpression.getResolvedCall(argumentExpression.analyze(BodyResolveMode.PARTIAL)) ?: return@forEachDescendantOfType
|
val resolvedCall = argumentExpression.getResolvedCall(argumentExpression.analyze(BodyResolveMode.PARTIAL)) ?: return@forEachDescendantOfType
|
||||||
val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: 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)
|
argumentsToExpand.add(argument to callExpression.valueArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6614,6 +6614,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("checkIfConstructorIsSynthetic.kt")
|
||||||
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
public void testCheckIfConstructorIsSynthetic() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/defaultArguments/constructor/checkIfConstructorIsSynthetic.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user