aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/util
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-12-13 12:35:00 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-13 12:37:08 -0800
commit918f32784eff50166cc6d0d5ac2f9dad7c5525ee (patch)
treee64876ae34d6e6789a94209fddb63a20c9f17939 /src/main/java/com/google/devtools/build/lib/util
parent0c349543eb5551f2eebe6177e72e0041d5415350 (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.java124
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;
+ }
+ }
}