Skip to content

Commit

Permalink
Add DateTimeExampleStringCheck ErrorProne plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
fluentfuture committed Dec 16, 2023
1 parent 1033c4b commit e870756
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
2 changes: 2 additions & 0 deletions mug-errorprone/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ java_library(
"@maven//:com_google_errorprone_error_prone_check_api",
"@maven//:com_google_guava_guava",
"//mug:base",
"//mug:time",
"//mug-guava",
],
)
Expand Down Expand Up @@ -66,6 +67,7 @@ junit_tests(
deps = [
":errorprone",
"//mug:format",
"//mug:time",
"//mug-guava:safe_sql",
"@maven//:com_google_guava_guava",
"@maven//:com_google_guava_guava_testlib",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.google.mu.errorprone;

import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import static com.google.errorprone.matchers.Matchers.staticMethod;

import com.google.auto.service.AutoService;
import com.google.mu.time.DateTimeFormats;
import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.LinkType;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;

/** Validate the example datetime string passed to {@code DateTimeFormats.formatOf()}. */
@BugPattern(
summary = "Checks that the format string passed to DateTimeFormats.formatOf() is supported.",
link = "go/java-tips/024#safer-string-format-reuse",
linkType = LinkType.CUSTOM,
severity = ERROR)
@AutoService(BugChecker.class)
public final class DateTimeExampleStringCheck extends AbstractBugChecker
implements AbstractBugChecker.MethodInvocationCheck {
private static final Matcher<ExpressionTree> MATCHER =
staticMethod().onClass("com.google.mu.time.DateTimeFormats").named("formatOf");

@Override
public void checkMethodInvocation(MethodInvocationTree tree, VisitorState state)
throws ErrorReport {
if (!MATCHER.matches(tree, state) || tree.getArguments().isEmpty()) {
return;
}
ExpressionTree exampleArg = tree.getArguments().get(0);
String exampleString = ASTHelpers.constValue(exampleArg, String.class);
checkingOn(exampleArg).require(exampleString != null, "compile-time string constant expected");
try {
Object verified = DateTimeFormats.formatOf(exampleString);
} catch (IllegalArgumentException e) {
throw checkingOn(exampleArg).report(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.google.mu.errorprone;

import com.google.errorprone.CompilationTestHelper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class DateTimeExampleStringCheckTest {
private final CompilationTestHelper helper =
CompilationTestHelper.newInstance(DateTimeExampleStringCheck.class, getClass());

@Test
public void mmddyyNotSupported() {
helper
.addSourceLines(
"Test.java",
"import static com.google.mu.time.DateTimeFormats.formatOf;",
"import java.time.format.DateTimeFormatter;",
"class Test {",
" private static final DateTimeFormatter FORMAT = formatOf(",
" // BUG: Diagnostic contains: unsupported date time example: 10/20/2023",
" \"10/20/2023 10:10:10\");",
"}")
.doTest();
}
}
9 changes: 9 additions & 0 deletions mug/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ java_library(
"src/main/java/com/google/mu/util/*.java",
"src/main/java/com/google/mu/util/stream/*.java",
"src/main/java/com/google/mu/function/*.java",
"src/main/java/com/google/mu/collect/*.java",
],
exclude = ["src/main/java/com/google/mu/util/StringFormat.java"]),
)
Expand All @@ -31,6 +32,14 @@ java_library(
exported_plugins = ["//mug-errorprone:plugin"],
)

java_library(
name = "time",
visibility = ["//visibility:public"],
srcs = glob(["src/main/java/com/google/mu/time/*.java"]),
deps = [":base"],
exported_plugins = ["//mug-errorprone:plugin"],
)

load("@com_googlesource_gerrit_bazlets//tools:junit.bzl", "junit_tests")

java_library(
Expand Down
4 changes: 2 additions & 2 deletions mug/src/main/java/com/google/mu/time/DateTimeFormats.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static DateTimeFormatter inferFromExample(String example) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
fmt.parse(example);
return fmt;
} catch (DateTimeParseException | IllegalArgumentException e) {
} catch (DateTimeParseException e) {
throw new IllegalArgumentException(
"invalid date time example: " + example + " (" + pattern + ")", e);
}
Expand Down Expand Up @@ -280,7 +280,7 @@ private static String inferDateTimePattern(String example, List<?> signature) {
})
.orElse(0);
if (consumed <= 0) {
throw new IllegalArgumentException("unsupported example: " + example);
throw new IllegalArgumentException("unsupported date time example: " + example);
}
matched += consumed;
}
Expand Down

0 comments on commit e870756

Please sign in to comment.