diff options
author | Googler <noreply@google.com> | 2017-12-13 12:35:00 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2017-12-13 12:37:08 -0800 |
commit | 918f32784eff50166cc6d0d5ac2f9dad7c5525ee (patch) | |
tree | e64876ae34d6e6789a94209fddb63a20c9f17939 /src/main/java/com/google/devtools/build/lib/util | |
parent | 0c349543eb5551f2eebe6177e72e0041d5415350 (diff) |
Adds a codec for RegexFilter.
PiperOrigin-RevId: 178942449
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/util')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/util/RegexFilter.java | 124 |
1 files changed, 91 insertions, 33 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java index 950e276de2..07081ebb60 100644 --- a/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java +++ b/src/main/java/com/google/devtools/build/lib/util/RegexFilter.java @@ -16,41 +16,43 @@ package com.google.devtools.build.lib.util; import com.google.common.base.Joiner; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.SerializationException; import com.google.devtools.common.options.Converter; import com.google.devtools.common.options.OptionsParsingException; - -import java.io.Serializable; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import javax.annotation.Nullable; /** - * Handles options that specify list of included/excluded regex expressions. - * Validates whether string is included in that filter. + * Handles options that specify list of included/excluded regex expressions. Validates whether + * string is included in that filter. * - * String is considered to be included into the filter if it does not match - * any of the excluded regex expressions and if it matches at least one - * included regex expression. + * <p>String is considered to be included into the filter if it does not match any of the excluded + * regex expressions and if it matches at least one included regex expression. */ @Immutable -public final class RegexFilter implements Serializable { - private final Pattern inclusionPattern; - private final Pattern exclusionPattern; +public final class RegexFilter { + // Null inclusion or exclusion pattern means those patterns are not used. + @Nullable private final Pattern inclusionPattern; + @Nullable private final Pattern exclusionPattern; private final int hashCode; /** - * Converts from a colon-separated list of regex expressions with optional - * -/+ prefix into the RegexFilter. Colons prefixed with backslash are - * considered to be part of regex definition and not a delimiter between - * separate regex expressions. + * Converts from a colon-separated list of regex expressions with optional -/+ prefix into the + * RegexFilter. Colons prefixed with backslash are considered to be part of regex definition and + * not a delimiter between separate regex expressions. * - * Order of expressions is not important. Empty entries are ignored. - * '-' marks an excluded expression. + * <p>Order of expressions is not important. Empty entries are ignored. '-' marks an excluded + * expression. */ - public static class RegexFilterConverter - implements Converter<RegexFilter> { + public static class RegexFilterConverter implements Converter<RegexFilter> { @Override public RegexFilter convert(String input) throws OptionsParsingException { @@ -81,33 +83,43 @@ public final class RegexFilter implements Serializable { return "a comma-separated list of regex expressions with prefix '-' specifying" + " excluded paths"; } - } /** - * Creates new RegexFilter using provided inclusion and exclusion path lists. + * Constructor taking regexes directly. + * + * <p>Null {@code inclusionRegex} or {@code exclusionRegex} means that inclusion or exclusion + * matching will not be applied, respectively. + * + * <p>May throw {@link PatternSyntaxException}. */ + public RegexFilter(@Nullable String inclusionRegex, @Nullable String exclusionRegex) { + this.inclusionPattern = inclusionRegex == null ? null : Pattern.compile(inclusionRegex); + this.exclusionPattern = exclusionRegex == null ? null : Pattern.compile(exclusionRegex); + this.hashCode = Objects.hash(inclusionRegex, exclusionRegex); + } + + /** Creates new RegexFilter using provided inclusion and exclusion path lists. */ public RegexFilter(List<String> inclusions, List<String> exclusions) { - inclusionPattern = convertRegexListToPattern(inclusions); - exclusionPattern = convertRegexListToPattern(exclusions); - hashCode = Objects.hash(inclusions, exclusions); + this(takeUnionOfRegexes(inclusions), takeUnionOfRegexes(exclusions)); } /** - * Converts list of regex expressions into one compiled regex expression. + * Converts a list of regex expressions into a single regex representing its union or null when + * the list is empty. */ - private static Pattern convertRegexListToPattern(List<String> regexList) { + private static String takeUnionOfRegexes(List<String> regexList) { if (regexList.isEmpty()) { return null; } - // Wrap each individual regex in the independent group, combine them using '|' and - // wrap in the non-capturing group. - return Pattern.compile("(?:(?>" + Joiner.on(")|(?>").join(regexList) + "))"); + // Wraps each individual regex into an independent group, then combines them using '|' and + // wraps the result in a non-capturing group. + return "(?:(?>" + Joiner.on(")|(?>").join(regexList) + "))"; } /** - * @return true iff given string is included (it is does not match exclusion - * pattern (if any) and matches inclusionPatter (if any). + * @return true iff given string is included (it does not match exclusion pattern (if any) and + * matches inclusionPatter (if any)). */ public boolean isIncluded(String value) { if (exclusionPattern != null && exclusionPattern.matcher(value).find()) { @@ -119,6 +131,14 @@ public final class RegexFilter implements Serializable { return inclusionPattern.matcher(value).find(); } + String getInclusionRegex() { + return inclusionPattern == null ? null : inclusionPattern.pattern(); + } + + String getExclusionRegex() { + return exclusionPattern == null ? null : exclusionPattern.pattern(); + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -134,7 +154,7 @@ public final class RegexFilter implements Serializable { } return builder.toString(); } - + @Override public boolean equals(Object other) { if (this == other) { @@ -144,7 +164,7 @@ public final class RegexFilter implements Serializable { return false; } - RegexFilter otherFilter = (RegexFilter) other; + RegexFilter otherFilter = (RegexFilter) other; if (this.exclusionPattern == null ^ otherFilter.exclusionPattern == null) { return false; } @@ -161,9 +181,47 @@ public final class RegexFilter implements Serializable { } return true; } - + @Override public int hashCode() { return hashCode; } + + public static final ObjectCodec<RegexFilter> CODEC = new Codec(); + + // TODO(shahan): replace with @AutoCodec once it's ready. + private static class Codec implements ObjectCodec<RegexFilter> { + + @Override + public Class<RegexFilter> getEncodedClass() { + return RegexFilter.class; + } + + @Override + public void serialize(RegexFilter filter, CodedOutputStream codedOut) + throws SerializationException, IOException { + serializeFilterString(filter.getInclusionRegex(), codedOut); + serializeFilterString(filter.getExclusionRegex(), codedOut); + } + + private void serializeFilterString(@Nullable String regex, CodedOutputStream codedOut) + throws IOException { + if (regex == null) { + codedOut.writeBoolNoTag(false); + } else { + codedOut.writeBoolNoTag(true); + codedOut.writeStringNoTag(regex); + } + } + + @Override + public RegexFilter deserialize(CodedInputStream codedIn) + throws SerializationException, IOException { + return new RegexFilter(deserializeFilterString(codedIn), deserializeFilterString(codedIn)); + } + + private String deserializeFilterString(CodedInputStream codedIn) throws IOException { + return codedIn.readBool() ? codedIn.readString() : null; + } + } } |