From 789fdc06c6936cdac12d150d0ffcc8a85086fb77 Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Mon, 6 Oct 2025 12:49:17 +0200 Subject: [PATCH] [java-inspection] IJ-CR-177592 IDEA-375813 It seems dataflow join works wrong for branching with division by zero - added descriptions and a new option GitOrigin-RevId: 4d105d96b1b8fd0bae8560134479c959aaaa7d20 --- .../InspectionGadgetsBundle.properties | 3 +++ .../ig/numeric/DivideByZeroInspection.java | 27 +++++++++++++++++-- .../inspectionDescriptions/DivideByZero.html | 3 ++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties index 1bf2c195962f..6cfc593056cc 100644 --- a/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties +++ b/java/java-analysis-impl/resources/messages/InspectionGadgetsBundle.properties @@ -849,6 +849,9 @@ comparison.of.short.and.char.problem.descriptor=Equality comparison #ref#ref() between BigDecimal values should probably be 'compareTo()' #loc divide.by.zero.problem.descriptor=Division by zero #loc divide.by.zero.problem.may.descriptor=Maybe division by zero #loc +divide.by.zero.problem.may.option=Report conditional divide-by-zero +divide.by.zero.problem.may.option.description=Highlights divisions that can become zero in some execution branches +divide.by.zero.problem.may.option.disabled=Don't suggest conditional divide-by-zero problems non.reproducible.math.call.problem.descriptor=Math.#ref() may produce non-reproducible results #loc constant.math.call.problem.descriptor=Constant call to #ref() can be simplified #loc floating.point.equality.problem.descriptor=#ref: floating-point values compared for exact equality #loc diff --git a/java/java-analysis-impl/src/com/siyeh/ig/numeric/DivideByZeroInspection.java b/java/java-analysis-impl/src/com/siyeh/ig/numeric/DivideByZeroInspection.java index 2418b0f36c46..36b0a8b77cd1 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/numeric/DivideByZeroInspection.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/numeric/DivideByZeroInspection.java @@ -17,10 +17,12 @@ package com.siyeh.ig.numeric; import com.intellij.codeInspection.CommonQuickFixBundle; import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.UpdateInspectionOptionFix; import com.intellij.codeInspection.dataFlow.CommonDataflow; import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet; import com.intellij.codeInspection.dataFlow.types.DfIntType; import com.intellij.codeInspection.dataFlow.types.DfType; +import com.intellij.codeInspection.options.OptPane; import com.intellij.modcommand.ModPsiUpdater; import com.intellij.modcommand.PsiUpdateModCommandQuickFix; import com.intellij.openapi.project.Project; @@ -41,8 +43,23 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.codeInspection.options.OptPane.checkbox; +import static com.intellij.codeInspection.options.OptPane.pane; + public final class DivideByZeroInspection extends BaseInspection { + + @SuppressWarnings("PublicField") + public boolean reportMayBeZero = true; + + @Override + public @NotNull OptPane getOptionsPane() { + return pane( + checkbox("reportMayBeZero", + InspectionGadgetsBundle.message("divide.by.zero.problem.may.option")) + .description(InspectionGadgetsBundle.message("divide.by.zero.problem.may.option.description"))); + } + @Pattern(VALID_ID_PATTERN) @Override public @NotNull String getID() { @@ -69,6 +86,11 @@ public final class DivideByZeroInspection extends BaseInspection { } } } + if (infos.length > 1 && infos[1] instanceof ThreeState threeState && threeState == ThreeState.UNSURE) { + return LocalQuickFix.from(new UpdateInspectionOptionFix( + this, "reportMayBeZero", + InspectionGadgetsBundle.message("divide.by.zero.problem.may.option.disabled", false), false)); + } return null; } @@ -77,7 +99,7 @@ public final class DivideByZeroInspection extends BaseInspection { return new DivisionByZeroVisitor(); } - private static class DivisionByZeroVisitor extends BaseInspectionVisitor { + private class DivisionByZeroVisitor extends BaseInspectionVisitor { @Override public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) { @@ -112,7 +134,7 @@ public final class DivideByZeroInspection extends BaseInspection { } } - private static ThreeState isZero(PsiExpression expression) { + private ThreeState isZero(PsiExpression expression) { final Object value = ConstantExpressionUtil.computeCastTo(expression, PsiTypes.doubleType()); if (value instanceof Double) { final double constantValue = ((Double)value).doubleValue(); @@ -123,6 +145,7 @@ public final class DivideByZeroInspection extends BaseInspection { if (val != null) { return val.doubleValue() == 0.0 ? ThreeState.YES : ThreeState.NO; } + if(!reportMayBeZero) return ThreeState.NO; if (dfType instanceof DfIntType dfIntType) { LongRangeSet range = dfIntType.getRange(); List ranges = range.asRanges(); diff --git a/java/java-impl/resources/inspectionDescriptions/DivideByZero.html b/java/java-impl/resources/inspectionDescriptions/DivideByZero.html index a041cde9df5c..ae94a3839bfa 100644 --- a/java/java-impl/resources/inspectionDescriptions/DivideByZero.html +++ b/java/java-impl/resources/inspectionDescriptions/DivideByZero.html @@ -5,6 +5,7 @@ Such expressions will produce an Infinity, -Infinity o and will throw an ArithmeticException for integers.

When the expression has a NaN result, the fix suggests replacing the division expression with the NaN constant. - +

Use the Report conditional divide-by-zero option to report divisions where the divisor may be zero in some execution paths. + This may occasionally produce false positives. \ No newline at end of file