[FIR] Implement DIVISION_BY_ZERO diagnostics, fix tests
This commit is contained in:
committed by
TeamCityServer
parent
964bba3530
commit
847ab40707
+1
-1
@@ -58,7 +58,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
RETURN_WITH_LABEL,
|
||||
INT_LITERAL_OUT_OF_RANGE,
|
||||
FLOAT_LITERAL_OUT_OF_RANGE,
|
||||
LONG_LITERAL_SUFFIX,
|
||||
LONG_LITERAL_SUFFIX
|
||||
|
||||
;
|
||||
|
||||
|
||||
+1
@@ -64,6 +64,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val INT_LITERAL_OUT_OF_RANGE by error<FirSourceElement, PsiElement>()
|
||||
val FLOAT_LITERAL_OUT_OF_RANGE by error<FirSourceElement, PsiElement>()
|
||||
val WRONG_LONG_SUFFIX by error<FirSourceElement, KtElement>(PositioningStrategy.LONG_LITERAL_SUFFIX)
|
||||
val DIVISION_BY_ZERO by warning<FirSourceElement, KtExpression>()
|
||||
}
|
||||
|
||||
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
|
||||
|
||||
@@ -89,6 +89,7 @@ object FirErrors {
|
||||
val INT_LITERAL_OUT_OF_RANGE by error0<FirSourceElement, PsiElement>()
|
||||
val FLOAT_LITERAL_OUT_OF_RANGE by error0<FirSourceElement, PsiElement>()
|
||||
val WRONG_LONG_SUFFIX by error0<FirSourceElement, KtElement>(SourceElementPositioningStrategies.LONG_LITERAL_SUFFIX)
|
||||
val DIVISION_BY_ZERO by warning0<FirSourceElement, KtExpression>()
|
||||
|
||||
// Unresolved
|
||||
val HIDDEN by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object FirDivisionByZeroChecker : FirFunctionCallChecker() {
|
||||
private val defaultPackageName = FqName("kotlin")
|
||||
private val defaultDivName = Name.identifier("div")
|
||||
|
||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val firstValue = (expression.arguments.singleOrNull() as? FirConstExpression<*>)?.value
|
||||
if (firstValue != null && (firstValue == 0L || firstValue == 0.0f || firstValue == 0.0)) {
|
||||
val callableId =
|
||||
((expression.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId
|
||||
if (callableId != null && callableId.packageName == defaultPackageName && callableId.callableName == defaultDivName) {
|
||||
reporter.reportOn(expression.source, FirErrors.DIVISION_BY_ZERO, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -32,6 +32,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf(
|
||||
FirConventionFunctionCallChecker,
|
||||
FirDivisionByZeroChecker
|
||||
)
|
||||
|
||||
override val tryExpressionCheckers: Set<FirTryExpressionChecker> = setOf(
|
||||
|
||||
@@ -1217,7 +1217,8 @@ open class RawFirBuilder(
|
||||
this.source = source
|
||||
constructedTypeRef = delegatedType.copyWithNewSourceKind(FirFakeSourceElementKind.ImplicitTypeRef)
|
||||
this.isThis = isThis
|
||||
val calleeKind = if (isImplicit)FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
|
||||
val calleeKind =
|
||||
if (isImplicit) FirFakeSourceElementKind.ImplicitConstructor else FirFakeSourceElementKind.DelegatingConstructorCall
|
||||
val calleeSource = this@convert.calleeExpression?.toFirSourceElement(calleeKind)
|
||||
?: source.fakeElement(calleeKind)
|
||||
this.calleeReference = if (isThis) {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ fun test3() {}
|
||||
@Foo(c = [1f], b = [""], a = [1])
|
||||
fun test4() {}
|
||||
|
||||
@Foo([1 + 2], ["Hello, " + "Kotlin"], [1 / 0f])
|
||||
@Foo([1 + 2], ["Hello, " + "Kotlin"], [<!DIVISION_BY_ZERO!>1 / 0f<!>])
|
||||
fun test5() {}
|
||||
|
||||
const val ONE = 1
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ fun test1_2() {}
|
||||
@Ann2(*[])
|
||||
fun test2() {}
|
||||
|
||||
@Ann3(a = *[0f, 1 / 0f])
|
||||
@Ann3(a = *[0f, <!DIVISION_BY_ZERO!>1 / 0f<!>])
|
||||
fun test3() {}
|
||||
|
||||
@Ann5(Ann4(*["/"]))
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
val a1 = 0
|
||||
val a2 = 1 / 0
|
||||
val a2 = <!DIVISION_BY_ZERO!>1 / 0<!>
|
||||
val a3 = 1 / a1
|
||||
val a4 = 1 / a2
|
||||
val a5 = 2 * (1 / 0)
|
||||
val a5 = 2 * (<!DIVISION_BY_ZERO!>1 / 0<!>)
|
||||
|
||||
val a6 = 1.div(0)
|
||||
val a6 = <!DIVISION_BY_ZERO!>1.div(0)<!>
|
||||
val a7 = 1.div(a1)
|
||||
val a8 = 1.div(a2)
|
||||
val a9 = 2 * (1.div(0))
|
||||
val a9 = 2 * (<!DIVISION_BY_ZERO!>1.div(0)<!>)
|
||||
|
||||
val b1: Byte = 1 / 0
|
||||
@Ann(1 / 0) val b2 = 1
|
||||
val a10 = <!DIVISION_BY_ZERO!>1 / 0.0f<!>
|
||||
val a11 = <!DIVISION_BY_ZERO!>1 / 0.0<!>
|
||||
val a12 = <!DIVISION_BY_ZERO!>1L / 0<!>
|
||||
|
||||
annotation class Ann(val i : Int)
|
||||
val b1: Byte = <!DIVISION_BY_ZERO!>1 / 0<!>
|
||||
@Ann(<!DIVISION_BY_ZERO!>1 / 0<!>) val b2 = 1
|
||||
|
||||
annotation class Ann(val i : Int)
|
||||
|
||||
@@ -12,6 +12,10 @@ val a7 = <!DIVISION_BY_ZERO!>1.div(a1)<!>
|
||||
val a8 = 1.div(a2)
|
||||
val a9 = 2 * (<!DIVISION_BY_ZERO!>1.div(0)<!>)
|
||||
|
||||
val a10 = <!DIVISION_BY_ZERO!>1 / 0.0f<!>
|
||||
val a11 = <!DIVISION_BY_ZERO!>1 / 0.0<!>
|
||||
val a12 = <!DIVISION_BY_ZERO!>1L / 0<!>
|
||||
|
||||
val b1: Byte = <!DIVISION_BY_ZERO, TYPE_MISMATCH!>1 / 0<!>
|
||||
@Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, DIVISION_BY_ZERO!>1 / 0<!>) val b2 = 1
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package
|
||||
|
||||
public val a1: kotlin.Int = 0
|
||||
public val a10: kotlin.Float = Infinity.toFloat()
|
||||
public val a11: kotlin.Double = Infinity.toDouble()
|
||||
public val a12: kotlin.Long
|
||||
public val a2: kotlin.Int
|
||||
public val a3: kotlin.Int
|
||||
public val a4: kotlin.Int
|
||||
@@ -19,3 +22,4 @@ public final annotation class Ann : kotlin.Annotation {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -167,6 +167,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.DIVISION_BY_ZERO) { firDiagnostic ->
|
||||
DivisionByZeroImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.HIDDEN) { firDiagnostic ->
|
||||
HiddenImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir as FirDeclaration),
|
||||
|
||||
+4
@@ -136,6 +136,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = WrongLongSuffix::class
|
||||
}
|
||||
|
||||
abstract class DivisionByZero : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = DivisionByZero::class
|
||||
}
|
||||
|
||||
abstract class Hidden : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = Hidden::class
|
||||
abstract val hidden: KtSymbol
|
||||
|
||||
+7
@@ -194,6 +194,13 @@ internal class WrongLongSuffixImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class DivisionByZeroImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.DivisionByZero(), KtAbstractFirDiagnostic<KtExpression> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class HiddenImpl(
|
||||
override val hidden: KtSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
Reference in New Issue
Block a user