From 66ebebbe35728349e12e6fa7bf3f55c557a841c4 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sun, 22 Oct 2017 15:25:40 +0200 Subject: [PATCH] Introduce a `CanonicalAnnotationSyntax` check While there, clean up some existing code. --- .../CanonicalAnnotationSyntaxCheck.java | 105 +++++ ...phicalAnnotationAttributeListingCheck.java | 28 ++ .../BoxingComparisonCheckTest.java | 366 +++++++++--------- .../CanonicalAnnotationSyntaxCheckTest.java | 112 ++++++ .../bugpatterns/EmptyMethodCheckTest.java | 6 +- 5 files changed, 438 insertions(+), 179 deletions(-) create mode 100644 error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheck.java create mode 100644 error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingCheck.java create mode 100644 error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheckTest.java diff --git a/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheck.java b/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheck.java new file mode 100644 index 00000000..b66be22a --- /dev/null +++ b/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheck.java @@ -0,0 +1,105 @@ +package com.picnicinternational.errorprone.bugpatterns; + +import static com.google.common.base.Verify.verify; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.ProvidesFix; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.BugPattern.StandardTags; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher; +import com.google.errorprone.fixes.Fix; +import com.google.errorprone.fixes.SuggestedFix; +import com.google.errorprone.matchers.Description; +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.Tree.Kind; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; + +// XXX: Drop redundant curly braces. +// XXX: Also flag/drop trailing commas? +@AutoService(BugChecker.class) +@BugPattern( + name = "CanonicalAnnotationSyntax", + summary = "Omit redundant syntax from annotation declarations", + severity = SeverityLevel.SUGGESTION, + tags = StandardTags.STYLE, + providesFix = ProvidesFix.REQUIRES_HUMAN_ATTENTION +) +public final class CanonicalAnnotationSyntaxCheck extends BugChecker + implements AnnotationTreeMatcher { + private static final ImmutableSet>> + FIX_FACTORIES = + ImmutableSet.of( + CanonicalAnnotationSyntaxCheck::dropRedundantParentheses, + CanonicalAnnotationSyntaxCheck::dropRedundantValueAttribute); + + @Override + public Description matchAnnotation(AnnotationTree tree, VisitorState state) { + return FIX_FACTORIES + .stream() + .map(op -> op.apply(tree, state)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .map(fix -> buildDescription(tree).addFix(fix).build()) + .orElse(Description.NO_MATCH); + } + + private static Optional dropRedundantParentheses(AnnotationTree tree, VisitorState state) { + if (!tree.getArguments().isEmpty()) { + /* Parentheses are necessary. */ + return Optional.empty(); + } + + String src = state.getSourceForNode(tree); + if (src == null) { + /* Without the source code there's not much we can do. */ + return Optional.empty(); + } + + int parenIndex = src.indexOf('('); + if (parenIndex < 0) { + /* There are no redundant parentheses. */ + return Optional.empty(); + } + + return Optional.of(SuggestedFix.replace(tree, src.substring(0, parenIndex))); + } + + private static Optional dropRedundantValueAttribute( + AnnotationTree tree, VisitorState state) { + List args = tree.getArguments(); + if (args.size() != 1) { + /* The `value` attribute, if specified, cannot be dropped. */ + return Optional.empty(); + } + + ExpressionTree arg = args.get(0); + if (arg.getKind() != Kind.ASSIGNMENT) { + verify( + arg.getKind() == Kind.IDENTIFIER, + "Unexpected type of expression: %s" + arg.getKind()); + return Optional.empty(); + } + + ExpressionTree variable = ((AssignmentTree) arg).getVariable(); + if (variable.getKind() != Kind.IDENTIFIER + || !((IdentifierTree) variable).getName().contentEquals("value") + || state.getSourceForNode(variable) == null) { + /* This is not an explicit assignment to the `value` attribute. */ + return Optional.empty(); + } + + /* Replace the assignment with just its value. */ + return Optional.of( + SuggestedFix.replace(arg, ((AssignmentTree) arg).getExpression().toString())); + } +} diff --git a/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingCheck.java b/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingCheck.java new file mode 100644 index 00000000..950d034d --- /dev/null +++ b/error-prone-contrib/src/main/java/com/picnicinternational/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingCheck.java @@ -0,0 +1,28 @@ +package com.picnicinternational.errorprone.bugpatterns; + +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.BugPattern.StandardTags; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher; +import com.google.errorprone.matchers.Description; +import com.sun.source.tree.AnnotationTree; + +// XXX: Add documentation. Explain that sorting reduces changes of conflicts and simplifies their resolution when they do happen. +// XXX: Add support for inclusions and exclusions. +// XXX: Disable until implemented. +//@AutoService(BugChecker.class) +@BugPattern( + name = "LexicographicalAnnotationAttributeListing", + summary = "Where possible, sort annotation array attributes lexicographically", + severity = SeverityLevel.SUGGESTION, + tags = StandardTags.STYLE +) +public final class LexicographicalAnnotationAttributeListingCheck extends BugChecker + implements AnnotationTreeMatcher { + @Override + public Description matchAnnotation(AnnotationTree tree, VisitorState state) { + return null; + } +} diff --git a/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/BoxingComparisonCheckTest.java b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/BoxingComparisonCheckTest.java index fa82a169..0f0f529a 100644 --- a/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/BoxingComparisonCheckTest.java +++ b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/BoxingComparisonCheckTest.java @@ -20,182 +20,6 @@ public final class BoxingComparisonCheckTest { // - During actual compilation only the first replacement is applied. // XXX: Can we perhaps work-around this by describing the fixes in reverse order? - @Test - public void testReplacementWithPrimitiveVariants() throws IOException { - refactoringTestHelper - .addInputLines( - "in/Test.java", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = Comparator.comparing(o -> (byte) 0);", - " Comparator cCmp = Comparator.comparing(o -> (char) 0);", - " Comparator sCmp = Comparator.comparing(o -> (short) 0);", - " Comparator iCmp = Comparator.comparing(o -> 0);", - " Comparator lCmp = Comparator.comparing(o -> 0L);", - " Comparator fCmp = Comparator.comparing(o -> 0.0f);", - " Comparator dCmp = Comparator.comparing(o -> 0.0);", - "", - " {", - " bCmp.thenComparing(o -> (byte) 0);", - " cCmp.thenComparing(o -> (char) 0);", - " sCmp.thenComparing(o -> (short) 0);", - " iCmp.thenComparing(o -> 0);", - " lCmp.thenComparing(o -> 0L);", - " fCmp.thenComparing(o -> 0.0f);", - " dCmp.thenComparing(o -> 0.0);", - " }", - "}") - .addOutputLines( - "out/Test.java", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = Comparator.comparingInt(o -> (byte) 0);", - " Comparator cCmp = Comparator.comparingInt(o -> (char) 0);", - " Comparator sCmp = Comparator.comparingInt(o -> (short) 0);", - " Comparator iCmp = Comparator.comparingInt(o -> 0);", - " Comparator lCmp = Comparator.comparingLong(o -> 0L);", - " Comparator fCmp = Comparator.comparingDouble(o -> 0.0f);", - " Comparator dCmp = Comparator.comparingDouble(o -> 0.0);", - "", - " {", - " bCmp.thenComparingInt(o -> (byte) 0);", - " cCmp.thenComparingInt(o -> (char) 0);", - " sCmp.thenComparingInt(o -> (short) 0);", - " iCmp.thenComparingInt(o -> 0);", - " lCmp.thenComparingLong(o -> 0L);", - " fCmp.thenComparingDouble(o -> 0.0f);", - " dCmp.thenComparingDouble(o -> 0.0);", - " }", - "}") - .doTest(); - } - - @Test - public void testReplacementWithBoxedVariants() throws IOException { - refactoringTestHelper - .addInputLines( - "in/Test.java", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = Comparator.comparingInt(o -> Byte.valueOf((byte) 0));", - " Comparator cCmp = Comparator.comparingInt(o -> Character.valueOf((char) 0));", - " Comparator sCmp = Comparator.comparingInt(o -> Short.valueOf((short) 0));", - " Comparator iCmp = Comparator.comparingInt(o -> Integer.valueOf(0));", - " Comparator lCmp = Comparator.comparingLong(o -> Long.valueOf(0));", - " Comparator fCmp = Comparator.comparingDouble(o -> Float.valueOf(0));", - " Comparator dCmp = Comparator.comparingDouble(o -> Double.valueOf(0));", - "", - " {", - " bCmp.thenComparingInt(o -> Byte.valueOf((byte) 0));", - " cCmp.thenComparingInt(o -> Character.valueOf((char) 0));", - " sCmp.thenComparingInt(o -> Short.valueOf((short) 0));", - " iCmp.thenComparingInt(o -> Integer.valueOf(0));", - " lCmp.thenComparingLong(o -> Long.valueOf(0));", - " fCmp.thenComparingDouble(o -> Float.valueOf(0));", - " dCmp.thenComparingDouble(o -> Double.valueOf(0));", - " }", - "}") - .addOutputLines( - "out/Test.java", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = Comparator.comparing(o -> Byte.valueOf((byte) 0));", - " Comparator cCmp = Comparator.comparing(o -> Character.valueOf((char) 0));", - " Comparator sCmp = Comparator.comparing(o -> Short.valueOf((short) 0));", - " Comparator iCmp = Comparator.comparing(o -> Integer.valueOf(0));", - " Comparator lCmp = Comparator.comparing(o -> Long.valueOf(0));", - " Comparator fCmp = Comparator.comparing(o -> Float.valueOf(0));", - " Comparator dCmp = Comparator.comparing(o -> Double.valueOf(0));", - "", - " {", - " bCmp.thenComparing(o -> Byte.valueOf((byte) 0));", - " cCmp.thenComparing(o -> Character.valueOf((char) 0));", - " sCmp.thenComparing(o -> Short.valueOf((short) 0));", - " iCmp.thenComparing(o -> Integer.valueOf(0));", - " lCmp.thenComparing(o -> Long.valueOf(0));", - " fCmp.thenComparing(o -> Float.valueOf(0));", - " dCmp.thenComparing(o -> Double.valueOf(0));", - " }", - "}") - .doTest(); - } - - @Test - public void testReplacementWithPrimitiveVariantsUsingStaticImports() throws IOException { - refactoringTestHelper - .addInputLines( - "in/Test.java", - "import static java.util.Comparator.comparing;", - "", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = comparing(o -> (byte) 0);", - " Comparator cCmp = comparing(o -> (char) 0);", - " Comparator sCmp = comparing(o -> (short) 0);", - " Comparator iCmp = comparing(o -> 0);", - " Comparator lCmp = comparing(o -> 0L);", - " Comparator fCmp = comparing(o -> 0.0f);", - " Comparator dCmp = comparing(o -> 0.0);", - "}") - .addOutputLines( - "out/Test.java", - "import static java.util.Comparator.comparing;", - "import static java.util.Comparator.comparingDouble;", - "import static java.util.Comparator.comparingInt;", - "import static java.util.Comparator.comparingLong;", - "", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = comparingInt(o -> (byte) 0);", - " Comparator cCmp = comparingInt(o -> (char) 0);", - " Comparator sCmp = comparingInt(o -> (short) 0);", - " Comparator iCmp = comparingInt(o -> 0);", - " Comparator lCmp = comparingLong(o -> 0L);", - " Comparator fCmp = comparingDouble(o -> 0.0f);", - " Comparator dCmp = comparingDouble(o -> 0.0);", - "}") - .doTest(); - } - - @Test - public void testReplacementWithBoxedVariantsUsingStaticImports() throws IOException { - refactoringTestHelper - .addInputLines( - "in/Test.java", - "import static java.util.Comparator.comparingDouble;", - "import static java.util.Comparator.comparingInt;", - "import static java.util.Comparator.comparingLong;", - "", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = comparingInt(o -> Byte.valueOf((byte) 0));", - " Comparator cCmp = comparingInt(o -> Character.valueOf((char) 0));", - " Comparator sCmp = comparingInt(o -> Short.valueOf((short) 0));", - " Comparator iCmp = comparingInt(o -> Integer.valueOf(0));", - " Comparator lCmp = comparingLong(o -> Long.valueOf(0));", - " Comparator fCmp = comparingDouble(o -> Float.valueOf(0));", - " Comparator dCmp = comparingDouble(o -> Double.valueOf(0));", - "}") - .addOutputLines( - "out/Test.java", - "import static java.util.Comparator.comparing;", - "import static java.util.Comparator.comparingDouble;", - "import static java.util.Comparator.comparingInt;", - "import static java.util.Comparator.comparingLong;", - "", - "import java.util.Comparator;", - "class Test {", - " Comparator bCmp = comparing(o -> Byte.valueOf((byte) 0));", - " Comparator cCmp = comparing(o -> Character.valueOf((char) 0));", - " Comparator sCmp = comparing(o -> Short.valueOf((short) 0));", - " Comparator iCmp = comparing(o -> Integer.valueOf(0));", - " Comparator lCmp = comparing(o -> Long.valueOf(0));", - " Comparator fCmp = comparing(o -> Float.valueOf(0));", - " Comparator dCmp = comparing(o -> Double.valueOf(0));", - "}") - .doTest(); - } - // The logic for `char` and `short` is exactly analogous to the `byte` case. @Test public void testByteComparison() { @@ -204,6 +28,7 @@ public final class BoxingComparisonCheckTest { "A.java", "import java.util.Comparator;", "import java.util.function.Function;", + "", "class A {", " {", " // BUG: Diagnostic contains:", @@ -293,6 +118,7 @@ public final class BoxingComparisonCheckTest { "import java.util.Comparator;", "import java.util.function.Function;", "import java.util.function.ToIntFunction;", + "", "class A {", " {", " // BUG: Diagnostic contains:", @@ -385,6 +211,7 @@ public final class BoxingComparisonCheckTest { "import java.util.Comparator;", "import java.util.function.Function;", "import java.util.function.ToLongFunction;", + "", "class A {", " {", " // BUG: Diagnostic contains:", @@ -460,6 +287,7 @@ public final class BoxingComparisonCheckTest { "A.java", "import java.util.Comparator;", "import java.util.function.Function;", + "", "class A {", " {", " // BUG: Diagnostic contains:", @@ -517,6 +345,7 @@ public final class BoxingComparisonCheckTest { "import java.util.Comparator;", "import java.util.function.Function;", "import java.util.function.ToDoubleFunction;", + "", "class A {", " {", " // BUG: Diagnostic contains:", @@ -576,6 +405,7 @@ public final class BoxingComparisonCheckTest { "A.java", "import java.util.Comparator;", "import java.util.function.Function;", + "", "class A {", " {", " Comparator.comparing(String::valueOf);", @@ -598,4 +428,188 @@ public final class BoxingComparisonCheckTest { "}") .doTest(); } + + @Test + public void testReplacementWithPrimitiveVariants() throws IOException { + refactoringTestHelper + .addInputLines( + "in/A.java", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = Comparator.comparing(o -> (byte) 0);", + " Comparator cCmp = Comparator.comparing(o -> (char) 0);", + " Comparator sCmp = Comparator.comparing(o -> (short) 0);", + " Comparator iCmp = Comparator.comparing(o -> 0);", + " Comparator lCmp = Comparator.comparing(o -> 0L);", + " Comparator fCmp = Comparator.comparing(o -> 0.0f);", + " Comparator dCmp = Comparator.comparing(o -> 0.0);", + "", + " {", + " bCmp.thenComparing(o -> (byte) 0);", + " cCmp.thenComparing(o -> (char) 0);", + " sCmp.thenComparing(o -> (short) 0);", + " iCmp.thenComparing(o -> 0);", + " lCmp.thenComparing(o -> 0L);", + " fCmp.thenComparing(o -> 0.0f);", + " dCmp.thenComparing(o -> 0.0);", + " }", + "}") + .addOutputLines( + "out/A.java", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = Comparator.comparingInt(o -> (byte) 0);", + " Comparator cCmp = Comparator.comparingInt(o -> (char) 0);", + " Comparator sCmp = Comparator.comparingInt(o -> (short) 0);", + " Comparator iCmp = Comparator.comparingInt(o -> 0);", + " Comparator lCmp = Comparator.comparingLong(o -> 0L);", + " Comparator fCmp = Comparator.comparingDouble(o -> 0.0f);", + " Comparator dCmp = Comparator.comparingDouble(o -> 0.0);", + "", + " {", + " bCmp.thenComparingInt(o -> (byte) 0);", + " cCmp.thenComparingInt(o -> (char) 0);", + " sCmp.thenComparingInt(o -> (short) 0);", + " iCmp.thenComparingInt(o -> 0);", + " lCmp.thenComparingLong(o -> 0L);", + " fCmp.thenComparingDouble(o -> 0.0f);", + " dCmp.thenComparingDouble(o -> 0.0);", + " }", + "}") + .doTest(); + } + + @Test + public void testReplacementWithBoxedVariants() throws IOException { + refactoringTestHelper + .addInputLines( + "in/A.java", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = Comparator.comparingInt(o -> Byte.valueOf((byte) 0));", + " Comparator cCmp = Comparator.comparingInt(o -> Character.valueOf((char) 0));", + " Comparator sCmp = Comparator.comparingInt(o -> Short.valueOf((short) 0));", + " Comparator iCmp = Comparator.comparingInt(o -> Integer.valueOf(0));", + " Comparator lCmp = Comparator.comparingLong(o -> Long.valueOf(0));", + " Comparator fCmp = Comparator.comparingDouble(o -> Float.valueOf(0));", + " Comparator dCmp = Comparator.comparingDouble(o -> Double.valueOf(0));", + "", + " {", + " bCmp.thenComparingInt(o -> Byte.valueOf((byte) 0));", + " cCmp.thenComparingInt(o -> Character.valueOf((char) 0));", + " sCmp.thenComparingInt(o -> Short.valueOf((short) 0));", + " iCmp.thenComparingInt(o -> Integer.valueOf(0));", + " lCmp.thenComparingLong(o -> Long.valueOf(0));", + " fCmp.thenComparingDouble(o -> Float.valueOf(0));", + " dCmp.thenComparingDouble(o -> Double.valueOf(0));", + " }", + "}") + .addOutputLines( + "out/A.java", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = Comparator.comparing(o -> Byte.valueOf((byte) 0));", + " Comparator cCmp = Comparator.comparing(o -> Character.valueOf((char) 0));", + " Comparator sCmp = Comparator.comparing(o -> Short.valueOf((short) 0));", + " Comparator iCmp = Comparator.comparing(o -> Integer.valueOf(0));", + " Comparator lCmp = Comparator.comparing(o -> Long.valueOf(0));", + " Comparator fCmp = Comparator.comparing(o -> Float.valueOf(0));", + " Comparator dCmp = Comparator.comparing(o -> Double.valueOf(0));", + "", + " {", + " bCmp.thenComparing(o -> Byte.valueOf((byte) 0));", + " cCmp.thenComparing(o -> Character.valueOf((char) 0));", + " sCmp.thenComparing(o -> Short.valueOf((short) 0));", + " iCmp.thenComparing(o -> Integer.valueOf(0));", + " lCmp.thenComparing(o -> Long.valueOf(0));", + " fCmp.thenComparing(o -> Float.valueOf(0));", + " dCmp.thenComparing(o -> Double.valueOf(0));", + " }", + "}") + .doTest(); + } + + @Test + public void testReplacementWithPrimitiveVariantsUsingStaticImports() throws IOException { + refactoringTestHelper + .addInputLines( + "in/A.java", + "import static java.util.Comparator.comparing;", + "", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = comparing(o -> (byte) 0);", + " Comparator cCmp = comparing(o -> (char) 0);", + " Comparator sCmp = comparing(o -> (short) 0);", + " Comparator iCmp = comparing(o -> 0);", + " Comparator lCmp = comparing(o -> 0L);", + " Comparator fCmp = comparing(o -> 0.0f);", + " Comparator dCmp = comparing(o -> 0.0);", + "}") + .addOutputLines( + "out/A.java", + "import static java.util.Comparator.comparing;", + "import static java.util.Comparator.comparingDouble;", + "import static java.util.Comparator.comparingInt;", + "import static java.util.Comparator.comparingLong;", + "", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = comparingInt(o -> (byte) 0);", + " Comparator cCmp = comparingInt(o -> (char) 0);", + " Comparator sCmp = comparingInt(o -> (short) 0);", + " Comparator iCmp = comparingInt(o -> 0);", + " Comparator lCmp = comparingLong(o -> 0L);", + " Comparator fCmp = comparingDouble(o -> 0.0f);", + " Comparator dCmp = comparingDouble(o -> 0.0);", + "}") + .doTest(); + } + + @Test + public void testReplacementWithBoxedVariantsUsingStaticImports() throws IOException { + refactoringTestHelper + .addInputLines( + "in/A.java", + "import static java.util.Comparator.comparingDouble;", + "import static java.util.Comparator.comparingInt;", + "import static java.util.Comparator.comparingLong;", + "", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = comparingInt(o -> Byte.valueOf((byte) 0));", + " Comparator cCmp = comparingInt(o -> Character.valueOf((char) 0));", + " Comparator sCmp = comparingInt(o -> Short.valueOf((short) 0));", + " Comparator iCmp = comparingInt(o -> Integer.valueOf(0));", + " Comparator lCmp = comparingLong(o -> Long.valueOf(0));", + " Comparator fCmp = comparingDouble(o -> Float.valueOf(0));", + " Comparator dCmp = comparingDouble(o -> Double.valueOf(0));", + "}") + .addOutputLines( + "out/A.java", + "import static java.util.Comparator.comparing;", + "import static java.util.Comparator.comparingDouble;", + "import static java.util.Comparator.comparingInt;", + "import static java.util.Comparator.comparingLong;", + "", + "import java.util.Comparator;", + "", + "class A {", + " Comparator bCmp = comparing(o -> Byte.valueOf((byte) 0));", + " Comparator cCmp = comparing(o -> Character.valueOf((char) 0));", + " Comparator sCmp = comparing(o -> Short.valueOf((short) 0));", + " Comparator iCmp = comparing(o -> Integer.valueOf(0));", + " Comparator lCmp = comparing(o -> Long.valueOf(0));", + " Comparator fCmp = comparing(o -> Float.valueOf(0));", + " Comparator dCmp = comparing(o -> Double.valueOf(0));", + "}") + .doTest(); + } } diff --git a/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheckTest.java b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheckTest.java new file mode 100644 index 00000000..ddac2ec5 --- /dev/null +++ b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/CanonicalAnnotationSyntaxCheckTest.java @@ -0,0 +1,112 @@ +package com.picnicinternational.errorprone.bugpatterns; + +import com.google.errorprone.BugCheckerRefactoringTestHelper; +import com.google.errorprone.CompilationTestHelper; +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class CanonicalAnnotationSyntaxCheckTest { + private final CompilationTestHelper compilationTestHelper = + CompilationTestHelper.newInstance(CanonicalAnnotationSyntaxCheck.class, getClass()); + private final BugCheckerRefactoringTestHelper refactoringTestHelper = + BugCheckerRefactoringTestHelper.newInstance( + new CanonicalAnnotationSyntaxCheck(), getClass()); + + @Test + public void testIdentification() { + compilationTestHelper + .addSourceLines( + "pkg/A.java", + "package pkg;", + "", + "import pkg.A.Foo;", + "", + "@Foo", + "interface A {", + " @interface Foo {", + " int value() default 0;", + " int value2() default 0;", + " }", + "", + " @pkg.A.Foo Object minimal1();", + " @A.Foo Object minimal2();", + " @Foo Object minimal3();", + "", + " // BUG: Diagnostic contains:", + " @pkg.A.Foo() Object functional1();", + " // BUG: Diagnostic contains:", + " @A.Foo() Object functional2();", + " // BUG: Diagnostic contains:", + " @Foo() Object functional3();", + "", + " @pkg.A.Foo(1) Object simple1();", + " @A.Foo(1) Object simple2();", + " @Foo(1) Object simple3();", + "", + " // BUG: Diagnostic contains:", + " @pkg.A.Foo(value = 1) Object verbose1();", + " // BUG: Diagnostic contains:", + " @A.Foo(value = 1) Object verbose2();", + " // BUG: Diagnostic contains:", + " @Foo(value = 1) Object verbose3();", + "", + " @pkg.A.Foo(value2 = 2) Object custom1();", + " @A.Foo(value2 = 2) Object custom2();", + " @Foo(value2 = 2) Object custom3();", + "", + " @pkg.A.Foo(value = 1, value2 = 2) Object extended1();", + " @A.Foo(value = 1, value2 = 2) Object extended2();", + " @Foo(value = 1, value2 = 2) Object extended3();", + "}") + .doTest(); + } + + @Test + public void testReplacement() throws IOException { + refactoringTestHelper + .addInputLines( + "in/pkg/A.java", + "package pkg;", + "", + "import pkg.A.Foo;", + "", + "interface A {", + " @interface Foo {", + " int value() default 0;", + " int value2() default 0;", + " }", + "", + " @pkg.A.Foo() Object functional1();", + " @A.Foo() Object functional2();", + " @Foo() Object functional3();", + "", + " @pkg.A.Foo(value = 1) Object verbose1();", + " @A.Foo(value = 1) Object verbose2();", + " @Foo(value = 1) Object verbose3();", + "}") + .addOutputLines( + "out/pkg/A.java", + "package pkg;", + "", + "import pkg.A.Foo;", + "", + "interface A {", + " @interface Foo {", + " int value() default 0;", + " int value2() default 0;", + " }", + "", + " @pkg.A.Foo Object functional1();", + " @A.Foo Object functional2();", + " @Foo Object functional3();", + "", + " @pkg.A.Foo(1) Object verbose1();", + " @A.Foo(1) Object verbose2();", + " @Foo(1) Object verbose3();", + "}") + .doTest(); + } +} diff --git a/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/EmptyMethodCheckTest.java b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/EmptyMethodCheckTest.java index 8454812d..0bd02bf2 100644 --- a/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/EmptyMethodCheckTest.java +++ b/error-prone-contrib/src/test/java/com/picnicinternational/errorprone/bugpatterns/EmptyMethodCheckTest.java @@ -7,12 +7,12 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class EmptyMethodCheckTest { - private final CompilationTestHelper testHelper = + private final CompilationTestHelper compilationTestHelper = CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass()); @Test public void testNegative() { - testHelper + compilationTestHelper .addSourceLines( "A.java", "class A {", @@ -33,7 +33,7 @@ public final class EmptyMethodCheckTest { @Test public void testPositive() { - testHelper + compilationTestHelper .addSourceLines( "A.java", "class A {",