diff --git a/check_api/src/main/java/com/google/errorprone/ErrorProneAnalyzer.java b/check_api/src/main/java/com/google/errorprone/ErrorProneAnalyzer.java index 8bd05a94204b..d03c3d82f0a7 100644 --- a/check_api/src/main/java/com/google/errorprone/ErrorProneAnalyzer.java +++ b/check_api/src/main/java/com/google/errorprone/ErrorProneAnalyzer.java @@ -38,8 +38,11 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.PropagatedException; + +import java.net.URI; import java.util.HashSet; import java.util.Set; +import java.util.regex.Pattern; /** A {@link TaskListener} that runs Error Prone over attributed compilation units. */ @Trusted @@ -138,11 +141,15 @@ public void finished(TaskEvent taskEvent) { // We only get TaskEvents for compilation units if they contain no package declarations // (e.g. package-info.java files). In this case it's safe to analyze the // CompilationUnitTree immediately. - transformer.get().apply(path, subContext, descriptionListener); + if (!isExcludedPath(compilation.getSourceFile().toUri())) { + transformer.get().apply(path, subContext, descriptionListener); + } } else if (finishedCompilation(path.getCompilationUnit())) { // Otherwise this TaskEvent is for a ClassTree, and we can scan the whole // CompilationUnitTree once we've seen all the enclosed classes. - transformer.get().apply(new TreePath(compilation), subContext, descriptionListener); + if (!isExcludedPath(compilation.getSourceFile().toUri())) { + transformer.get().apply(new TreePath(compilation), subContext, descriptionListener); + } } } catch (ErrorProneError e) { e.logFatalError(log); @@ -160,6 +167,11 @@ public void finished(TaskEvent taskEvent) { } } + private boolean isExcludedPath(URI uri) { + Pattern excludedPattern = errorProneOptions.getExcludedPattern(); + return (excludedPattern != null) && excludedPattern.matcher(uri.toString()).matches(); + } + /** * Returns true if all declarations inside the given compilation unit have been visited. */ diff --git a/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java b/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java index e0dddaa10ddb..a041ad203b97 100644 --- a/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java +++ b/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java @@ -17,6 +17,7 @@ package com.google.errorprone; import com.google.auto.value.AutoValue; +import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; @@ -25,6 +26,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.errorprone.apply.ImportOrganizer; + import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; @@ -33,8 +35,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; /** * Processes command-line options specific to error-prone. @@ -55,6 +59,7 @@ public class ErrorProneOptions { private static final String IGNORE_UNKNOWN_CHECKS_FLAG = "-XepIgnoreUnknownCheckNames"; private static final String DISABLE_WARNINGS_IN_GENERATED_CODE_FLAG = "-XepDisableWarningsInGeneratedCode"; + private static final String EXCLUDED_PATHS_PREFIX = "-XepExcludedPaths:"; /** * see {@link javax.tools.OptionChecker#isSupportedOption(String)} @@ -64,6 +69,7 @@ public static int isSupportedOption(String option) { option.startsWith(CUSTOM_ENABLEMENT_PREFIX) || option.startsWith(PATCH_OUTPUT_LOCATION) || option.startsWith(PATCH_CHECKS_PREFIX) + || option.startsWith(EXCLUDED_PATHS_PREFIX) || option.equals(IGNORE_UNKNOWN_CHECKS_FLAG) || option.equals(DISABLE_WARNINGS_IN_GENERATED_CODE_FLAG) || option.equals(ERRORS_AS_WARNINGS_FLAG) @@ -154,6 +160,7 @@ final PatchingOptions build() { private final boolean enableAllChecksAsWarnings; private final boolean disableAllChecks; private final PatchingOptions patchingOptions; + private final Pattern excludedPattern; private ErrorProneOptions( ImmutableMap severityMap, @@ -163,7 +170,8 @@ private ErrorProneOptions( boolean dropErrorsToWarnings, boolean enableAllChecksAsWarnings, boolean disableAllChecks, - PatchingOptions patchingOptions) { + PatchingOptions patchingOptions, + Pattern excludedPattern) { this.severityMap = severityMap; this.remainingArgs = remainingArgs; this.ignoreUnknownChecks = ignoreUnknownChecks; @@ -172,6 +180,7 @@ private ErrorProneOptions( this.enableAllChecksAsWarnings = enableAllChecksAsWarnings; this.disableAllChecks = disableAllChecks; this.patchingOptions = patchingOptions; + this.excludedPattern = excludedPattern; } public String[] getRemainingArgs() { @@ -198,6 +207,10 @@ public PatchingOptions patchingOptions() { return patchingOptions; } + public Pattern getExcludedPattern() { + return excludedPattern; + } + private static class Builder { private boolean ignoreUnknownChecks = false; private boolean disableWarningsInGeneratedCode = false; @@ -206,6 +219,7 @@ private static class Builder { private boolean disableAllChecks = false; private Map severityMap = new HashMap<>(); private final PatchingOptions.Builder patchingOptionsBuilder = PatchingOptions.builder(); + private Pattern excludedPattern; public void setIgnoreUnknownChecks(boolean ignoreUnknownChecks) { this.ignoreUnknownChecks = ignoreUnknownChecks; @@ -257,7 +271,12 @@ public ErrorProneOptions build(ImmutableList outputArgs) { dropErrorsToWarnings, enableAllChecksAsWarnings, disableAllChecks, - patchingOptionsBuilder.build()); + patchingOptionsBuilder.build(), + excludedPattern); + } + + public void setExcludedPattern(Pattern excludedPattern) { + this.excludedPattern = excludedPattern; } } @@ -342,6 +361,10 @@ public static ErrorProneOptions processArgs(Iterable args) { String remaining = arg.substring(PATCH_IMPORT_ORDER_PREFIX.length()); ImportOrganizer importOrganizer = ImportOrderParser.getImportOrganizer(remaining); builder.patchingOptionsBuilder().importOrganizer(importOrganizer); + } else if (arg.startsWith(EXCLUDED_PATHS_PREFIX)) { + String remaining = arg.substring(EXCLUDED_PATHS_PREFIX.length()); + Iterable paths = Splitter.on(',').trimResults().split(remaining); + builder.setExcludedPattern(getExcludedPattern(paths)); } else { outputArgs.add(arg); } @@ -385,4 +408,16 @@ public static ErrorProneOptions processArgs(String[] args) { Preconditions.checkNotNull(args); return processArgs(Arrays.asList(args)); } + + private static Pattern getExcludedPattern(Iterable excludeSubStrings) { + if (!excludeSubStrings.iterator().hasNext()) { + return null; + } + Set escapedExcluded = new LinkedHashSet<>(); + for (String str: excludeSubStrings) { + escapedExcluded.add(str.replace(".", "\\.")); + } + String choiceRegexp = Joiner.on("|").join(escapedExcluded); + return Pattern.compile("(?:.*)(?:" + choiceRegexp + ")(?:.*)"); + } }