diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java | 59 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java | 75 |
2 files changed, 87 insertions, 47 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java index 572b281584..adb7b2902c 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java @@ -102,6 +102,29 @@ public class MethodLibrary { } }; + /** + * For consistency with Python we recognize the same whitespace characters as they do over the + * range 0x00-0xFF. See https://hg.python.org/cpython/file/3.6/Objects/unicodetype_db.h#l5738 + * This list is a consequence of Unicode character information. + * + * Note that this differs from Python 2.7, which uses ctype.h#isspace(), and from + * java.lang.Character#isWhitespace(), which does not recognize U+00A0. + */ + private static final String LATIN1_WHITESPACE = ( + "\u0009" + + "\n" + + "\u000B" + + "\u000C" + + "\r" + + "\u001C" + + "\u001D" + + "\u001E" + + "\u001F" + + "\u0020" + + "\u0085" + + "\u00A0" + ); + private static String stringLStrip(String self, String chars) { CharMatcher matcher = CharMatcher.anyOf(chars); for (int i = 0; i < self.length(); i++) { @@ -137,14 +160,16 @@ public class MethodLibrary { @Param( name = "chars", type = String.class, - doc = "The characters to remove", - defaultValue = "' \\t\\n\\r'" // \f \v are illegal in Skylark + noneable = true, + doc = "The characters to remove, or all whitespace if None", + defaultValue = "None" ) } ) private static final BuiltinFunction lstrip = new BuiltinFunction("lstrip") { - public String invoke(String self, String chars) { + public String invoke(String self, Object charsOrNone) { + String chars = charsOrNone != Runtime.NONE ? (String) charsOrNone : LATIN1_WHITESPACE; return stringLStrip(self, chars); } }; @@ -162,16 +187,18 @@ public class MethodLibrary { parameters = { @Param(name = "self", type = String.class, doc = "This string"), @Param( - name = "chars", - type = String.class, - doc = "The characters to remove", - defaultValue = "' \\t\\n\\r'" // \f \v are illegal in Skylark - ) + name = "chars", + type = String.class, + noneable = true, + doc = "The characters to remove, or all whitespace if None", + defaultValue = "None" + ) } ) private static final BuiltinFunction rstrip = new BuiltinFunction("rstrip") { - public String invoke(String self, String chars) { + public String invoke(String self, Object charsOrNone) { + String chars = charsOrNone != Runtime.NONE ? (String) charsOrNone : LATIN1_WHITESPACE; return stringRStrip(self, chars); } }; @@ -189,16 +216,18 @@ public class MethodLibrary { parameters = { @Param(name = "self", type = String.class, doc = "This string"), @Param( - name = "chars", - type = String.class, - doc = "The characters to remove", - defaultValue = "' \\t\\n\\r'" // \f \v are illegal in Skylark - ) + name = "chars", + type = String.class, + noneable = true, + doc = "The characters to remove, or all whitespace if None", + defaultValue = "None" + ) } ) private static final BuiltinFunction strip = new BuiltinFunction("strip") { - public String invoke(String self, String chars) { + public String invoke(String self, Object charsOrNone) { + String chars = charsOrNone != Runtime.NONE ? (String) charsOrNone : LATIN1_WHITESPACE; return stringLStrip(stringRStrip(self, chars), chars); } }; diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java index ae6b8fb595..b2910a25c0 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java @@ -1810,42 +1810,53 @@ public class MethodLibraryTest extends EvaluationTestCase { .testStatement("'AbZ'.isalpha()", true); } - @Test - public void testLStrip() throws Exception { - new BothModesTest() - .testStatement("'a b c'.lstrip('')", "a b c") - .testStatement("'abcba'.lstrip('ba')", "cba") - .testStatement("'abc'.lstrip('xyz')", "abc") - .testStatement("' a b c '.lstrip()", "a b c ") - // the "\\"s are because Java absorbs one level of "\"s - .testStatement("' \\t\\na b c '.lstrip()", "a b c ") - .testStatement("' a b c '.lstrip('')", " a b c "); - } - - @Test - public void testRStrip() throws Exception { - new BothModesTest() - .testStatement("'a b c'.rstrip('')", "a b c") - .testStatement("'abcba'.rstrip('ba')", "abc") - .testStatement("'abc'.rstrip('xyz')", "abc") - .testStatement("' a b c '.rstrip()", " a b c") - // the "\\"s are because Java absorbs one level of "\"s - .testStatement("' a b c \\t \\n'.rstrip()", " a b c") - .testStatement("' a b c '.rstrip('')", " a b c "); + /** + * Assert that lstrip(), rstrip(), and strip() produce the expected result for a given input + * string and chars argument. If chars is null no argument is passed. + */ + private void checkStrip( + String input, Object chars, + String expLeft, String expRight, String expBoth) throws Exception { + if (chars == null) { + new BothModesTest() + .update("s", input) + .testStatement("s.lstrip()", expLeft) + .testStatement("s.rstrip()", expRight) + .testStatement("s.strip()", expBoth); + } else { + new BothModesTest() + .update("s", input) + .update("chars", chars) + .testStatement("s.lstrip(chars)", expLeft) + .testStatement("s.rstrip(chars)", expRight) + .testStatement("s.strip(chars)", expBoth); + } } @Test public void testStrip() throws Exception { - new BothModesTest() - .testStatement("'a b c'.strip('')", "a b c") - .testStatement("'abcba'.strip('ba')", "c") - .testStatement("'abc'.strip('xyz')", "abc") - .testStatement("' a b c '.strip()", "a b c") - .testStatement("' a b c\\t'.strip()", "a b c") - .testStatement("'a b c'.strip('.')", "a b c") - // the "\\"s are because Java absorbs one level of "\"s - .testStatement("' \\t\\n\\ra b c \\t\\n\\r'.strip()", "a b c") - .testStatement("' a b c '.strip('')", " a b c "); + // Strip nothing. + checkStrip("a b c", "", "a b c", "a b c", "a b c"); + checkStrip(" a b c ", "", " a b c ", " a b c ", " a b c "); + // Normal case, found and not found. + checkStrip("abcba", "ba", "cba", "abc", "c"); + checkStrip("abc", "xyz", "abc", "abc", "abc"); + // Default whitespace. + checkStrip(" a b c ", null, "a b c ", " a b c", "a b c"); + checkStrip(" a b c ", Runtime.NONE, "a b c ", " a b c", "a b c"); + // Default whitespace with full range of Latin-1 whitespace chars. + String whitespace = "\u0009\n\u000B\u000C\r\u001C\u001D\u001E\u001F\u0020\u0085\u00A0"; + checkStrip( + whitespace + "a" + whitespace, null, + "a" + whitespace, whitespace + "a", "a"); + checkStrip( + whitespace + "a" + whitespace, Runtime.NONE, + "a" + whitespace, whitespace + "a", "a"); + // Empty cases. + checkStrip("", "", "", "", ""); + checkStrip("abc", "abc", "", "", ""); + checkStrip("", "xyz", "", "", ""); + checkStrip("", null, "", "", ""); } @Test |