diff --git a/.baseline/checkstyle/checkstyle.xml b/.baseline/checkstyle/checkstyle.xml index eab4bcf45..fb61b24fa 100644 --- a/.baseline/checkstyle/checkstyle.xml +++ b/.baseline/checkstyle/checkstyle.xml @@ -296,11 +296,6 @@ - - - - - diff --git a/baseline-error-prone/build.gradle b/baseline-error-prone/build.gradle index 1d4b7bc14..3ad5b47e9 100644 --- a/baseline-error-prone/build.gradle +++ b/baseline-error-prone/build.gradle @@ -6,6 +6,7 @@ dependencies { testCompile 'com.fasterxml.jackson.core:jackson-annotations' testCompile 'com.google.errorprone:error_prone_test_helpers' + testCompile 'com.palantir.safe-logging:preconditions' testCompile 'com.palantir.safe-logging:safe-logging' testCompile 'org.slf4j:slf4j-api' testCompile 'org.apache.commons:commons-lang3' diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormat.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormat.java new file mode 100755 index 000000000..09e06b7de --- /dev/null +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormat.java @@ -0,0 +1,62 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.Category; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.google.errorprone.matchers.Matchers; +import com.google.errorprone.matchers.method.MethodMatchers; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import java.util.regex.Pattern; + +@AutoService(BugChecker.class) +@BugPattern( + name = "GuavaPreconditionsMessageFormat", + category = Category.GUAVA, + severity = SeverityLevel.ERROR, + summary = "Guava Preconditions.checkX() methods must use print-f style formatting.") +public final class GuavaPreconditionsMessageFormat extends PreconditionsMessageFormat { + + private static final long serialVersionUID = 1L; + + private static final Matcher GUAVA_PRECONDITIONS_METHODS = + Matchers.anyOf( + MethodMatchers.staticMethod() + .onClassAny("com.google.common.base.Preconditions") + .withNameMatching(Pattern.compile("checkArgument|checkState|checkNotNull"))); + + public GuavaPreconditionsMessageFormat() { + super(GUAVA_PRECONDITIONS_METHODS); + } + + @Override + protected Description matchMessageFormat(MethodInvocationTree tree, String message, VisitorState state) { + if (!message.contains("{}")) { + return Description.NO_MATCH; + } + + return buildDescription(tree).setMessage( + "Use printf-style formatting in Guava Preconditions, not '{}' style formatting.").build(); + } +} diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormat.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormat.java new file mode 100755 index 000000000..b3a766a94 --- /dev/null +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormat.java @@ -0,0 +1,65 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.Category; +import com.google.errorprone.BugPattern.LinkType; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.google.errorprone.matchers.Matchers; +import com.google.errorprone.matchers.method.MethodMatchers; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import java.util.regex.Pattern; + +@AutoService(BugChecker.class) +@BugPattern( + name = "LogSafePreconditionsMessageFormat", + category = Category.ONE_OFF, + link = "https://github.com/palantir/gradle-baseline#baseline-error-prone-checks", + linkType = LinkType.CUSTOM, + severity = SeverityLevel.ERROR, + summary = "logsafe Preconditions.checkX() methods should not have print-f style formatting.") +public final class LogSafePreconditionsMessageFormat extends PreconditionsMessageFormat { + + private static final long serialVersionUID = 1L; + + private static final Matcher LOGSAFE_PRECONDITIONS_METHOD = + Matchers.anyOf( + MethodMatchers.staticMethod() + .onClassAny("com.palantir.logsafe.Preconditions") + .withNameMatching(Pattern.compile("checkArgument|checkState|checkNotNull"))); + + public LogSafePreconditionsMessageFormat() { + super(LOGSAFE_PRECONDITIONS_METHOD); + } + + @Override + protected Description matchMessageFormat(MethodInvocationTree tree, String message, VisitorState state) { + if (!message.contains("%s")) { + return Description.NO_MATCH; + } + + return buildDescription(tree).setMessage( + "Do not use printf-style formatting in logsafe Preconditions.").build(); + } +} diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsConstantMessage.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsConstantMessage.java index 6f39b9b7a..63a73e2f2 100644 --- a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsConstantMessage.java +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsConstantMessage.java @@ -35,7 +35,7 @@ @AutoService(BugChecker.class) @BugPattern( name = "PreconditionsConstantMessage", - category = Category.GUAVA, + category = Category.ONE_OFF, severity = SeverityLevel.ERROR, summary = "Allow only constant messages to Preconditions.checkX() methods") public final class PreconditionsConstantMessage extends BugChecker implements BugChecker.MethodInvocationTreeMatcher { @@ -45,7 +45,7 @@ public final class PreconditionsConstantMessage extends BugChecker implements Bu private static final Matcher PRECONDITIONS_METHOD = Matchers.anyOf( MethodMatchers.staticMethod() - .onClass("com.google.common.base.Preconditions") + .onClassAny("com.google.common.base.Preconditions", "com.palantir.logsafe.Preconditions") .withNameMatching(Pattern.compile("checkArgument|checkState|checkNotNull"))); private final Matcher compileTimeConstExpressionMatcher = diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsMessageFormat.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsMessageFormat.java new file mode 100755 index 000000000..3ae0b91cb --- /dev/null +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/PreconditionsMessageFormat.java @@ -0,0 +1,64 @@ +/* + * (c) Copyright 2017 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.LiteralTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.Tree; +import java.util.List; + +abstract class PreconditionsMessageFormat extends BugChecker implements BugChecker.MethodInvocationTreeMatcher { + + private final Matcher methodMatcher; + + protected PreconditionsMessageFormat(Matcher methodMatcher) { + this.methodMatcher = methodMatcher; + } + + protected abstract Description matchMessageFormat(MethodInvocationTree tree, String message, VisitorState state); + + @Override + public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { + if (!methodMatcher.matches(tree, state)) { + return Description.NO_MATCH; + } + + List args = tree.getArguments(); + if (args.size() <= 1) { + return Description.NO_MATCH; + } + + ExpressionTree messageArg = args.get(1); + if (!messageArg.getKind().equals(Tree.Kind.STRING_LITERAL)) { + return Description.NO_MATCH; + } + + String message; + try { + message = (String) ((LiteralTree) messageArg).getValue(); + } catch (ClassCastException exception) { + return Description.NO_MATCH; + } + + return matchMessageFormat(tree, message, state); + } +} diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormatTests.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormatTests.java new file mode 100755 index 000000000..39d372c0e --- /dev/null +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/GuavaPreconditionsMessageFormatTests.java @@ -0,0 +1,47 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.errorprone.CompilationTestHelper; +import org.junit.Before; +import org.junit.Test; + +public final class GuavaPreconditionsMessageFormatTests extends PreconditionsTests { + private CompilationTestHelper compilationHelper; + + @Before + public void before() { + compilationHelper = CompilationTestHelper.newInstance(GuavaPreconditionsMessageFormat.class, getClass()); + } + + @Override + public CompilationTestHelper compilationHelper() { + return compilationHelper; + } + + @Test + public void positive() throws Exception { + String diagnostic = "Use printf-style formatting"; + failGuava(diagnostic, "Preconditions.checkArgument(param != \"string\", \"message {}\", 123L);"); + failGuava(diagnostic, "Preconditions.checkState(param != \"string\", \"message {}\", 123L);"); + failGuava(diagnostic, "Preconditions.checkNotNull(param, \"message {}\", 123L);"); + + failGuava(diagnostic, "Preconditions.checkArgument(param != \"string\", \"message {} {}\", 'a', 'b');"); + failGuava(diagnostic, "Preconditions.checkState(param != \"string\", \"message {} {}\", 'a', 'b');"); + failGuava(diagnostic, "Preconditions.checkNotNull(param, \"message {} {}\", 'a', 'b');"); + } +} diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormatTests.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormatTests.java new file mode 100755 index 000000000..8a617fb30 --- /dev/null +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/LogSafePreconditionsMessageFormatTests.java @@ -0,0 +1,53 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.errorprone.CompilationTestHelper; +import org.junit.Before; +import org.junit.Test; + +public final class LogSafePreconditionsMessageFormatTests extends PreconditionsTests { + private CompilationTestHelper compilationHelper; + + @Before + public void before() { + compilationHelper = CompilationTestHelper.newInstance(LogSafePreconditionsMessageFormat.class, getClass()); + } + + @Override + public CompilationTestHelper compilationHelper() { + return compilationHelper; + } + + @Test + public void positive() throws Exception { + String diagnostic = "Do not use printf-style formatting"; + failLogSafe(diagnostic, "Preconditions.checkArgument(param != \"string\", \"message %s\"," + + " UnsafeArg.of(\"long\", 123L));"); + failLogSafe(diagnostic, "Preconditions.checkState(param != \"string\", \"message %s\"," + + " UnsafeArg.of(\"long\", 123L));"); + failLogSafe(diagnostic, "Preconditions.checkNotNull(param, \"message %s\"," + + " UnsafeArg.of(\"long\", 123L));"); + + failLogSafe(diagnostic, "Preconditions.checkArgument(param != \"string\", \"message %s %s\"," + + " UnsafeArg.of(\"char1\", 'a'), UnsafeArg.of(\"char2\", 'b'));"); + failLogSafe(diagnostic, "Preconditions.checkState(param != \"string\", \"message %s %s\"," + + " UnsafeArg.of(\"char1\", 'a'), UnsafeArg.of(\"char2\", 'b'));"); + failLogSafe(diagnostic, "Preconditions.checkNotNull(param, \"message %s %s\"," + + " UnsafeArg.of(\"char1\", 'a'), UnsafeArg.of(\"char2\", 'b'));"); + } +} diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsConstantMessageTests.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsConstantMessageTests.java index ef0789a80..27fc09fe4 100644 --- a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsConstantMessageTests.java +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsConstantMessageTests.java @@ -20,7 +20,7 @@ import org.junit.Before; import org.junit.Test; -public final class PreconditionsConstantMessageTests { +public final class PreconditionsConstantMessageTests extends PreconditionsTests { private CompilationTestHelper compilationHelper; @@ -29,121 +29,31 @@ public void before() { compilationHelper = CompilationTestHelper.newInstance(PreconditionsConstantMessage.class, getClass()); } - private void test(String call) throws Exception { - compilationHelper - .addSourceLines( - "Test.java", - "import com.google.common.base.Preconditions;", - "class Test {", - " void f(String param) {", - " // BUG: Diagnostic contains: non-constant message", - " " + call, - " }", - "}") - .doTest(); + @Override + public CompilationTestHelper compilationHelper() { + return compilationHelper; } @Test public void positive() throws Exception { - test("Preconditions.checkArgument(param != \"string\", \"constant\" + param);"); - test("Preconditions.checkState(param != \"string\", \"constant\" + param);"); - test("Preconditions.checkNotNull(param, \"constant\" + param);"); - - test("Preconditions.checkArgument(param != \"string\", String.format(\"constant %s\", param));"); - test("Preconditions.checkState(param != \"string\", String.format(\"constant %s\", param));"); - test("Preconditions.checkNotNull(param, String.format(\"constant %s\", param));"); + String diagnostic = "non-constant message"; + failGuava(diagnostic, "Preconditions.checkArgument(param != \"string\", \"constant\" + param);"); + failGuava(diagnostic, "Preconditions.checkState(param != \"string\", \"constant\" + param);"); + failGuava(diagnostic, "Preconditions.checkNotNull(param, \"constant\" + param);"); + + failGuava(diagnostic, + "Preconditions.checkArgument(param != \"string\", String.format(\"constant %s\", param));"); + failGuava(diagnostic, "Preconditions.checkState(param != \"string\", String.format(\"constant %s\", param));"); + failGuava(diagnostic, "Preconditions.checkNotNull(param, String.format(\"constant %s\", param));"); + + failLogSafe(diagnostic, "Preconditions.checkArgument(param != \"string\", \"constant\" + param);"); + failLogSafe(diagnostic, "Preconditions.checkState(param != \"string\", \"constant\" + param);"); + failLogSafe(diagnostic, "Preconditions.checkNotNull(param, \"constant\" + param);"); + + failLogSafe(diagnostic, + "Preconditions.checkArgument(param != \"string\", String.format(\"constant %s\", param));"); + failLogSafe(diagnostic, + "Preconditions.checkState(param != \"string\", String.format(\"constant %s\", param));"); + failLogSafe(diagnostic, "Preconditions.checkNotNull(param, String.format(\"constant %s\", param));"); } - - @Test - public void negative() throws Exception { - compilationHelper - .addSourceLines( - "Test.java", - "import com.google.common.base.Preconditions;", - "import java.util.Iterator;", - "class Test {", - " private static final String compileTimeConstant = \"constant\";", - " void f(boolean bArg, int iArg, Object oArg) {", - " Preconditions.checkArgument(bArg);", - " Preconditions.checkArgument(bArg, \"message\");", - " Preconditions.checkArgument(bArg, \"message %s\", 'a');", - " Preconditions.checkArgument(bArg, \"message %s\", 123);", - " Preconditions.checkArgument(bArg, \"message %s\", 123L);", - " Preconditions.checkArgument(bArg, \"message %s\", \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 'b');", - " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 123);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 123L);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 'a');", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 123);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 123L);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123, \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 'a');", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 123);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 123L);", - " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 'a');", - " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 123);", - " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 123L);", - " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", - " Preconditions.checkArgument(bArg, \"message %s %s %s %s\"," - + " \"msg\", \"msg\", \"msg\", \"msg\");", - "", - " Preconditions.checkState(iArg > 0);", - " Preconditions.checkState(iArg > 0, \"message\");", - " Preconditions.checkState(iArg > 0, \"message %s\", 'a');", - " Preconditions.checkState(iArg > 0, \"message %s\", 123);", - " Preconditions.checkState(iArg > 0, \"message %s\", 123L);", - " Preconditions.checkState(iArg > 0, \"message %s\", \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 'b');", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 123);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 123L);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 'a');", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 123);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 123L);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 'a');", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 123);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 123L);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 'a');", - " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 123);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 123L);", - " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", - " Preconditions.checkState(iArg > 0, \"message %s %s %s %s\"," - + " \"msg\", \"msg\", \"msg\", \"msg\");", - "", - " Preconditions.checkNotNull(oArg);", - " Preconditions.checkNotNull(oArg, \"message\");", - " Preconditions.checkNotNull(oArg, \"message %s\", 'a');", - " Preconditions.checkNotNull(oArg, \"message %s\", 123);", - " Preconditions.checkNotNull(oArg, \"message %s\", 123L);", - " Preconditions.checkNotNull(oArg, \"message %s\", \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 'b');", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 123);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 123L);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 'a');", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 123);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 123L);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 'a');", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 123);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 123L);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 'a');", - " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 123);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 123L);", - " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", - " Preconditions.checkNotNull(oArg, \"message %s %s %s %s\"," - + " \"msg\", \"msg\", \"msg\", \"msg\");", - " }", - "}") - .doTest(); - } - } diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsTests.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsTests.java new file mode 100755 index 000000000..4a62aeb55 --- /dev/null +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/PreconditionsTests.java @@ -0,0 +1,294 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.baseline.errorprone; + +import com.google.errorprone.CompilationTestHelper; +import org.junit.Test; + +public abstract class PreconditionsTests { + + public abstract CompilationTestHelper compilationHelper(); + + public final void failGuava(String diagnostic, String precondition) { + compilationHelper() + .addSourceLines( + "Test.java", + "import com.google.common.base.Preconditions;", + "class Test {", + " void f(String param) {", + " // BUG: Diagnostic contains: " + diagnostic, + " " + precondition, + " }", + "}") + .doTest(); + } + + public final void failLogSafe(String diagnostic, String precondition) { + compilationHelper() + .addSourceLines( + "Test.java", + "import com.palantir.logsafe.Preconditions;", + "import com.palantir.logsafe.UnsafeArg;", + "class Test {", + " void f(String param) {", + " // BUG: Diagnostic contains: " + diagnostic, + " " + precondition, + " }", + "}") + .doTest(); + } + + + @Test + public final void validGuava() throws Exception { + compilationHelper().addSourceLines( + "Test.java", + "import com.google.common.base.Preconditions;", + "import java.util.Iterator;", + "class Test {", + " private static final String compileTimeConstant = \"constant\";", + " void f(boolean bArg, int iArg, Object oArg) {", + " Preconditions.checkArgument(bArg);", + " Preconditions.checkArgument(bArg, \"message\");", + " Preconditions.checkArgument(bArg, \"message %s\", 'a');", + " Preconditions.checkArgument(bArg, \"message %s\", 123);", + " Preconditions.checkArgument(bArg, \"message %s\", 123L);", + " Preconditions.checkArgument(bArg, \"message %s\", \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 'b');", + " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 123);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', 123L);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 'a', \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 'a');", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 123);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123, 123L);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123, \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 'a');", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 123);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, 123L);", + " Preconditions.checkArgument(bArg, \"message %s %s\", 123L, \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 'a');", + " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 123);", + " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", 123L);", + " Preconditions.checkArgument(bArg, \"message %s %s\", \"msg\", \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", + " Preconditions.checkArgument(bArg, \"message %s %s %s %s\"," + + " \"msg\", \"msg\", \"msg\", \"msg\");", + "", + " Preconditions.checkState(iArg > 0);", + " Preconditions.checkState(iArg > 0, \"message\");", + " Preconditions.checkState(iArg > 0, \"message %s\", 'a');", + " Preconditions.checkState(iArg > 0, \"message %s\", 123);", + " Preconditions.checkState(iArg > 0, \"message %s\", 123L);", + " Preconditions.checkState(iArg > 0, \"message %s\", \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 'b');", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 123);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', 123L);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 'a', \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 'a');", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 123);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, 123L);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123, \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 'a');", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 123);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, 123L);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", 123L, \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 'a');", + " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 123);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", 123L);", + " Preconditions.checkState(iArg > 0, \"message %s %s\", \"msg\", \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", + " Preconditions.checkState(iArg > 0, \"message %s %s %s %s\"," + + " \"msg\", \"msg\", \"msg\", \"msg\");", + "", + " Preconditions.checkNotNull(oArg);", + " Preconditions.checkNotNull(oArg, \"message\");", + " Preconditions.checkNotNull(oArg, \"message %s\", 'a');", + " Preconditions.checkNotNull(oArg, \"message %s\", 123);", + " Preconditions.checkNotNull(oArg, \"message %s\", 123L);", + " Preconditions.checkNotNull(oArg, \"message %s\", \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 'b');", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 123);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', 123L);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 'a', \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 'a');", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 123);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, 123L);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123, \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 'a');", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 123);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, 123L);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", 123L, \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 'a');", + " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 123);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", 123L);", + " Preconditions.checkNotNull(oArg, \"message %s %s\", \"msg\", \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s %s\", \"msg\", \"msg\", \"msg\");", + " Preconditions.checkNotNull(oArg, \"message %s %s %s %s\"," + + " \"msg\", \"msg\", \"msg\", \"msg\");", + " }", + "}") + .doTest(); + } + + @Test + public final void validLogSafe() throws Exception { + compilationHelper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.Preconditions;", + "import com.palantir.logsafe.UnsafeArg;", + "import java.util.Iterator;", + "class Test {", + " private static final String compileTimeConstant = \"constant\";", + " void f(boolean bArg, int iArg, Object oArg) {", + " Preconditions.checkArgument(bArg);", + " Preconditions.checkArgument(bArg, \"message\");", + " Preconditions.checkArgument(bArg, \"message {}\", UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkArgument(bArg, \"message {}\", UnsafeArg.of(\"int\", 123));", + " Preconditions.checkArgument(bArg, \"message {}\", UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkArgument(bArg, \"message {}\", UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"char1\", 'a')," + + " UnsafeArg.of(\"char2\", 'b'));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkArgument(bArg, \"message {} {}\", UnsafeArg.of(\"string1\", \"msg\")," + + " UnsafeArg.of(\"string2\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {} {}\"," + + " UnsafeArg.of(\"string1\", \"msg\"), UnsafeArg.of(\"string2\", \"msg\")," + + " UnsafeArg.of(\"string3\", \"msg\"));", + " Preconditions.checkArgument(bArg, \"message {} {} {} {}\"," + + " UnsafeArg.of(\"string1\", \"msg\"), UnsafeArg.of(\"string2\", \"msg\")," + + " UnsafeArg.of(\"string3\", \"msg\"), UnsafeArg.of(\"string4\", \"msg\"));", + "", + " Preconditions.checkState(iArg > 0);", + " Preconditions.checkState(iArg > 0, \"message\");", + " Preconditions.checkState(iArg > 0, \"message {}\", UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkState(iArg > 0, \"message {}\", UnsafeArg.of(\"int\", 123));", + " Preconditions.checkState(iArg > 0, \"message {}\", UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkState(iArg > 0, \"message {}\", UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"char1\", 'a')," + + " UnsafeArg.of(\"char2\", 'b'));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkState(iArg > 0, \"message {} {}\", UnsafeArg.of(\"string1\", \"msg\")," + + " UnsafeArg.of(\"string2\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {} {}\"," + + " UnsafeArg.of(\"string1\", \"msg\"), UnsafeArg.of(\"string2\", \"msg\")," + + " UnsafeArg.of(\"string3\", \"msg\"));", + " Preconditions.checkState(iArg > 0, \"message {} {} {} {}\"," + + " UnsafeArg.of(\"string1\", \"msg\"), UnsafeArg.of(\"string2\", \"msg\")," + + " UnsafeArg.of(\"string3\", \"msg\"), UnsafeArg.of(\"string4\", \"msg\"));", + "", + " Preconditions.checkNotNull(oArg);", + " Preconditions.checkNotNull(oArg, \"message\");", + " Preconditions.checkNotNull(oArg, \"message {}\", UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkNotNull(oArg, \"message {}\", UnsafeArg.of(\"int\", 123));", + " Preconditions.checkNotNull(oArg, \"message {}\", UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkNotNull(oArg, \"message {}\", UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"char1\", 'a')," + + " UnsafeArg.of(\"char2\", 'b'));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"char\", 'a')," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"int\", 123)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"long\", 123L)," + + " UnsafeArg.of(\"string\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"char\", 'a'));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"int\", 123));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"string\", \"msg\")," + + " UnsafeArg.of(\"long\", 123L));", + " Preconditions.checkNotNull(oArg, \"message {} {}\", UnsafeArg.of(\"string1\", \"msg\")," + + " UnsafeArg.of(\"string2\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {} {}\", UnsafeArg.of(\"string1\", \"msg\")," + + " UnsafeArg.of(\"string2\", \"msg\"), UnsafeArg.of(\"string3\", \"msg\"));", + " Preconditions.checkNotNull(oArg, \"message {} {} {} {}\"," + + " UnsafeArg.of(\"string1\", \"msg\"), UnsafeArg.of(\"string2\", \"msg\")," + + " UnsafeArg.of(\"string3\", \"msg\"), UnsafeArg.of(\"string4\", \"msg\"));", + " }", + "}") + .doTest(); + } +} diff --git a/gradle-baseline-java-config/resources/checkstyle/checkstyle.xml b/gradle-baseline-java-config/resources/checkstyle/checkstyle.xml index 5b5545897..103b7e003 100644 --- a/gradle-baseline-java-config/resources/checkstyle/checkstyle.xml +++ b/gradle-baseline-java-config/resources/checkstyle/checkstyle.xml @@ -81,6 +81,7 @@ @@ -296,11 +297,6 @@ - - - - - diff --git a/versions.props b/versions.props index 2bb3c0aa0..45c1ba64a 100644 --- a/versions.props +++ b/versions.props @@ -4,7 +4,7 @@ com.google.errorprone:error_prone_core = 2.0.19 com.google.errorprone:error_prone_test_helpers = 2.0.19 com.google.guava:guava = 21.0 com.palantir.baseline:* = 0.17.1 -com.palantir.safe-logging:safe-logging = 0.1.3 +com.palantir.safe-logging:* = 1.1.1 org.slf4j:slf4j-api = 1.7.24 net.ltgt.gradle:gradle-errorprone-plugin = 0.0.12