From 20211e00848badd77f3db879fc12864cc001f7a7 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 4 Dec 2017 10:03:42 +0700 Subject: [PATCH] LongRangeSet: fix for range[Long.MIN_VALUE..x] % point[Long.MIN_VALUE] --- .../dataFlow/rangeSet/LongRangeSet.java | 4 +++- .../dataFlow/rangeSet/LongRangeSetTest.java | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/rangeSet/LongRangeSet.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/rangeSet/LongRangeSet.java index 996f27e22344..0f9fea57dad3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/rangeSet/LongRangeSet.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/rangeSet/LongRangeSet.java @@ -737,7 +737,9 @@ public abstract class LongRangeSet { @Override public LongRangeSet mod(LongRangeSet divisor) { if (divisor.isEmpty() || divisor.equals(point(0))) return empty(); - if (divisor instanceof Point && ((Point)divisor).myValue == Long.MIN_VALUE) return this; + if (divisor instanceof Point && ((Point)divisor).myValue == Long.MIN_VALUE) { + return this.contains(Long.MIN_VALUE) ? this.subtract(divisor).union(point(0)) : this; + } if (divisor.contains(Long.MIN_VALUE)) { return possibleMod(); } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/rangeSet/LongRangeSetTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/rangeSet/LongRangeSetTest.java index c1525e7989cc..77788804167c 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/rangeSet/LongRangeSetTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/dataFlow/rangeSet/LongRangeSetTest.java @@ -23,6 +23,7 @@ import org.junit.Test; import java.util.Random; import java.util.function.Function; +import java.util.stream.Collectors; import static com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet.*; import static org.junit.Assert.*; @@ -321,16 +322,23 @@ public class LongRangeSetTest { checkMod(range(0, 10).union(range(30, 50)), range(-20, -10).union(range(15, 25)), "{0..24}"); checkMod(point(10), point(0), "{}"); checkMod(range(0, 10), point(0), "{}"); + checkMod(range(Long.MIN_VALUE, Long.MIN_VALUE + 3), point(Long.MIN_VALUE), "{-9223372036854775807..-9223372036854775805, 0}"); + checkMod(range(Long.MAX_VALUE - 3, Long.MAX_VALUE), point(Long.MAX_VALUE), "{0..9223372036854775806}"); } - void checkMod(LongRangeSet dividentRange, LongRangeSet divisorRange, String expected) { - LongRangeSet result = dividentRange.mod(divisorRange); + void checkMod(LongRangeSet dividendRange, LongRangeSet divisorRange, String expected) { + LongRangeSet result = dividendRange.mod(divisorRange); assertEquals(expected, result.toString()); - assertTrue( - dividentRange.stream() - .mapToObj(divident -> divisorRange.stream() - .filter(divisor -> divisor != 0).map(divisor -> divident % divisor)).flatMapToLong(Function.identity()) - .allMatch(result::contains)); + String errors = dividendRange.stream() + .mapToObj(dividend -> divisorRange.stream() + .filter(divisor -> divisor != 0) + .filter(divisor -> !result.contains(dividend % divisor)) + .mapToObj(divisor -> dividend + " % " + divisor + " = " + (dividend % divisor))) + .flatMap(Function.identity()) + .collect(Collectors.joining("\n")); + if (!errors.isEmpty()) { + fail("Expected range " + expected + " is not satisfied:\n" + errors); + } } @Test