Add warning if constant conforms to infinity or zero

#KT-3805 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2017-02-07 16:08:42 +03:00
parent 292f010e59
commit 935f7b1cc1
7 changed files with 78 additions and 4 deletions
@@ -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.
@@ -790,6 +790,8 @@ public interface Errors {
DiagnosticFactory0<KtConstantExpression> WRONG_LONG_SUFFIX = DiagnosticFactory0.create(ERROR, LONG_LITERAL_SUFFIX);
DiagnosticFactory0<KtConstantExpression> INT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_CONFORMS_INFINITY = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtConstantExpression> FLOAT_LITERAL_CONFORMS_ZERO = DiagnosticFactory0.create(WARNING);
DiagnosticFactory2<KtConstantExpression, String, KotlinType> CONSTANT_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtConstantExpression> INCORRECT_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtConstantExpression> EMPTY_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR);
@@ -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.
@@ -534,6 +534,8 @@ public class DefaultErrorMessages {
MAP.put(INT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(WRONG_LONG_SUFFIX, "Use 'L' instead of 'l'");
MAP.put(FLOAT_LITERAL_OUT_OF_RANGE, "The value is out of range");
MAP.put(FLOAT_LITERAL_CONFORMS_INFINITY, "Floating point number conforms to infinity");
MAP.put(FLOAT_LITERAL_CONFORMS_ZERO, "Floating point number conforms to zero");
MAP.put(INCORRECT_CHARACTER_LITERAL, "Incorrect character literal");
MAP.put(EMPTY_CHARACTER_LITERAL, "Empty character literal");
MAP.put(ILLEGAL_UNDERSCORE, "Illegal underscore");
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.constants.evaluate
import com.intellij.psi.tree.IElementType
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.text.LiteralFormatUtil
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -313,8 +314,26 @@ private class ConstantExpressionEvaluatorVisitor(
else -> throw IllegalArgumentException("Unsupported constant: " + expression)
} ?: return null
fun isLongWithSuffix() = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
return createConstant(result, expectedType, CompileTimeConstant.Parameters(true, !isLongWithSuffix(), false, usesNonConstValAsConstant = false))
if (result is Double) {
if (result.isInfinite()) {
trace.report(Errors.FLOAT_LITERAL_CONFORMS_INFINITY.on(expression))
}
if (result == 0.0 && !TypeConversionUtil.isFPZero(text)) {
trace.report(Errors.FLOAT_LITERAL_CONFORMS_ZERO.on(expression))
}
}
if (result is Float) {
if (result.isInfinite()) {
trace.report(Errors.FLOAT_LITERAL_CONFORMS_INFINITY.on(expression))
}
if (result == 0.0f && !TypeConversionUtil.isFPZero(text)) {
trace.report(Errors.FLOAT_LITERAL_CONFORMS_ZERO.on(expression))
}
}
val isLongWithSuffix = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
return createConstant(result, expectedType, CompileTimeConstant.Parameters(true, !isLongWithSuffix, false, usesNonConstValAsConstant = false))
}
override fun visitParenthesizedExpression(expression: KtParenthesizedExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNUSED_EXPRESSION
fun test() {
<!FLOAT_LITERAL_CONFORMS_INFINITY!>1.2E400F<!>
<!FLOAT_LITERAL_CONFORMS_ZERO!>1.2E-400F<!>
<!FLOAT_LITERAL_CONFORMS_INFINITY!>11111111111111111111111111111111111111111111111111111111111111111F<!>
<!FLOAT_LITERAL_CONFORMS_ZERO!>0.000000000000000000000000000000000000000000000000000000000000001F<!>
0.000000000000000000000000000000000000001000000000000000000000000F
<!FLOAT_LITERAL_CONFORMS_INFINITY!>1.2E400f<!>
<!FLOAT_LITERAL_CONFORMS_ZERO!>1.2E-400f<!>
<!FLOAT_LITERAL_CONFORMS_INFINITY!>11111111111111111111111111111111111111111111111111111111111111111f<!>
<!FLOAT_LITERAL_CONFORMS_ZERO!>0.000000000000000000000000000000000000000000000000000000000000001f<!>
0.000000000000000000000000000000000000001000000000000000000000000f
val d1: Double = <!FLOAT_LITERAL_CONFORMS_INFINITY!>1.2E400<!>
val d2: Double = <!FLOAT_LITERAL_CONFORMS_ZERO!>1.2E-400<!>
val d3: Double = 11111111111111111111111111111111111111111111111111111111111111111.0
val d4: Double = 0.000000000000000000000000000000000000000000000000000000000000001
val d5: Double = 0.000000000000000000000000000000000000001000000000000000000000000
}
@@ -0,0 +1,3 @@
package
public fun test(): kotlin.Unit
+21
View File
@@ -26,3 +26,24 @@ val prop8: Float = 1.0.toDouble() + 1.0
// val prop9: -2.0.toDouble()
val prop9: Double = -2.0
// val prop10: Infinity.toFloat()
val prop10: Float = 1.2E400F
// val prop11: 0.0.toFloat()
val prop11: Float = 1.2E-400F
// val prop12: Infinity.toFloat()
val prop12: Float = 11111111111111111111111111111111111111111111111111111111111111111F
// val prop13: 0.0.toFloat()
val prop13: Float = 0.000000000000000000000000000000000000000000000000000000000000001F
// val prop14: 1.0E-39.toFloat()
val prop14: Float = 0.000000000000000000000000000000000000001000000000000000000000000F
// val prop15: Infinity.toDouble()
val prop15: Double = 1.2E400
// val prop16: 0.0.toDouble()
val prop16: Double = 1.2E-400
@@ -7372,6 +7372,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("floatLiteralOutOfRange.kt")
public void testFloatLiteralOutOfRange() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.kt");
doTest(fileName);
}
@TestMetadata("intOverflow.kt")
public void testIntOverflow() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/evaluate/intOverflow.kt");