Report warning on usages of non-const vals in places where constants expected

This commit is contained in:
Denis Zharkov
2015-09-21 18:14:35 +03:00
parent 8d13f08271
commit afd4e644a3
21 changed files with 105 additions and 29 deletions
@@ -141,6 +141,8 @@ public interface Errors {
DiagnosticFactory0<PsiElement> CONST_VAL_WITHOUT_INITIALIZER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> CONST_VAL_WITHOUT_INITIALIZER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetExpression> CONST_VAL_WITH_NON_CONST_INITIALIZER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetExpression> CONST_VAL_WITH_NON_CONST_INITIALIZER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetExpression> NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR);
@@ -602,6 +602,7 @@ public class DefaultErrorMessages {
MAP.put(TYPE_CANT_BE_USED_FOR_CONST_VAL, "Const 'val' has type ''{0}''. Only primitives and String are allowed", RENDER_TYPE); MAP.put(TYPE_CANT_BE_USED_FOR_CONST_VAL, "Const 'val' has type ''{0}''. Only primitives and String are allowed", RENDER_TYPE);
MAP.put(CONST_VAL_WITHOUT_INITIALIZER, "Const 'val' should have an initializer"); MAP.put(CONST_VAL_WITHOUT_INITIALIZER, "Const 'val' should have an initializer");
MAP.put(CONST_VAL_WITH_NON_CONST_INITIALIZER, "Const 'val' initializer should be a constant value"); MAP.put(CONST_VAL_WITH_NON_CONST_INITIALIZER, "Const 'val' initializer should be a constant value");
MAP.put(NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION, "Only 'const val' can be used in constant expressions");
MAP.put(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE, "An overriding function is not allowed to specify default values for its parameters"); MAP.put(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE, "An overriding function is not allowed to specify default values for its parameters");
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsPackage; import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsPackage;
@@ -880,7 +881,7 @@ public class DescriptorResolver {
} }
private void setConstantForVariableIfNeeded( private void setConstantForVariableIfNeeded(
@NotNull VariableDescriptorWithInitializerImpl variableDescriptor, @NotNull final VariableDescriptorWithInitializerImpl variableDescriptor,
@NotNull final LexicalScope scope, @NotNull final LexicalScope scope,
@NotNull final JetVariableDeclaration variable, @NotNull final JetVariableDeclaration variable,
@NotNull final DataFlowInfo dataFlowInfo, @NotNull final DataFlowInfo dataFlowInfo,
@@ -898,7 +899,15 @@ public class DescriptorResolver {
public ConstantValue<?> invoke() { public ConstantValue<?> invoke() {
JetExpression initializer = variable.getInitializer(); JetExpression initializer = variable.getInitializer();
JetType initializerType = expressionTypingServices.safeGetType(scope, initializer, variableType, dataFlowInfo, trace); JetType initializerType = expressionTypingServices.safeGetType(scope, initializer, variableType, dataFlowInfo, trace);
return constantExpressionEvaluator.evaluateToConstantValue(initializer, trace, initializerType); CompileTimeConstant<?> constant = constantExpressionEvaluator.evaluateExpression(initializer, trace, initializerType);
if (constant == null) return null;
if (constant.getUsesNonConstValAsConstant() && variableDescriptor.isConst()) {
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(initializer));
}
return constant.toConstantValue(initializerType);
} }
}, null) }, null)
); );
@@ -124,6 +124,9 @@ public class ConstantExpressionEvaluator(
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.getBindingContext()) val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.getBindingContext())
if (constant != null && constant.canBeUsedInAnnotations) { if (constant != null && constant.canBeUsedInAnnotations) {
if (constant.usesNonConstValAsConstant) {
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
}
return return
} }
@@ -284,7 +287,7 @@ private class ConstantExpressionEvaluatorVisitor(
} ?: return null } ?: return null
fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
return createConstant(result, expectedType, CompileTimeConstant.Parameters(true, !isLongWithSuffix(), false)) return createConstant(result, expectedType, CompileTimeConstant.Parameters(true, !isLongWithSuffix(), false, usesNonConstValAsConstant = false))
} }
override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? {
@@ -308,6 +311,7 @@ private class ConstantExpressionEvaluatorVisitor(
var interupted = false var interupted = false
var canBeUsedInAnnotation = true var canBeUsedInAnnotation = true
var usesVariableAsConstant = false var usesVariableAsConstant = false
var usesNonConstantVariableAsConstant = false
for (entry in expression.getEntries()) { for (entry in expression.getEntries()) {
val constant = stringExpressionEvaluator.evaluate(entry) val constant = stringExpressionEvaluator.evaluate(entry)
if (constant == null) { if (constant == null) {
@@ -317,6 +321,7 @@ private class ConstantExpressionEvaluatorVisitor(
else { else {
if (!constant.canBeUsedInAnnotations) canBeUsedInAnnotation = false if (!constant.canBeUsedInAnnotations) canBeUsedInAnnotation = false
if (constant.usesVariableAsConstant) usesVariableAsConstant = true if (constant.usesVariableAsConstant) usesVariableAsConstant = true
if (constant.usesNonConstValAsConstant) usesNonConstantVariableAsConstant = true
sb.append(constant.constantValue.value) sb.append(constant.constantValue.value)
} }
} }
@@ -327,7 +332,8 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters( CompileTimeConstant.Parameters(
isPure = false, isPure = false,
canBeUsedInAnnotation = canBeUsedInAnnotation, canBeUsedInAnnotation = canBeUsedInAnnotation,
usesVariableAsConstant = usesVariableAsConstant usesVariableAsConstant = usesVariableAsConstant,
usesNonConstValAsConstant = usesNonConstantVariableAsConstant
) )
) )
else null else null
@@ -363,7 +369,8 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters( CompileTimeConstant.Parameters(
canBeUsedInAnnotation = true, canBeUsedInAnnotation = true,
isPure = false, isPure = false,
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
) )
) )
} }
@@ -388,6 +395,7 @@ private class ConstantExpressionEvaluatorVisitor(
val isArgumentPure = isPureConstant(argumentForReceiver.expression) val isArgumentPure = isPureConstant(argumentForReceiver.expression)
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression)
val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression)
val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression)
val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS
return createConstant( return createConstant(
result, result,
@@ -395,7 +403,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters( CompileTimeConstant.Parameters(
canBeUsedInAnnotation, canBeUsedInAnnotation,
!isNumberConversionMethod && isArgumentPure, !isNumberConversionMethod && isArgumentPure,
usesVariableAsConstant) usesVariableAsConstant, usesNonConstValAsConstant)
) )
} }
else if (argumentsEntrySet.size() == 1) { else if (argumentsEntrySet.size() == 1) {
@@ -415,7 +423,8 @@ private class ConstantExpressionEvaluatorVisitor(
val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression)
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression)
val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression) val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
val parameters = CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant) val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
val parameters = CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
return when (resultingDescriptorName) { return when (resultingDescriptorName) {
OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, factory)?.wrap(parameters) OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, factory)?.wrap(parameters)
OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, factory)?.wrap(parameters) OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, factory)?.wrap(parameters)
@@ -429,6 +438,8 @@ private class ConstantExpressionEvaluatorVisitor(
} }
private fun usesVariableAsConstant(expression: JetExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext())?.usesVariableAsConstant ?: false private fun usesVariableAsConstant(expression: JetExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext())?.usesVariableAsConstant ?: false
private fun usesNonConstValAsConstant(expression: JetExpression)
= ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.usesNonConstValAsConstant ?: false
private fun canBeUsedInAnnotation(expression: JetExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext())?.canBeUsedInAnnotations ?: false private fun canBeUsedInAnnotation(expression: JetExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.getBindingContext())?.canBeUsedInAnnotations ?: false
@@ -515,7 +526,8 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters( CompileTimeConstant.Parameters(
canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor), canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor),
isPure = false, isPure = false,
usesVariableAsConstant = true usesVariableAsConstant = true,
usesNonConstValAsConstant = !callableDescriptor.isConst
) )
) )
} }
@@ -523,6 +535,7 @@ private class ConstantExpressionEvaluatorVisitor(
return null return null
} }
// TODO: Should be replaced with descriptor.isConst
private fun isPropertyCompileTimeConstant(descriptor: VariableDescriptor): Boolean { private fun isPropertyCompileTimeConstant(descriptor: VariableDescriptor): Boolean {
if (descriptor.isVar()) { if (descriptor.isVar()) {
return false return false
@@ -566,7 +579,7 @@ private class ConstantExpressionEvaluatorVisitor(
val resultingDescriptor = call.getResultingDescriptor() val resultingDescriptor = call.getResultingDescriptor()
// array() // arrayOf()
if (CompileTimeConstantUtils.isArrayMethodCall(call)) { if (CompileTimeConstantUtils.isArrayMethodCall(call)) {
val varargType = resultingDescriptor.getValueParameters().first().getVarargElementType()!! val varargType = resultingDescriptor.getValueParameters().first().getVarargElementType()!!
@@ -574,7 +587,8 @@ private class ConstantExpressionEvaluatorVisitor(
return factory.createArrayValue(arguments.map { it.toConstantValue(varargType) }, resultingDescriptor.getReturnType()!!). return factory.createArrayValue(arguments.map { it.toConstantValue(varargType) }, resultingDescriptor.getReturnType()!!).
wrap( wrap(
usesVariableAsConstant = arguments.any { it.usesVariableAsConstant } usesVariableAsConstant = arguments.any { it.usesVariableAsConstant },
usesNonConstValAsConstant = arguments.any { it.usesNonConstValAsConstant }
) )
} }
@@ -696,9 +710,10 @@ private class ConstantExpressionEvaluatorVisitor(
private fun <T> ConstantValue<T>.wrap( private fun <T> ConstantValue<T>.wrap(
canBeUsedInAnnotation: Boolean = this !is NullValue, canBeUsedInAnnotation: Boolean = this !is NullValue,
isPure: Boolean = false, isPure: Boolean = false,
usesVariableAsConstant: Boolean = false usesVariableAsConstant: Boolean = false,
usesNonConstValAsConstant: Boolean = false
): TypedCompileTimeConstant<T> ): TypedCompileTimeConstant<T>
= wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, usesVariableAsConstant)) = wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, usesVariableAsConstant, usesNonConstValAsConstant))
} }
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L') private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
@@ -1,3 +1,3 @@
// Properties can be recursively annotated // Properties can be recursively annotated
annotation class ann(val x: Int) annotation class ann(val x: Int)
@ann(x) val x: Int = 1 @ann(x) const val x: Int = 1
@@ -1,6 +1,6 @@
package package
@ann(x = 1) public val x: kotlin.Int = 1 @ann(x = 1) public const val x: kotlin.Int = 1
@kotlin.annotation.annotation() public final class ann : kotlin.Annotation { @kotlin.annotation.annotation() public final class ann : kotlin.Annotation {
public constructor ann(/*0*/ x: kotlin.Int) public constructor ann(/*0*/ x: kotlin.Int)
@@ -11,8 +11,8 @@ annotation class Ann(vararg val i: Int)
class Test class Test
var i1 = 1 // var var i1 = 1 // var
val i2 = 1 // val const val i2 = 1 // val
val i3 = i1 // val with var in initializer val i3 = i1 // val with var in initializer
val i4 = i2 // val with val in initializer const val i4 = i2 // val with val in initializer
var i5 = i1 // var with var in initializer var i5 = i1 // var with var in initializer
var i6 = i2 // var with val in initializer var i6 = i2 // var with val in initializer
@@ -1,9 +1,9 @@
package package
public var i1: kotlin.Int public var i1: kotlin.Int
public val i2: kotlin.Int = 1 public const val i2: kotlin.Int = 1
public val i3: kotlin.Int public val i3: kotlin.Int
public val i4: kotlin.Int = 1 public const val i4: kotlin.Int = 1
public var i5: kotlin.Int public var i5: kotlin.Int
public var i6: kotlin.Int public var i6: kotlin.Int
@@ -1,7 +1,7 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_VARIABLE
annotation class Ann(vararg val i: String) annotation class Ann(vararg val i: String)
val topLevel = "topLevel" const val topLevel = "topLevel"
fun foo() { fun foo() {
val a1 = "a" val a1 = "a"
@@ -1,6 +1,6 @@
package package
public val topLevel: kotlin.String = "topLevel" public const val topLevel: kotlin.String = "topLevel"
public fun foo(): kotlin.Unit public fun foo(): kotlin.Unit
@kotlin.annotation.annotation() public final class Ann : kotlin.Annotation { @kotlin.annotation.annotation() public final class Ann : kotlin.Annotation {
@@ -2,7 +2,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
annotation class ann(val name: String) annotation class ann(val name: String)
val ok = "OK" const val ok = "OK"
class A class A
@@ -2,7 +2,7 @@ package
public val extensionWithoutName: A.() -> kotlin.Unit public val extensionWithoutName: A.() -> kotlin.Unit
public val funfun: () -> () -> kotlin.Int public val funfun: () -> () -> kotlin.Int
public val ok: kotlin.String = "OK" public const val ok: kotlin.String = "OK"
public val parentesized: () -> kotlin.Unit public val parentesized: () -> kotlin.Unit
public val parentesizedWithType: () -> kotlin.Unit public val parentesizedWithType: () -> kotlin.Unit
public val withExpression: () -> kotlin.Int public val withExpression: () -> kotlin.Int
@@ -10,7 +10,7 @@ annotation class Ann(val i: IntArray)
class Test class Test
var i = 1 var i = 1
val i2 = 1 const val i2 = 1
val i3 = foo() val i3 = foo()
fun foo(): Int = 1 fun foo(): Int = 1
@@ -1,7 +1,7 @@
package package
public var i: kotlin.Int public var i: kotlin.Int
public val i2: kotlin.Int = 1 public const val i2: kotlin.Int = 1
public val i3: kotlin.Int public val i3: kotlin.Int
public val iAnn: Ann public val iAnn: Ann
public fun foo(): kotlin.Int public fun foo(): kotlin.Int
@@ -0,0 +1,16 @@
val nonConst = 1
const val constConst = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst * nonConst + 2<!>
annotation class Ann(val x: Int, val y: String)
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst<!>, <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>"${nonConst}"<!>)
fun foo1() {}
@Ann(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst + constConst<!>, "${constConst}")
fun foo2() {}
annotation class ArrayAnn(val x: IntArray)
@ArrayAnn(<!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>intArrayOf(1, constConst, <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>nonConst<!>)<!>)
fun foo3() {}
@@ -0,0 +1,24 @@
package
public const val constConst: kotlin.Int = 3
public val nonConst: kotlin.Int = 1
@Ann(x = 1, y = "1") public fun foo1(): kotlin.Unit
@Ann(x = 4, y = "3") public fun foo2(): kotlin.Unit
@ArrayAnn(x = {1, 3, 1}) public fun foo3(): kotlin.Unit
@kotlin.annotation.annotation() public final class Ann : kotlin.Annotation {
public constructor Ann(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.annotation() public final class ArrayAnn : kotlin.Annotation {
public constructor ArrayAnn(/*0*/ x: kotlin.IntArray)
public final val x: kotlin.IntArray
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -13,7 +13,7 @@ annotation class Ann(vararg val i: Int)
class Test class Test
var i = 1 var i = 1
val i2 = 1 const val i2 = 1
val i3 = foo() val i3 = foo()
fun foo(): Int = 1 fun foo(): Int = 1
@@ -1,7 +1,7 @@
package package
public var i: kotlin.Int public var i: kotlin.Int
public val i2: kotlin.Int = 1 public const val i2: kotlin.Int = 1
public val i3: kotlin.Int public val i3: kotlin.Int
public val iAnn: Ann public val iAnn: Ann
public fun foo(): kotlin.Int public fun foo(): kotlin.Int
@@ -162,6 +162,12 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
doTest(fileName); doTest(fileName);
} }
@TestMetadata("useOfNonConstVal.kt")
public void testUseOfNonConstVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/useOfNonConstVal.kt");
doTest(fileName);
}
@TestMetadata("vararg.kt") @TestMetadata("vararg.kt")
public void testVararg() throws Exception { public void testVararg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/annotationParameterMustBeConstant/vararg.kt");
@@ -34,12 +34,15 @@ public interface CompileTimeConstant<out T> {
public val usesVariableAsConstant: Boolean get() = parameters.usesVariableAsConstant public val usesVariableAsConstant: Boolean get() = parameters.usesVariableAsConstant
public val usesNonConstValAsConstant: Boolean get() = parameters.usesNonConstValAsConstant
public val isPure: Boolean get() = parameters.isPure public val isPure: Boolean get() = parameters.isPure
public class Parameters( public class Parameters(
public val canBeUsedInAnnotation: Boolean, public val canBeUsedInAnnotation: Boolean,
public val isPure: Boolean, public val isPure: Boolean,
public val usesVariableAsConstant: Boolean public val usesVariableAsConstant: Boolean,
public val usesNonConstValAsConstant: Boolean
) )
} }
+2 -2
View File
@@ -16,8 +16,8 @@
package boo package boo
val BAZ = "baz" const val BAZ = "baz"
val N = 0 const val N = 0
@Target(AnnotationTarget.FILE) @Target(AnnotationTarget.FILE)
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)