From 935f7b1cc1116d6211c1a459ad08b9254079c5eb Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 7 Feb 2017 16:08:42 +0300 Subject: [PATCH] Add warning if constant conforms to infinity or zero #KT-3805 Fixed --- .../jetbrains/kotlin/diagnostics/Errors.java | 4 +++- .../rendering/DefaultErrorMessages.java | 4 +++- .../evaluate/ConstantExpressionEvaluator.kt | 23 +++++++++++++++++-- .../tests/evaluate/floatLiteralOutOfRange.kt | 21 +++++++++++++++++ .../tests/evaluate/floatLiteralOutOfRange.txt | 3 +++ .../evaluate/constant/floatsAndDoubles.kt | 21 +++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ 7 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.kt create mode 100644 compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index d89e9b346fd..b06e07cd4b4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -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 WRONG_LONG_SUFFIX = DiagnosticFactory0.create(ERROR, LONG_LITERAL_SUFFIX); DiagnosticFactory0 INT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 FLOAT_LITERAL_OUT_OF_RANGE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 FLOAT_LITERAL_CONFORMS_INFINITY = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 FLOAT_LITERAL_CONFORMS_ZERO = DiagnosticFactory0.create(WARNING); DiagnosticFactory2 CONSTANT_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); DiagnosticFactory0 INCORRECT_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 EMPTY_CHARACTER_LITERAL = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7b1264c80ab..38f5ee5dd26 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -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"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 1df918d5dd1..5271848cc48 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -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<*>? { diff --git a/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.kt b/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.kt new file mode 100644 index 00000000000..118c1e4fb4e --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNUSED_EXPRESSION + +fun test() { + 1.2E400F + 1.2E-400F + 11111111111111111111111111111111111111111111111111111111111111111F + 0.000000000000000000000000000000000000000000000000000000000000001F + 0.000000000000000000000000000000000000001000000000000000000000000F + + 1.2E400f + 1.2E-400f + 11111111111111111111111111111111111111111111111111111111111111111f + 0.000000000000000000000000000000000000000000000000000000000000001f + 0.000000000000000000000000000000000000001000000000000000000000000f + + val d1: Double = 1.2E400 + val d2: Double = 1.2E-400 + val d3: Double = 11111111111111111111111111111111111111111111111111111111111111111.0 + val d4: Double = 0.000000000000000000000000000000000000000000000000000000000000001 + val d5: Double = 0.000000000000000000000000000000000000001000000000000000000000000 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.txt b/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.txt new file mode 100644 index 00000000000..93e27f34c8c --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/floatLiteralOutOfRange.txt @@ -0,0 +1,3 @@ +package + +public fun test(): kotlin.Unit diff --git a/compiler/testData/evaluate/constant/floatsAndDoubles.kt b/compiler/testData/evaluate/constant/floatsAndDoubles.kt index acb3e85ca2f..8be0759460c 100644 --- a/compiler/testData/evaluate/constant/floatsAndDoubles.kt +++ b/compiler/testData/evaluate/constant/floatsAndDoubles.kt @@ -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 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0b111f92fb8..f1387b3c1e4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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");