diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/RandomGeneratorRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/RandomGeneratorRules.java index 694ae052c6..7f9f4ecb74 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/RandomGeneratorRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/RandomGeneratorRules.java @@ -31,6 +31,25 @@ static final class RandomGeneratorNextDouble { } } + /** + * Prefer {@link RandomGenerator#nextDouble(double origin, double bound)} over alternatives that + * may silently yield an ununiform domain of values. + */ + // XXX: This rule assumes that `a` is not an expensive or side-effectful expression. + // XXX: The replacement code throws an `IllegalArgumentException` in more cases than the original + // code, but only in situations that are likely unintended. + static final class RandomGeneratorNextDoubleWithOrigin { + @BeforeTemplate + double before(RandomGenerator random, double a, double b) { + return a + random.nextDouble(b); + } + + @AfterTemplate + double after(RandomGenerator random, double a, double b) { + return random.nextDouble(a, a + b); + } + } + /** Prefer {@link RandomGenerator#nextInt(int)} over more contrived alternatives. */ static final class RandomGeneratorNextInt { @BeforeTemplate @@ -46,6 +65,25 @@ int after(RandomGenerator random, int bound) { } } + /** + * Prefer {@link RandomGenerator#nextInt(int origin, int bound)} over alternatives that may + * silently yield values outside the intended domain. + */ + // XXX: This rule assumes that `a` is not an expensive or side-effectful expression. + // XXX: The replacement code throws an `IllegalArgumentException` in more cases than the original + // code, but only in situations that are likely unintended. + static final class RandomGeneratorNextIntWithOrigin { + @BeforeTemplate + int before(RandomGenerator random, int a, int b) { + return a + random.nextInt(b); + } + + @AfterTemplate + int after(RandomGenerator random, int a, int b) { + return random.nextInt(a, a + b); + } + } + /** * Prefer {@link RandomGenerator#nextLong(long)} over more contrived alternatives. * @@ -75,4 +113,23 @@ long after(RandomGenerator random, long bound) { return random.nextLong(bound); } } + + /** + * Prefer {@link RandomGenerator#nextLong(long origin, long bound)} over more contrived + * alternatives. + */ + // XXX: This rule assumes that `a` is not an expensive or side-effectful expression. + // XXX: The replacement code throws an `IllegalArgumentException` in more cases than the original + // code, but only in situations that are likely unintended. + static final class RandomGeneratorNextLongWithOrigin { + @BeforeTemplate + long before(RandomGenerator random, long a, long b) { + return a + random.nextLong(b); + } + + @AfterTemplate + long after(RandomGenerator random, long a, long b) { + return random.nextLong(a, a + b); + } + } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestInput.java index af0bf755ee..38ddef4343 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestInput.java @@ -15,11 +15,19 @@ ImmutableSet testRandomGeneratorNextDouble() { new SecureRandom().nextDouble() * 3.0); } + double testRandomGeneratorNextDoubleWithOrigin() { + return 1.0 + new Random().nextDouble(2.0); + } + ImmutableSet testRandomGeneratorNextInt() { return ImmutableSet.of( (int) new Random().nextDouble(1), (int) Math.round(new SplittableRandom().nextDouble(2))); } + int testRandomGeneratorNextIntWithOrigin() { + return 1 + new Random().nextInt(2); + } + ImmutableSet testRandomGeneratorNextLong() { return ImmutableSet.of( (long) new Random().nextDouble((double) 1L), @@ -27,4 +35,8 @@ ImmutableSet testRandomGeneratorNextLong() { (long) new SecureRandom().nextDouble(3L), Math.round(ThreadLocalRandom.current().nextDouble(4L))); } + + long testRandomGeneratorNextLongWithOrigin() { + return 1L + new Random().nextLong(2L); + } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestOutput.java index a12c163ac0..ba1ffec208 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/RandomGeneratorRulesTestOutput.java @@ -15,10 +15,18 @@ ImmutableSet testRandomGeneratorNextDouble() { new SecureRandom().nextDouble(3.0)); } + double testRandomGeneratorNextDoubleWithOrigin() { + return new Random().nextDouble(1.0, 1.0 + 2.0); + } + ImmutableSet testRandomGeneratorNextInt() { return ImmutableSet.of(new Random().nextInt(1), new SplittableRandom().nextInt(2)); } + int testRandomGeneratorNextIntWithOrigin() { + return new Random().nextInt(1, 1 + 2); + } + ImmutableSet testRandomGeneratorNextLong() { return ImmutableSet.of( new Random().nextLong(1L), @@ -26,4 +34,8 @@ ImmutableSet testRandomGeneratorNextLong() { new SecureRandom().nextLong(3L), ThreadLocalRandom.current().nextLong(4L)); } + + long testRandomGeneratorNextLongWithOrigin() { + return new Random().nextLong(1L, 1L + 2L); + } } diff --git a/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/RequiresComputation.java b/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/RequiresComputation.java index 7ccc96fc6c..6c84f740a4 100644 --- a/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/RequiresComputation.java +++ b/refaster-support/src/main/java/tech/picnic/errorprone/refaster/matchers/RequiresComputation.java @@ -14,7 +14,7 @@ import com.sun.source.tree.TypeCastTree; import com.sun.source.tree.UnaryTree; -/** A matcher of expressions that may a non-trivial amount of computation. */ +/** A matcher of expressions that may require a non-trivial amount of computation. */ public final class RequiresComputation implements Matcher { private static final long serialVersionUID = 1L;