aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java35
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java47
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"