diff options
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java | 35 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java | 47 |
2 files changed, 82 insertions, 0 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 43939049d3..2f17084a50 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 @@ -636,6 +636,41 @@ public class MethodLibrary { } }; + @SkylarkSignature(name = "splitlines", objectType = StringModule.class, + returnType = MutableList.class, + doc = + "Splits the string at line boundaries ('\\n', '\\r\\n', '\\r') " + + "and returns the result as a list.", + mandatoryPositionals = { + @Param(name = "self", type = String.class, doc = "This string.")}, + optionalPositionals = { + @Param(name = "keepends", type = Boolean.class, defaultValue = "False", + doc = "Whether the line breaks should be included in the resulting list.")}) + private static BuiltinFunction splitLines = new BuiltinFunction("splitlines") { + @SuppressWarnings("unused") + public MutableList invoke(String self, Boolean keepEnds) throws EvalException { + List<String> result = new ArrayList<>(); + Matcher matcher = SPLIT_LINES_PATTERN.matcher(self); + while (matcher.find()) { + String line = matcher.group("line"); + String lineBreak = matcher.group("break"); + boolean trailingBreak = lineBreak.isEmpty(); + if (line.isEmpty() && trailingBreak) { + break; + } + if (keepEnds && !trailingBreak) { + result.add(line + lineBreak); + } else { + result.add(line); + } + } + return new MutableList(result); + } + }; + + private static final Pattern SPLIT_LINES_PATTERN = + Pattern.compile("(?<line>.*)(?<break>(\\r\\n|\\r|\\n)?)"); + @SkylarkSignature(name = "isalpha", objectType = StringModule.class, returnType = Boolean.class, doc = "Returns True if all characters in the string are alphabetic ([a-zA-Z]) and it " + "contains at least one character.", 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 a3f71fa2b9..76f46bfa35 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 @@ -40,6 +40,53 @@ public class MethodLibraryTest extends EvaluationTestCase { } @Test + public void testSplitLines_EmptyLine() throws Exception { + new SkylarkTest().testEval("''.splitlines()", "[]").testEval("'\\n'.splitlines()", "['']"); + } + + @Test + public void testSplitLines_StartsWithLineBreak() throws Exception { + new SkylarkTest().testEval("'\\ntest'.splitlines()", "['', 'test']"); + } + + @Test + public void testSplitLines_EndsWithLineBreak() throws Exception { + new SkylarkTest().testEval("'test\\n'.splitlines()", "['test']"); + } + + @Test + public void testSplitLines_DifferentLineBreaks() throws Exception { + new SkylarkTest().testEval( + "'this\\nis\\na\\ntest'.splitlines()", "['this', 'is', 'a', 'test']"); + } + + @Test + public void testSplitLines_OnlyLineBreaks() throws Exception { + new SkylarkTest() + .testEval("'\\n\\n\\n'.splitlines()", "['', '', '']") + .testEval("'\\r\\r\\r'.splitlines()", "['', '', '']") + .testEval("'\\n\\r\\n\\r'.splitlines()", "['', '', '']") + .testEval("'\\r\\n\\r\\n\\r\\n'.splitlines()", "['', '', '']"); + } + + @Test + public void testSplitLines_EscapedSequences() throws Exception { + new SkylarkTest().testEval("'\\n\\\\n\\\\\\n'.splitlines()", "['', '\\\\n\\\\']"); + } + + @Test + public void testSplitLines_KeepEnds() throws Exception { + new SkylarkTest() + .testEval("''.splitlines(True)", "[]") + .testEval("'\\n'.splitlines(True)", "['\\n']") + .testEval( + "'this\\nis\\r\\na\\rtest'.splitlines(True)", "['this\\n', 'is\\r\\n', 'a\\r', 'test']") + .testEval("'\\ntest'.splitlines(True)", "['\\n', 'test']") + .testEval("'test\\n'.splitlines(True)", "['test\\n']") + .testEval("'\\n\\\\n\\\\\\n'.splitlines(True)", "['\\n', '\\\\n\\\\\\n']"); + } + + @Test public void testStackTraceLocation() throws Exception { new SkylarkTest().testIfErrorContains( "Traceback (most recent call last):\n\t" |