Skip to content

Commit

Permalink
Remove emulation of java.util.regex.Matcher#group as this relies on G…
Browse files Browse the repository at this point in the history
…WT library which is not ported to J2CL.

This make it easier to reuse the regex super sources in J2CL.

Also mark some code classes as @GwtIncompatible since they are not actually used in live GWT code but use java.util.regex.Matcher#group.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=160707666
  • Loading branch information
tadeegan authored and brad4d committed Jul 5, 2017
1 parent 5290f4f commit f58b0e4
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 51 deletions.
6 changes: 4 additions & 2 deletions src/com/google/javascript/jscomp/GoogleCodingConvention.java
Expand Up @@ -16,15 +16,16 @@


package com.google.javascript.jscomp; package com.google.javascript.jscomp;


import com.google.common.annotations.GwtIncompatible;
import com.google.errorprone.annotations.Immutable; import com.google.errorprone.annotations.Immutable;
import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.StaticSourceFile; import com.google.javascript.rhino.StaticSourceFile;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;


/** /**
* This describes the Google-specific JavaScript coding conventions. * This describes the Google-specific JavaScript coding conventions. Within Google, variable names
* Within Google, variable names are semantically significant. * are semantically significant.
* *
*/ */
@Immutable @Immutable
Expand Down Expand Up @@ -164,6 +165,7 @@ public boolean isClassFactoryCall(Node callNode) {
* to match the package of the generating file. * to match the package of the generating file.
*/ */
@Override @Override
@GwtIncompatible // TODO(tdeegan): Remove use of Matcher#group to make this fully GWT compatible.
public String getPackageName(StaticSourceFile source) { public String getPackageName(StaticSourceFile source) {
String name = source.getName(); String name = source.getName();
Matcher genfilesMatcher = GENFILES_DIR.matcher(name); Matcher genfilesMatcher = GENFILES_DIR.matcher(name);
Expand Down
83 changes: 47 additions & 36 deletions src/com/google/javascript/jscomp/GwtProperties.java
Expand Up @@ -19,20 +19,12 @@
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/** /**
* GWT-compatible helper for dealing with Java .properties files. The format is probably not * GWT-compatible helper for dealing with Java .properties files. The format is probably not fully
* fully parsed by this code, but is suitable for simple use-cases inside Closure. * parsed by this code, but is suitable for simple use-cases inside Closure.
*/ */
public class GwtProperties { public class GwtProperties {
// Matches the first part of a property, e.g. "foo.bar.baz = "
private static final Pattern PROP_DEF = Pattern.compile("^(\\w+(\\.\\w+)*)\\s*[:= ]");

// Matches a value part of a property, e.g. " value\" (continuation) or "value"
private static final Pattern PROP_LINE = Pattern.compile("^\\s*(.*?)(\\\\?)$"); // literal "\"

private final Map<String, String> contents; private final Map<String, String> contents;


private GwtProperties(Map<String, String> contents) { private GwtProperties(Map<String, String> contents) {
Expand All @@ -47,13 +39,34 @@ public String getProperty(String key) {
return contents.get(key); return contents.get(key);
} }


/** /** @return The collection of property names. */
* @return The collection of property names.
*/
public Collection<String> propertyNames() { public Collection<String> propertyNames() {
return contents.keySet(); return contents.keySet();
} }


private static String trimLeft(String str) {
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != ' ') {
return str.substring(i);
}
}
return str;
}

private static int findDelimiter(String line) {
if (line.contains(":") || line.contains("=")) {
if (line.indexOf(':') == -1) {
return line.indexOf("=");
}
if (line.indexOf('=') == -1) {
return line.indexOf(':');
}
// Both delimeters exist!
return Math.min(line.indexOf('='), line.indexOf(':'));
}
// If no : or =, delimiter is first whitespace.
return line.indexOf(' ');
}
/** /**
* Constructs a new {@link GwtProperties} from the given source string. * Constructs a new {@link GwtProperties} from the given source string.
* *
Expand All @@ -67,37 +80,35 @@ public static GwtProperties load(String source) {
for (int i = 0; i < lines.length; ++i) { for (int i = 0; i < lines.length; ++i) {
String line = lines[i]; String line = lines[i];
if (line.isEmpty() || line.startsWith("#") || line.startsWith("!")) { if (line.isEmpty() || line.startsWith("#") || line.startsWith("!")) {
continue; // skip if empty or starts with # or ! continue; // skip if empty or starts with # or !
} }


Matcher m = PROP_DEF.matcher(line);
if (!m.find()) {
continue;
}
String key = m.group(1);
String data = ""; String data = "";


line = line.substring(m.group(0).length()); // remove matched part int delimeterIndex = findDelimiter(line);
for (;;) { if (delimeterIndex == -1) {
Matcher lineMatch = PROP_LINE.matcher(line); continue;
if (!lineMatch.matches()) { }
// Should never happen, since PROP_LINE contains .* and no hard requirements. // Remove whitespace on both sides of key.
throw new RuntimeException("Properties parser failed on line: " + line); String key = line.substring(0, delimeterIndex).trim();
} // Remove whitespace only on left side of data value. Trailing white space is data.
data += lineMatch.group(1); // add content found line = trimLeft(line.substring(delimeterIndex + 1));

while (true) {
// If the line ends with "/", then consume another line if possible. if (line.endsWith("\\")) {
boolean isLastLine = lineMatch.group(2).isEmpty(); data += line.substring(0, line.length() - 1);
if (isLastLine || i + 1 == lines.length) { if (i + 1 == lines.length) {
break;
}
line = trimLeft(lines[++i]);
} else {
data += line;
break; break;
} }
line = lines[++i]; }
builder.put(key, data);
} }


builder.put(key, data); return new GwtProperties(builder.build());
} }


return new GwtProperties(builder.build());
} }

}
Expand Up @@ -65,16 +65,6 @@ public boolean find() {
return false; return false;
} }


public String group(int index) {
if (!hasExecuted) {
throw new IllegalStateException("regex not executed yet");
} else if (result == null) {
throw new IllegalStateException("regex did not match");
} else {
return result.getGroup(index);
}
}

public static String quoteReplacement(String input) { public static String quoteReplacement(String input) {
return RegExp.quote(input); return RegExp.quote(input);
} }
Expand Down
12 changes: 9 additions & 3 deletions test/com/google/javascript/jscomp/GwtPropertiesTest.java
Expand Up @@ -52,11 +52,17 @@ public void testLoadWithComments() {
} }


// https://en.wikipedia.org/wiki/.properties // https://en.wikipedia.org/wiki/.properties
public void testSpaceEscapeNotSupported() { public void testSpaceEscape() {
String src = "key\\ with\\ spaces = value\n"; String src = "key\\ with\\ spaces = value\n";
GwtProperties p = GwtProperties.load(src); GwtProperties p = GwtProperties.load(src);
// Asserts that we do not correctly handle escaped spaces. assertThat(p.getProperty("key\\ with\\ spaces")).isEqualTo("value");
assertThat(p.getProperty("key\\ with\\ spaces")).isNotEqualTo("value");
// Technically this is valid too but we do not support this, and definitely don't use it in
// our own .properties files.
String srcWithSpace = "key\\ with\\ spaces value\n";
GwtProperties pWithSpace = GwtProperties.load(srcWithSpace);
// Incorrect behaviour.
assertThat(pWithSpace.getProperty("key\\ with\\ spaces")).isNotEqualTo("value");
} }


public void testNoEquals() { public void testNoEquals() {
Expand Down

0 comments on commit f58b0e4

Please sign in to comment.