Repository: decorators-squad/eo-yaml
Pull request #385 (2020-07-14 13:32:46)

#382 RegEx escaping issues fixed
PR for #382 


Patch:
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadPlainScalar.java b/src/main/java/com/amihaiemil/eoyaml/ReadPlainScalar.java
index 255238e..b63bda5 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadPlainScalar.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadPlainScalar.java
@@ -70,12 +70,16 @@ final class ReadPlainScalar extends BaseScalar {
     public String value() {
         final String value;
         final String trimmed = this.scalar.trimmed();
-        if(trimmed.contains(":") && !trimmed.endsWith(":")) {
-            value = trimmed.substring(trimmed.indexOf(":") + 1).trim();
-        } else if(trimmed.startsWith("-") && trimmed.length() > 1) {
+        if(this.escapedSequenceScalar(this.scalar)) {
             value = trimmed.substring(trimmed.indexOf('-')+1).trim();
         } else {
-            value = trimmed;
+            if (trimmed.contains(":") && !trimmed.endsWith(":")) {
+                value = trimmed.substring(trimmed.indexOf(":") + 1).trim();
+            } else if (trimmed.startsWith("-") && trimmed.length() > 1) {
+                value = trimmed.substring(trimmed.indexOf('-') + 1).trim();
+            } else {
+                value = trimmed;
+            }
         }
         if("null".equals(value)) {
             return null;
@@ -125,4 +129,16 @@ final class ReadPlainScalar extends BaseScalar {
         }
         return unescaped;
     }
+
+    /**
+     * Returns true if there's a YamlMapping starting right after the
+     * dash, on the same line.
+     * @param dashLine Line.
+     * @return True of false.
+     */
+    private boolean escapedSequenceScalar(final YamlLine dashLine) {
+        final String trimmed = dashLine.trimmed();
+        return trimmed.matches("^[ ]*\\-[ ]*\".*\"$")
+            || trimmed.matches("^[ ]*\\-[ ]*\'.*\'$");
+    }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
index 4e0ec42..41c690a 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
@@ -29,6 +29,7 @@ package com.amihaiemil.eoyaml;
 
 import com.amihaiemil.eoyaml.exceptions.YamlReadingException;
 import java.util.*;
+import java.util.regex.Pattern;
 
 /**
  * YamlMapping read from somewhere. YAML directives and
@@ -224,6 +225,7 @@ final class ReadYamlMapping extends BaseYamlMapping {
      * @param key String key.
      * @return YamlNode.
      * @checkstyle ReturnCount (50 lines)
+     * @checkstyle LineLength (30 lines)
      */
     private YamlNode valueOfStringKey(final String key) {
         YamlNode value = null;
@@ -236,8 +238,8 @@ final class ReadYamlMapping extends BaseYamlMapping {
             for (final YamlLine line : this.significant) {
                 final String trimmed = line.trimmed();
                 if(trimmed.endsWith(tryKey + ":")
-                    || trimmed.matches("^" + tryKey + "\\:[ ]*\\>$")
-                    || trimmed.matches("^" + tryKey + "\\:[ ]*\\|$")
+                    || trimmed.matches("^" + Pattern.quote(tryKey) + "\\:[ ]*\\>$")
+                    || trimmed.matches("^" + Pattern.quote(tryKey) + "\\:[ ]*\\|$")
                 ) {
                     value = this.significant.toYamlNode(
                         line, this.guessIndentation
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
index 9a0c947..3953cd5 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
@@ -150,7 +150,7 @@ final class ReadYamlSequence extends BaseYamlSequence {
                         )
                     );
                 } else {
-                    if(trimmed.matches("^.*\\-.*\\:.*$")) {
+                    if(this.mappingStartsAtDash(line)) {
                         kids.add(
                             new ReadYamlMapping(
                                 new RtYamlLine("", line.number()-1),
@@ -202,4 +202,16 @@ final class ReadYamlSequence extends BaseYamlSequence {
         );
     }
 
+    /**
+     * Returns true if there's a YamlMapping starting right after the
+     * dash, on the same line.
+     * @param dashLine Line.
+     * @return True of false.
+     */
+    private boolean mappingStartsAtDash(final YamlLine dashLine) {
+        final String trimmed = dashLine.trimmed();
+        final boolean escapedScalar = trimmed.matches("^[ ]*\\-[ ]*\".*\"$")
+            || trimmed.matches("^[ ]*\\-[ ]*\'.*\'$");
+        return trimmed.matches("^.*\\-.*\\:.*$") && !escapedScalar;
+    }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
index a7e57d3..04f0c60 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
@@ -346,7 +346,7 @@ final class RtYamlPrinter implements YamlPrinter {
         /**
          * Special chars that need escaping.
          */
-        private final String RESERVED = "#:->|$%&";
+        private final String RESERVED = "#:->|$%&{}[]";
 
         /**
          * Original unescaped scalar.
diff --git a/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java b/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
index 7b3abca..c0a5ecd 100644
--- a/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
+++ b/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
@@ -77,7 +77,7 @@ final class SameIndentationLevel implements YamlLines {
             final YamlLine first = iterator.next();
             sameIndentation.add(first);
             int firstIndentation = first.indentation();
-            if(first.trimmed().matches("^[ ]*\\-.*\\:.+$")) {
+            if(this.mappingStartsAtDash(first)) {
                 firstIndentation += 2;
             }
             while (iterator.hasNext()) {
@@ -106,4 +106,17 @@ final class SameIndentationLevel implements YamlLines {
         return this.yamlLines.toYamlNode(prev, guessIndentation);
     }
 
+    /**
+     * Returns true if there's a YamlMapping starting right after the
+     * dash, on the same line.
+     * @param dashLine Line.
+     * @return True of false.
+     */
+    private boolean mappingStartsAtDash(final YamlLine dashLine) {
+        final String trimmed = dashLine.trimmed();
+        final boolean escapedScalar = trimmed.matches("^[ ]*\\-[ ]*\".*\"$")
+            || trimmed.matches("^[ ]*\\-[ ]*\'.*\'$");
+        return trimmed.matches("^[ ]*\\-.*\\:.+$") && !escapedScalar;
+    }
+
 }


Test patch:
diff --git a/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java b/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
index 6a455ef..4b34c5c 100644
--- a/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
@@ -647,6 +647,43 @@ public final class RtYamlInputTest {
         );
     }
 
+    /**
+     * Some escaped scalars can be read from a sequence.
+     * @throws Exception If something goes wrong.
+     */
+    @Test
+    public void readsEscapedScalarsFromSequence() throws Exception {
+        final YamlMapping map = Yaml.createYamlInput(
+            this.readTestResource("escapedScalarsInSequence.yml")
+        ).readYamlMapping();
+        System.out.println(map);
+        final YamlSequence scalars = map.yamlSequence("scalars");
+        MatcherAssert.assertThat(
+            scalars.string(0),
+            Matchers.equalTo(
+                "escaped: scalar, looks like mapping"
+            )
+        );
+        MatcherAssert.assertThat(
+            scalars.string(1),
+            Matchers.equalTo(
+                "{escaped: scalar, like: flow}"
+            )
+        );
+        MatcherAssert.assertThat(
+            scalars.string(2),
+            Matchers.equalTo(
+                "- escapedScalar3"
+            )
+        );
+        MatcherAssert.assertThat(
+            scalars.string(3),
+            Matchers.equalTo(
+                "[scalar, like, flow, sequence]"
+            )
+        );
+    }
+
     /**
      * Read a test resource file's contents.
      * @param fileName File to read.
diff --git a/src/test/resources/escapedScalarsInSequence.yml b/src/test/resources/escapedScalarsInSequence.yml
new file mode 100644
index 0000000..9b1d62c
--- /dev/null
+++ b/src/test/resources/escapedScalarsInSequence.yml
@@ -0,0 +1,5 @@
+scalars:
+  - "escaped: scalar, looks like mapping"
+  - '{escaped: scalar, like: flow}'
+  - "- escapedScalar3"
+  - '[scalar, like, flow, sequence]'
\ No newline at end of file