Introduce new feature: division by zero in constant expressions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 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.
|
||||
@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
@@ -92,8 +91,6 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
|
||||
private DefaultSourceMapper sourceMapper;
|
||||
|
||||
private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||
|
||||
public MemberCodegen(
|
||||
@NotNull GenerationState state,
|
||||
@Nullable MemberCodegen<?> parentCodegen,
|
||||
@@ -111,7 +108,6 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
this.functionCodegen = new FunctionCodegen(context, v, state, this);
|
||||
this.propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
|
||||
this.parentCodegen = parentCodegen;
|
||||
this.constantExpressionEvaluator = new ConstantExpressionEvaluator(state.getModule().getBuiltIns());
|
||||
}
|
||||
|
||||
protected MemberCodegen(@NotNull MemberCodegen<T> wrapped, T declaration, FieldOwnerContext codegenContext) {
|
||||
|
||||
+6
-2
@@ -21,6 +21,8 @@ import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.text.LiteralFormatUtil
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -44,7 +46,8 @@ import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
class ConstantExpressionEvaluator(
|
||||
internal val builtIns: KotlinBuiltIns
|
||||
internal val builtIns: KotlinBuiltIns,
|
||||
internal val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
internal val constantValueFactory = ConstantValueFactory(builtIns)
|
||||
|
||||
@@ -456,7 +459,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
val parentExpression: KtExpression = PsiTreeUtil.getParentOfType(receiverExpression, KtExpression::class.java)!!
|
||||
trace.report(Errors.DIVISION_BY_ZERO.on(parentExpression))
|
||||
|
||||
if (isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) {
|
||||
if ((isIntegerType(argumentForReceiver.value) && isIntegerType(argumentForParameter.value)) ||
|
||||
!constantExpressionEvaluator.languageVersionSettings.supportsFeature(LanguageFeature.DivisionByZeroInConstantExpressions)) {
|
||||
return factory.createErrorValue("Division by zero").wrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.script
|
||||
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtUserType
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
@@ -42,7 +43,7 @@ internal class KtAnnotationWrapper(val psi: KtAnnotationEntry, val targetClass:
|
||||
// TODO: annotation constructors unsupported yet in kotlin reflection, test and correct when they will be ready
|
||||
val targetAnnParams = targetClass.primaryConstructor?.parameters
|
||||
psi.valueArguments.mapIndexed { i, arg ->
|
||||
val evaluator = ConstantExpressionEvaluator(DefaultBuiltIns.Instance)
|
||||
val evaluator = ConstantExpressionEvaluator(DefaultBuiltIns.Instance, LanguageVersionSettingsImpl.DEFAULT)
|
||||
val trace = BindingTraceContext()
|
||||
val result = evaluator.evaluateToConstantValue(arg.getArgumentExpression()!!, trace, TypeUtils.NO_EXPECTED_TYPE)
|
||||
// TODO: consider inspecting `trace` to find diagnostics reported during the computation (such as division by zero, integer overflow, invalid annotation parameters etc.)
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// !LANGUAGE: -DivisionByZeroInConstantExpressions
|
||||
// !DIAGNOSTICS:-DIVISION_BY_ZERO
|
||||
|
||||
const val a = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 / 0.0<!>
|
||||
const val b = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.0 / 0<!>
|
||||
const val c = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>0.0 / 0<!>
|
||||
|
||||
const val i = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 / 0<!>
|
||||
|
||||
val nonConst1 = 1.0 / 0
|
||||
val nonConst2 = 1 / 0
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package
|
||||
|
||||
public const val a: kotlin.Double
|
||||
public const val b: kotlin.Double
|
||||
public const val c: kotlin.Double
|
||||
public const val i: kotlin.Int
|
||||
public val nonConst1: kotlin.Double
|
||||
public val nonConst2: kotlin.Int
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 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.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.constants.evaluate
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -64,7 +65,7 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractAnnotationDesc
|
||||
|
||||
private fun evaluateInitializer(context: BindingContext, property: VariableDescriptor): CompileTimeConstant<*>? {
|
||||
val propertyDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(property) as KtProperty
|
||||
val compileTimeConstant = ConstantExpressionEvaluator(property.builtIns).evaluateExpression(
|
||||
val compileTimeConstant = ConstantExpressionEvaluator(property.builtIns, LanguageVersionSettingsImpl.DEFAULT).evaluateExpression(
|
||||
propertyDeclaration.initializer!!,
|
||||
DelegatingBindingTrace(context, "trace for evaluating compile time constant"),
|
||||
property.type
|
||||
|
||||
@@ -12261,6 +12261,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noDivisionByZeroFeature.kt")
|
||||
public void testNoDivisionByZeroFeature() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/const/noDivisionByZeroFeature.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("types.kt")
|
||||
public void testTypes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/const/types.kt");
|
||||
|
||||
@@ -33,6 +33,7 @@ enum class LanguageFeature(val sinceVersion: LanguageVersion?) {
|
||||
SingleUnderscoreForParameterName(KOTLIN_1_1),
|
||||
DslMarkersSupport(KOTLIN_1_1),
|
||||
UnderscoresInNumericLiterals(KOTLIN_1_1),
|
||||
DivisionByZeroInConstantExpressions(KOTLIN_1_1),
|
||||
|
||||
// Experimental features
|
||||
MultiPlatformProjects(null),
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 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.
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
@@ -54,7 +55,8 @@ class ExtractableSubstringInfo(
|
||||
|
||||
val tempContext = expr.analyzeInContext(scope, template)
|
||||
val trace = DelegatingBindingTrace(tempContext, "Evaluate '$literal'")
|
||||
val value = ConstantExpressionEvaluator(builtIns).evaluateExpression(expr, trace)
|
||||
val languageVersionSettings = facade.getFrontendService(LanguageVersionSettings::class.java)
|
||||
val value = ConstantExpressionEvaluator(builtIns, languageVersionSettings).evaluateExpression(expr, trace)
|
||||
if (value == null || value.isError) return stringType
|
||||
|
||||
return value.toConstantValue(TypeUtils.NO_EXPECTED_TYPE).type
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiExpression
|
||||
import com.intellij.psi.impl.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
@@ -53,7 +54,8 @@ class KotlinLightConstantExpressionEvaluator : ConstantExpressionEvaluator {
|
||||
return when (expressionToCompute) {
|
||||
is KtExpression -> {
|
||||
val resolutionFacade = expressionToCompute.getResolutionFacade()
|
||||
val evaluator = FrontendConstantExpressionEvaluator(resolutionFacade.moduleDescriptor.builtIns)
|
||||
val evaluator = FrontendConstantExpressionEvaluator(resolutionFacade.moduleDescriptor.builtIns,
|
||||
expressionToCompute.languageVersionSettings)
|
||||
val evaluatorTrace = DelegatingBindingTrace(resolutionFacade.analyze(expressionToCompute), "Evaluating annotation argument")
|
||||
|
||||
val constant = evaluator.evaluateExpression(expressionToCompute, evaluatorTrace) ?: return null
|
||||
|
||||
Reference in New Issue
Block a user