diff -Nru snakeyaml-1.27+ds/debian/changelog snakeyaml-1.28/debian/changelog --- snakeyaml-1.27+ds/debian/changelog 2020-11-07 09:58:51.000000000 +0000 +++ snakeyaml-1.28/debian/changelog 2021-02-28 21:49:25.000000000 +0000 @@ -1,3 +1,11 @@ +snakeyaml (1.28-1) unstable; urgency=medium + + * Team upload. + * New upstream release + * Standards-Version updated to 4.5.1 + + -- Emmanuel Bourg Sun, 28 Feb 2021 22:49:25 +0100 + snakeyaml (1.27+ds-1) unstable; urgency=medium [ Mechtilde Stehmann ] diff -Nru snakeyaml-1.27+ds/debian/control snakeyaml-1.28/debian/control --- snakeyaml-1.27+ds/debian/control 2020-11-07 08:38:08.000000000 +0000 +++ snakeyaml-1.28/debian/control 2021-02-28 21:47:01.000000000 +0000 @@ -23,7 +23,7 @@ , libsurefire-java , maven-debian-helper (>= 1.6.5) , velocity -Standards-Version: 4.5.0 +Standards-Version: 4.5.1 Vcs-Git: https://salsa.debian.org/java-team/snakeyaml.git Vcs-Browser: https://salsa.debian.org/java-team/snakeyaml Homepage: https://bitbucket.org/asomov/snakeyaml diff -Nru snakeyaml-1.27+ds/debian/watch snakeyaml-1.28/debian/watch --- snakeyaml-1.27+ds/debian/watch 2020-09-06 18:13:28.000000000 +0000 +++ snakeyaml-1.28/debian/watch 2021-02-28 21:47:01.000000000 +0000 @@ -1,6 +1,5 @@ version=4 -opts="repack,compression=xz,dversionmangle=s/\+ds$//, \ - repacksuffix=+ds, \ +opts="repack,compression=xz, \ uversionmangle=s/(\d)[\.\-]?((?:rc|RC|pre)(?:\.|-)?\d+(?:-\d+)?)$/$1~$2/" \ https://bitbucket.org/asomov/snakeyaml/downloads?tab=tags \ .*/snakeyaml-(\d\S+)\.tar\.gz diff -Nru snakeyaml-1.27+ds/pom.xml snakeyaml-1.28/pom.xml --- snakeyaml-1.27+ds/pom.xml 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/pom.xml 2021-02-22 05:54:32.000000000 +0000 @@ -3,7 +3,7 @@ 4.0.0 org.yaml snakeyaml - 1.27 + 1.28 bundle UTF-8 @@ -38,7 +38,7 @@ scm:git:http://bitbucket.org/asomov/snakeyaml scm:git:ssh://git@bitbucket.org/asomov/snakeyaml https://bitbucket.org/asomov/snakeyaml/src - snakeyaml-1.27 + snakeyaml-1.28 @@ -68,7 +68,7 @@ junit junit - 4.12 + 4.13.1 test diff -Nru snakeyaml-1.27+ds/src/changes/changes.xml snakeyaml-1.28/src/changes/changes.xml --- snakeyaml-1.27+ds/src/changes/changes.xml 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/changes/changes.xml 2021-02-22 05:54:32.000000000 +0000 @@ -5,7 +5,25 @@ YAML 1.1 parser and emitter - + + + Fix tests to work on Windows (2021-02-19) + + + Add enumCaseSensitive property to LoaderOptions to control constructing enum with case sensitivity (2021-01-05) + + + ENV substitution default can contain special characters (2021-01-03) + + + Allow for read and write YAML with Comments (2020-11-01) + + + Alias names are too permissive compared to libyaml and future spec. + Follow https://github.com/yaml/yaml-spec/blob/master/rfc/RFC-0003.md (2020-10-06) + + + Serialize anchors that are not used by any alias (2020-08-14) diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentEventsCollector.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentEventsCollector.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentEventsCollector.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentEventsCollector.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comments; + +import java.util.AbstractQueue; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Queue; + +import org.yaml.snakeyaml.events.CommentEvent; +import org.yaml.snakeyaml.events.Event; +import org.yaml.snakeyaml.parser.Parser; + +/** + * Used by the Composer and Emitter to collect comment events so that they can be used at a later point in the process. + */ +public class CommentEventsCollector { + private List commentLineList; + private Queue eventSource; + private CommentType[] expectedCommentTypes; + + /** + * Constructor used to collect comment events emitted by a Parser. + * + * @param parser + * the event source. + * @param expectedCommentTypes + * the comment types expected. Any comment types not included are not collected. + */ + public CommentEventsCollector(final Parser parser, CommentType... expectedCommentTypes) { + this.eventSource = new AbstractQueue() { + + @Override + public boolean offer(Event e) { + throw new UnsupportedOperationException(); + } + + @Override + public Event poll() { + return parser.getEvent(); + } + + @Override + public Event peek() { + return parser.peekEvent(); + } + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + throw new UnsupportedOperationException(); + } + + }; + this.expectedCommentTypes = expectedCommentTypes; + commentLineList = new ArrayList<>(); + } + + /** + * Constructor used to collect events emitted by the Serializer. + * + * @param eventSource + * the event source. + * + * @param expectedCommentTypes + * the comment types expected. Any comment types not included are not collected. + */ + public CommentEventsCollector(Queue eventSource, CommentType... expectedCommentTypes) { + this.eventSource = eventSource; + this.expectedCommentTypes = expectedCommentTypes; + commentLineList = new ArrayList<>(); + } + + /** + * Determine if the event is a comment of one of the expected types set during construction. + * + * @param event + * the event to test. + * @return true if the events is a comment of the expected type; Otherwise, false. + */ + private boolean isEventExpected(Event event) { + if (event == null || !event.is(Event.ID.Comment)) { + return false; + } + CommentEvent commentEvent = (CommentEvent) event; + for (CommentType type : expectedCommentTypes) { + if (commentEvent.getCommentType() == type) { + return true; + } + } + return false; + } + + /** + * Collect all events of the expected type (set during construction) starting with the top event on the event source. + * Collection stops as soon as a non comment or comment of the unexpected type is encountered. + * + * @return this object. + */ + public CommentEventsCollector collectEvents() { + collectEvents(null); + return this; + } + + /** + * Collect all events of the expected type (set during construction) starting with event provided as an argument and + * continuing with the top event on the event source. Collection stops as soon as a non comment or comment of the + * unexpected type is encountered. + * + * @param event + * the first event to attempt to collect. + * @return the event provided as an argument, if it is not collected; Otherwise, null + */ + public Event collectEvents(Event event) { + if (event != null) { + if (isEventExpected(event)) { + commentLineList.add(new CommentLine((CommentEvent) event)); + } else { + return event; + } + } + while (isEventExpected(eventSource.peek())) { + commentLineList.add(new CommentLine((CommentEvent) eventSource.poll())); + } + return null; + } + + /** + * Collect all events of the expected type (set during construction) starting with event provided as an argument and + * continuing with the top event on the event source. Collection stops as soon as a non comment or comment of the + * unexpected type is encountered. + * + * @param event + * the first event to attempt to collect. + * @return the event provided as an argument, if it is not collected; Otherwise, the first event that is not collected. + */ + public Event collectEventsAndPoll(Event event) { + Event nextEvent = collectEvents(event); + return nextEvent != null ? nextEvent : eventSource.poll(); + } + + /** + * Return the events collected and reset the colletor. + * + * @return the events collected. + */ + public List consume() { + try { + return commentLineList; + } finally { + commentLineList = new ArrayList<>(); + } + } + + /** + * Test if the collector contains any collected events. + * @return true if it does; Otherwise, false + */ + public boolean isEmpty() { + return commentLineList.isEmpty(); + } +} diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentLine.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentLine.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentLine.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentLine.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comments; + +import org.yaml.snakeyaml.error.Mark; +import org.yaml.snakeyaml.events.CommentEvent; + +/** + * A comment line. May be a block comment, blank line, or inline comment. + */ +public class CommentLine { + private Mark startMark; + private Mark endMark; + private String value; + private CommentType commentType; + + public CommentLine(CommentEvent event) { + this(event.getStartMark(), event.getEndMark(), event.getValue(), event.getCommentType()); + } + + public CommentLine(Mark startMark, Mark endMark, String value, CommentType commentType) { + this.startMark = startMark; + this.endMark = endMark; + this.value = value; + this.commentType = commentType; + } + + public Mark getEndMark() { + return endMark; + } + + public Mark getStartMark() { + return startMark; + } + + public CommentType getCommentType() { + return commentType; + } + + /** + * Value of this comment. + * + * @return comment's value. + */ + public String getValue() { + return value; + } + + public String toString() { + return "<" + this.getClass().getName() + " (type=" + getCommentType() + ", value=" + getValue() + ")>"; + } +} diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentType.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentType.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/comments/CommentType.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/comments/CommentType.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comments; + +/** + * The type of a comment line. + */ +public enum CommentType { + BLANK_LINE, // + BLOCK, // + IN_LINE; // +} \ No newline at end of file diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/composer/Composer.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/composer/Composer.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/composer/Composer.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/composer/Composer.java 2021-02-22 05:54:32.000000000 +0000 @@ -16,13 +16,18 @@ package org.yaml.snakeyaml.composer; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.yaml.snakeyaml.DumperOptions.FlowStyle; import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.comments.CommentEventsCollector; +import org.yaml.snakeyaml.comments.CommentLine; +import org.yaml.snakeyaml.comments.CommentType; import org.yaml.snakeyaml.error.Mark; import org.yaml.snakeyaml.error.YAMLException; import org.yaml.snakeyaml.events.AliasEvent; @@ -55,6 +60,8 @@ private final Set recursiveNodes; private int nonScalarAliasesCount = 0; private final LoaderOptions loadingConfig; + private final CommentEventsCollector blockCommentsCollector; + private final CommentEventsCollector inlineCommentsCollector; public Composer(Parser parser, Resolver resolver) { this(parser, resolver, new LoaderOptions()); @@ -66,6 +73,10 @@ this.anchors = new HashMap(); this.recursiveNodes = new HashSet(); this.loadingConfig = loadingConfig; + this.blockCommentsCollector = new CommentEventsCollector(parser, + CommentType.BLANK_LINE, CommentType.BLOCK); + this.inlineCommentsCollector = new CommentEventsCollector(parser, + CommentType.IN_LINE); } /** @@ -85,17 +96,29 @@ /** * Reads and composes the next document. * - * @return The root node of the document or null if no more - * documents are available. + * @return The root node of the document or null if no more documents are available. */ public Node getNode() { + // Collect inter-document start comments + blockCommentsCollector.collectEvents(); + if (parser.checkEvent(Event.ID.StreamEnd)) { + List commentLines = blockCommentsCollector.consume(); + Mark startMark = commentLines.get(0).getStartMark(); + List children = Collections.emptyList(); + Node node = new MappingNode(Tag.COMMENT, false, children, startMark, null, FlowStyle.BLOCK); + node.setBlockComments(commentLines); + return node; + } // Drop the DOCUMENT-START event. parser.getEvent(); // Compose the root node. - Node node = composeNode(null); + Node node = composeNode(null, blockCommentsCollector.collectEvents().consume()); // Drop the DOCUMENT-END event. + blockCommentsCollector.collectEvents(); + if(!blockCommentsCollector.isEmpty()) { + node.setEndComments(blockCommentsCollector.consume()); + } parser.getEvent(); - //clean up resources this.anchors.clear(); this.recursiveNodes.clear(); return node; @@ -113,11 +136,19 @@ public Node getSingleNode() { // Drop the STREAM-START event. parser.getEvent(); + // Drop any leading comments (though should not have run this case with comments on) + while (parser.checkEvent(Event.ID.Comment)) { + parser.getEvent(); + } // Compose a document if the stream is not empty. Node document = null; if (!parser.checkEvent(Event.ID.StreamEnd)) { document = getNode(); } + // Drop any trailing comments (though should not have run this case with comments on) + while (parser.checkEvent(Event.ID.Comment)) { + parser.getEvent(); + } // Ensure that the stream contains no more documents. if (!parser.checkEvent(Event.ID.StreamEnd)) { Event event = parser.getEvent(); @@ -130,8 +161,9 @@ return document; } - private Node composeNode(Node parent) { - if (parent != null) recursiveNodes.add(parent); + private Node composeNode(Node parent, List blockComments) { + if (parent != null) + recursiveNodes.add(parent); final Node node; if (parser.checkEvent(Event.ID.Alias)) { AliasEvent event = (AliasEvent) parser.getEvent(); @@ -150,23 +182,24 @@ if (recursiveNodes.remove(node)) { node.setTwoStepsConstruction(true); } + node.setBlockComments(blockComments); } else { NodeEvent event = (NodeEvent) parser.peekEvent(); String anchor = event.getAnchor(); // the check for duplicate anchors has been removed (issue 174) if (parser.checkEvent(Event.ID.Scalar)) { - node = composeScalarNode(anchor); + node = composeScalarNode(anchor, blockComments); } else if (parser.checkEvent(Event.ID.SequenceStart)) { - node = composeSequenceNode(anchor); + node = composeSequenceNode(anchor, blockComments); } else { - node = composeMappingNode(anchor); + node = composeMappingNode(anchor, blockComments); } } recursiveNodes.remove(parent); return node; } - protected Node composeScalarNode(String anchor) { + protected Node composeScalarNode(String anchor, List blockComments) { ScalarEvent ev = (ScalarEvent) parser.getEvent(); String tag = ev.getTag(); boolean resolved = false; @@ -184,13 +217,16 @@ node.setAnchor(anchor); anchors.put(anchor, node); } + node.setBlockComments(blockComments); + node.setInLineComments(inlineCommentsCollector.collectEvents().consume()); return node; } - protected Node composeSequenceNode(String anchor) { + protected Node composeSequenceNode(String anchor, List blockComments) { SequenceStartEvent startEvent = (SequenceStartEvent) parser.getEvent(); String tag = startEvent.getTag(); Tag nodeTag; + boolean resolved = false; if (tag == null || tag.equals("!")) { nodeTag = resolver.resolve(NodeId.sequence, null, startEvent.getImplicit()); @@ -205,15 +241,25 @@ node.setAnchor(anchor); anchors.put(anchor, node); } + node.setBlockComments(blockComments); + node.setInLineComments(inlineCommentsCollector.collectEvents().consume()); while (!parser.checkEvent(Event.ID.SequenceEnd)) { - children.add(composeNode(node)); + blockCommentsCollector.collectEvents(); + if (parser.checkEvent(Event.ID.SequenceEnd)) { + break; + } + children.add(composeNode(node, blockCommentsCollector.consume())); } Event endEvent = parser.getEvent(); node.setEndMark(endEvent.getEndMark()); + inlineCommentsCollector.collectEvents(); + if(!inlineCommentsCollector.isEmpty()) { + node.setInLineComments(inlineCommentsCollector.consume()); + } return node; } - protected Node composeMappingNode(String anchor) { + protected Node composeMappingNode(String anchor, List blockComments) { MappingStartEvent startEvent = (MappingStartEvent) parser.getEvent(); String tag = startEvent.getTag(); Tag nodeTag; @@ -232,28 +278,38 @@ node.setAnchor(anchor); anchors.put(anchor, node); } + node.setBlockComments(blockComments); + node.setInLineComments(inlineCommentsCollector.collectEvents().consume()); while (!parser.checkEvent(Event.ID.MappingEnd)) { - composeMappingChildren(children, node); + blockCommentsCollector.collectEvents(); + if (parser.checkEvent(Event.ID.MappingEnd)) { + break; + } + composeMappingChildren(children, node, blockCommentsCollector.consume()); } Event endEvent = parser.getEvent(); node.setEndMark(endEvent.getEndMark()); + inlineCommentsCollector.collectEvents(); + if(!inlineCommentsCollector.isEmpty()) { + node.setInLineComments(inlineCommentsCollector.consume()); + } return node; } - protected void composeMappingChildren(List children, MappingNode node) { - Node itemKey = composeKeyNode(node); + protected void composeMappingChildren(List children, MappingNode node, List keyBlockComments) { + Node itemKey = composeKeyNode(node, keyBlockComments); if (itemKey.getTag().equals(Tag.MERGE)) { node.setMerged(true); } - Node itemValue = composeValueNode(node); + Node itemValue = composeValueNode(node, blockCommentsCollector.collectEvents().consume()); children.add(new NodeTuple(itemKey, itemValue)); } - protected Node composeKeyNode(MappingNode node) { - return composeNode(node); + protected Node composeKeyNode(MappingNode node, List blockComments) { + return composeNode(node, blockComments); } - protected Node composeValueNode(MappingNode node) { - return composeNode(node); + protected Node composeValueNode(MappingNode node, List blockComments) { + return composeNode(node, blockComments); } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java 2021-02-22 05:54:32.000000000 +0000 @@ -79,9 +79,10 @@ private PropertyUtils propertyUtils; private boolean explicitPropertyUtils; private boolean allowDuplicateKeys = true; - private boolean wrappedToRootException = false; + private boolean enumCaseSensitive = false; + protected final Map, TypeDescription> typeDefinitions; protected final Map> typeTags; @@ -616,4 +617,12 @@ public void setWrappedToRootException(boolean wrappedToRootException) { this.wrappedToRootException = wrappedToRootException; } + + public boolean isEnumCaseSensitive() { + return enumCaseSensitive; + } + + public void setEnumCaseSensitive(boolean enumCaseSensitive) { + this.enumCaseSensitive = enumCaseSensitive; + } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java 2021-02-22 05:54:32.000000000 +0000 @@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.ScalarNode; import org.yaml.snakeyaml.nodes.SequenceNode; import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.util.EnumUtils; /** * Construct a custom Java instance. @@ -491,7 +492,11 @@ } else if (Enum.class.isAssignableFrom(type)) { String enumValueName = node.getValue(); try { - result = Enum.valueOf(type, enumValueName); + if(loadingConfig.isEnumCaseSensitive()) { + result = Enum.valueOf(type, enumValueName); + } else { + result = EnumUtils.findEnumInsensitiveCase(type, enumValueName); + } } catch (Exception ex) { throw new YAMLException("Unable to find enum value '" + enumValueName + "' for enum class: " + type.getName()); diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java 2021-02-22 05:54:32.000000000 +0000 @@ -16,14 +16,20 @@ package org.yaml.snakeyaml.emitter; import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.DumperOptions.ScalarStyle; import org.yaml.snakeyaml.DumperOptions.Version; +import org.yaml.snakeyaml.comments.CommentEventsCollector; +import org.yaml.snakeyaml.comments.CommentLine; +import org.yaml.snakeyaml.comments.CommentType; import org.yaml.snakeyaml.error.YAMLException; import org.yaml.snakeyaml.events.AliasEvent; import org.yaml.snakeyaml.events.CollectionEndEvent; import org.yaml.snakeyaml.events.CollectionStartEvent; +import org.yaml.snakeyaml.events.CommentEvent; import org.yaml.snakeyaml.events.DocumentEndEvent; import org.yaml.snakeyaml.events.DocumentStartEvent; import org.yaml.snakeyaml.events.Event; +import org.yaml.snakeyaml.events.Event.ID; import org.yaml.snakeyaml.events.MappingEndEvent; import org.yaml.snakeyaml.events.MappingStartEvent; import org.yaml.snakeyaml.events.NodeEvent; @@ -43,6 +49,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; @@ -165,6 +172,11 @@ // Scalar analysis and style. private ScalarAnalysis analysis; private DumperOptions.ScalarStyle style; + + // Comment processing + private final CommentEventsCollector blockCommentsCollector; + private final CommentEventsCollector inlineCommentsCollector; + public Emitter(Writer stream, DumperOptions opts) { // The stream should have the methods `write` and possibly `flush`. @@ -226,6 +238,12 @@ // Scalar analysis and style. this.analysis = null; this.style = null; + + // Comment processing + this.blockCommentsCollector = new CommentEventsCollector(events, + CommentType.BLANK_LINE, CommentType.BLOCK); + this.inlineCommentsCollector = new CommentEventsCollector(events, + CommentType.IN_LINE); } public void emit(Event event) throws IOException { @@ -243,36 +261,53 @@ if (events.isEmpty()) { return true; } - Event event = events.peek(); - if (event instanceof DocumentStartEvent) { - return needEvents(1); - } else if (event instanceof SequenceStartEvent) { - return needEvents(2); - } else if (event instanceof MappingStartEvent) { - return needEvents(3); - } else { - return false; + Iterator iter = events.iterator(); + Event event = null; + while(iter.hasNext()) { + event = iter.next(); + if (event instanceof CommentEvent) { + continue; + } + if (event instanceof DocumentStartEvent) { + return needEvents(iter, 1); + } else if (event instanceof SequenceStartEvent) { + return needEvents(iter, 2); + } else if (event instanceof MappingStartEvent) { + return needEvents(iter, 3); + } else if (event instanceof StreamStartEvent) { + return needEvents(iter, 2); + } else if (event instanceof StreamEndEvent) { + return false; + } else { + // To collect any comment events + return needEvents(iter, 1); + } } + return true; } - - private boolean needEvents(int count) { + + private boolean needEvents(Iterator iter, int count) { int level = 0; - Iterator iter = events.iterator(); - iter.next(); + int actualCount = 0; while (iter.hasNext()) { Event event = iter.next(); + if (event instanceof CommentEvent) { + continue; + } + actualCount++; if (event instanceof DocumentStartEvent || event instanceof CollectionStartEvent) { level++; } else if (event instanceof DocumentEndEvent || event instanceof CollectionEndEvent) { level--; } else if (event instanceof StreamEndEvent) { level = -1; + } else if (event instanceof CommentEvent) { } if (level < 0) { return false; } } - return events.size() < count + 1; + return actualCount < count; } private void increaseIndent(boolean flow, boolean indentless) { @@ -366,6 +401,10 @@ // } writeStreamEnd(); state = new ExpectNothing(); + } else if (event instanceof CommentEvent) { + blockCommentsCollector.collectEvents(event); + writeBlockComment(); + // state = state; remains unchanged } else { throw new EmitterException("expected DocumentStartEvent, but got " + event); } @@ -374,6 +413,8 @@ private class ExpectDocumentEnd implements EmitterState { public void expect() throws IOException { + event = blockCommentsCollector.collectEventsAndPoll(event); + writeBlockComment(); if (event instanceof DocumentEndEvent) { writeIndent(); if (((DocumentEndEvent) event).getExplicit()) { @@ -390,6 +431,14 @@ private class ExpectDocumentRoot implements EmitterState { public void expect() throws IOException { + event = blockCommentsCollector.collectEventsAndPoll(event); + if (!blockCommentsCollector.isEmpty()) { + writeBlockComment(); + if (event instanceof DocumentEndEvent) { + new ExpectDocumentEnd().expect(); + return; + } + } states.push(new ExpectDocumentEnd()); expectNode(true, false, false); } @@ -461,13 +510,20 @@ indent = indents.pop(); flowLevel--; writeIndicator("]", false, false, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); state = states.pop(); + } else if (event instanceof CommentEvent) { + blockCommentsCollector.collectEvents(event); + writeBlockComment(); } else { if (canonical || (column > bestWidth && splitLines) || prettyFlow) { writeIndent(); } states.push(new ExpectFlowSequenceItem()); expectNode(false, false, false); + event = inlineCommentsCollector.collectEvents(event); + writeInlineComments(); } } } @@ -482,10 +538,15 @@ writeIndent(); } writeIndicator("]", false, false, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); if (prettyFlow) { writeIndent(); } state = states.pop(); + } else if (event instanceof CommentEvent) { + blockCommentsCollector.collectEvents(event); + writeBlockComment(); } else { writeIndicator(",", false, false, false); if (canonical || (column > bestWidth && splitLines) || prettyFlow) { @@ -493,6 +554,8 @@ } states.push(new ExpectFlowSequenceItem()); expectNode(false, false, false); + inlineCommentsCollector.collectEvents(event); + writeInlineComments(); } } } @@ -515,6 +578,8 @@ indent = indents.pop(); flowLevel--; writeIndicator("}", false, false, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); state = states.pop(); } else { if (canonical || (column > bestWidth && splitLines) || prettyFlow) { @@ -545,6 +610,8 @@ writeIndent(); } writeIndicator("}", false, false, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); state = states.pop(); } else { writeIndicator(",", false, false, false); @@ -566,8 +633,12 @@ private class ExpectFlowMappingSimpleValue implements EmitterState { public void expect() throws IOException { writeIndicator(":", false, false, false); + event = inlineCommentsCollector.collectEventsAndPoll(event); + writeInlineComments(); states.push(new ExpectFlowMappingKey()); expectNode(false, true, false); + inlineCommentsCollector.collectEvents(event); + writeInlineComments(); } } @@ -577,8 +648,12 @@ writeIndent(); } writeIndicator(":", true, false, false); + event = inlineCommentsCollector.collectEventsAndPoll(event); + writeInlineComments(); states.push(new ExpectFlowMappingKey()); expectNode(false, true, false); + inlineCommentsCollector.collectEvents(event); + writeInlineComments(); } } @@ -607,6 +682,9 @@ if (!this.first && event instanceof SequenceEndEvent) { indent = indents.pop(); state = states.pop(); + } else if( event instanceof CommentEvent) { + blockCommentsCollector.collectEvents(event); + writeBlockComment(); } else { writeIndent(); if (!indentWithIndicator || this.first) { @@ -618,6 +696,8 @@ } states.push(new ExpectBlockSequenceItem(false)); expectNode(false, false, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); } } } @@ -642,6 +722,8 @@ } public void expect() throws IOException { + event = blockCommentsCollector.collectEventsAndPoll(event); + writeBlockComment(); if (!this.first && event instanceof MappingEndEvent) { indent = indents.pop(); state = states.pop(); @@ -659,11 +741,37 @@ } } + private boolean isFoldedOrLiteral(Event event) { + if(!event.is(ID.Scalar)) { + return false; + } + ScalarEvent scalarEvent = (ScalarEvent) event; + ScalarStyle style = scalarEvent.getScalarStyle(); + return style == ScalarStyle.FOLDED || style == ScalarStyle.LITERAL; + } + private class ExpectBlockMappingSimpleValue implements EmitterState { public void expect() throws IOException { writeIndicator(":", false, false, false); + event = inlineCommentsCollector.collectEventsAndPoll(event); + if(!isFoldedOrLiteral(event)) { + if(writeInlineComments()) { + increaseIndent(true, false); + writeIndent(); + indent = indents.pop(); + } + } + event = blockCommentsCollector.collectEventsAndPoll(event); + if(!blockCommentsCollector.isEmpty()) { + increaseIndent(true, false); + writeBlockComment(); + writeIndent(); + indent = indents.pop(); + } states.push(new ExpectBlockMappingKey(false)); expectNode(false, true, false); + inlineCommentsCollector.collectEvents(); + writeInlineComments(); } } @@ -671,8 +779,14 @@ public void expect() throws IOException { writeIndent(); writeIndicator(":", true, false, true); + event = inlineCommentsCollector.collectEventsAndPoll(event); + writeInlineComments(); + event = blockCommentsCollector.collectEventsAndPoll(event); + writeBlockComment(); states.push(new ExpectBlockMappingKey(false)); expectNode(false, true, false); + inlineCommentsCollector.collectEvents(event); + writeInlineComments(); } } @@ -1316,6 +1430,39 @@ } writeIndicator("\"", false, false, false); } + + private boolean writeCommentLines(List commentLines) throws IOException { + int indentColumns = 0; + boolean firstComment = true; + boolean wroteComment = false; + for(CommentLine commentLine : commentLines) { + if(commentLine.getCommentType() != CommentType.BLANK_LINE) { + if(firstComment) { + firstComment = false; + writeIndicator("#", commentLine.getCommentType() == CommentType.IN_LINE, false, false); + indentColumns = this.column > 0 ? this.column - 1 : 0; + } else { + writeWhitespace(indentColumns); + writeIndicator("#", false, false, false); + } + stream.write(commentLine.getValue()); + } + writeLineBreak(null); + wroteComment = true; + } + return wroteComment; + } + + private void writeBlockComment() throws IOException { + if(!blockCommentsCollector.isEmpty()) { + writeIndent(); + } + writeCommentLines(blockCommentsCollector.consume()); + } + + private boolean writeInlineComments() throws IOException { + return writeCommentLines(inlineCommentsCollector.consume()); + } private String determineBlockHints(String text) { StringBuilder hints = new StringBuilder(); @@ -1337,7 +1484,9 @@ if (hints.length() > 0 && (hints.charAt(hints.length() - 1) == '+')) { openEnded = true; } - writeLineBreak(null); + if(!writeInlineComments()) { + writeLineBreak(null); + } boolean leadingSpace = true; boolean spaces = false; boolean breaks = true; @@ -1402,7 +1551,9 @@ if (hints.length() > 0 && (hints.charAt(hints.length() - 1)) == '+') { openEnded = true; } - writeLineBreak(null); + if(!writeInlineComments()) { + writeLineBreak(null); + } boolean breaks = true; int start = 0, end = 0; while (end <= text.length()) { diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/env/EnvScalarConstructor.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/env/EnvScalarConstructor.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/env/EnvScalarConstructor.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/env/EnvScalarConstructor.java 2021-02-22 05:54:32.000000000 +0000 @@ -32,7 +32,9 @@ */ public class EnvScalarConstructor extends Constructor { public static final Tag ENV_TAG = new Tag("!ENV"); - public static final Pattern ENV_FORMAT = Pattern.compile("^\\$\\{\\s*((?\\w+)((?:?(-|\\?))(?\\w+)?)?)\\s*\\}$"); + // name must be a word -> \w+ + // value can be any non-space -> \S+ + public static final Pattern ENV_FORMAT = Pattern.compile("^\\$\\{\\s*((?\\w+)((?:?(-|\\?))(?\\S+)?)?)\\s*\\}$"); public EnvScalarConstructor() { this.yamlConstructors.put(ENV_TAG, new ConstructEnv()); diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/events/CommentEvent.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/events/CommentEvent.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/events/CommentEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/events/CommentEvent.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.events; + +import org.yaml.snakeyaml.comments.CommentType; +import org.yaml.snakeyaml.error.Mark; + +/** + * Marks a comment block value. + */ +public final class CommentEvent extends Event { + private final CommentType type; + private final String value; + + public CommentEvent(CommentType type, String value, Mark startMark, Mark endMark) { + super(startMark, endMark); + if (type == null) throw new NullPointerException("Event Type must be provided."); + this.type = type; + if (value == null) throw new NullPointerException("Value must be provided."); + this.value = value; + } + + /** + * String representation of the value. + *

+ * Without quotes and escaping. + *

+ * + * @return Value a comment line string without the leading '#' or a blank line. + */ + public String getValue() { + return this.value; + } + + /** + * The comment type. + * + * @return the commentType. + */ + public CommentType getCommentType() { + return this.type; + } + + @Override + protected String getArguments() { + return super.getArguments() + "type=" + type + ", value=" + value; + } + + @Override + public Event.ID getEventId() { + return ID.Comment; + } + +} diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/events/Event.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/events/Event.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/events/Event.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/events/Event.java 2021-02-22 05:54:32.000000000 +0000 @@ -23,7 +23,17 @@ */ public abstract class Event { public enum ID { - Alias, DocumentEnd, DocumentStart, MappingEnd, MappingStart, Scalar, SequenceEnd, SequenceStart, StreamEnd, StreamStart + Alias, + Comment, + DocumentEnd, + DocumentStart, + MappingEnd, + MappingStart, + Scalar, + SequenceEnd, + SequenceStart, + StreamEnd, + StreamStart } private final Mark startMark; diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/LoaderOptions.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/LoaderOptions.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/LoaderOptions.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/LoaderOptions.java 2021-02-22 05:54:32.000000000 +0000 @@ -21,6 +21,8 @@ private boolean wrappedToRootException = false; private int maxAliasesForCollections = 50; //to prevent YAML at https://en.wikipedia.org/wiki/Billion_laughs_attack private boolean allowRecursiveKeys = false; + private boolean processComments = false; + private boolean enumCaseSensitive = true; public boolean isAllowDuplicateKeys() { return allowDuplicateKeys; @@ -85,4 +87,31 @@ public boolean getAllowRecursiveKeys() { return allowRecursiveKeys; } + + /** + * Set the comment processing. By default comments are ignored. + * + * @param processComments true to process; false to ignore + */ + public void setProcessComments(boolean processComments) { + this.processComments = processComments; + } + + public boolean isProcessComments() { + return processComments; + } + + public boolean isEnumCaseSensitive() { + return enumCaseSensitive; + } + + /** + * Disables or enables case sensitivity during construct enum constant from string value + * Default is false. + * + * @param enumCaseSensitive - true to set enum case sensitive, false the reverse + */ + public void setEnumCaseSensitive(boolean enumCaseSensitive) { + this.enumCaseSensitive = enumCaseSensitive; + } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/nodes/Node.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/nodes/Node.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/nodes/Node.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/nodes/Node.java 2021-02-22 05:54:32.000000000 +0000 @@ -15,6 +15,9 @@ */ package org.yaml.snakeyaml.nodes; +import java.util.List; + +import org.yaml.snakeyaml.comments.CommentLine; import org.yaml.snakeyaml.error.Mark; /** @@ -37,6 +40,10 @@ private Class type; private boolean twoStepsConstruction; private String anchor; + private List inLineComments; + private List blockComments; + // End Comments are only on the last node in a document + private List endComments; /** * true when the tag is assigned by the resolver @@ -52,6 +59,9 @@ this.twoStepsConstruction = false; this.resolved = true; this.useClassConstructor = null; + this.inLineComments = null; + this.blockComments = null; + this.endComments = null; } /** @@ -176,4 +186,46 @@ public void setAnchor(String anchor) { this.anchor = anchor; } + + /** + * The ordered list of in-line comments. The first of which appears at the end of the line respresent by this node. + * The rest are in the following lines, indented per the Spec to indicate they are continuation of the inline comment. + * + * @return the comment line list. + */ + public List getInLineComments() { + return inLineComments; + } + + public void setInLineComments(List inLineComments) { + this.inLineComments = inLineComments; + } + + /** + * The ordered list of blank lines and block comments (full line) that appear before this node. + * + * @return the comment line list. + */ + public List getBlockComments() { + return blockComments; + } + + public void setBlockComments(List blockComments) { + this.blockComments = blockComments; + } + + /** + * The ordered list of blank lines and block comments (full line) that appear AFTER this node. + *

+ * NOTE: these comment should occur only in the last node in a document, when walking the node tree "in order" + * + * @return the comment line list. + */ + public List getEndComments() { + return endComments; + } + + public void setEndComments(List endComments) { + this.endComments = endComments; + } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/nodes/Tag.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/nodes/Tag.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/nodes/Tag.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/nodes/Tag.java 2021-02-22 05:54:32.000000000 +0000 @@ -43,6 +43,8 @@ public static final Tag STR = new Tag(PREFIX + "str"); public static final Tag SEQ = new Tag(PREFIX + "seq"); public static final Tag MAP = new Tag(PREFIX + "map"); + // For use to indicate a DUMMY node that contains comments, when there is no other (empty document) + public static final Tag COMMENT = new Tag(PREFIX + "comment"); protected static final Map>> COMPATIBILITY_MAP; static { COMPATIBILITY_MAP = new HashMap>>(); @@ -96,7 +98,8 @@ /** * @deprecated - it will be removed - * @param uri - URI to be encoded as tag value + * @param uri + * - URI to be encoded as tag value */ public Tag(URI uri) { if (uri == null) { @@ -143,13 +146,11 @@ } /** - * Java has more then 1 class compatible with a language-independent tag - * (!!int, !!float, !!timestamp etc) + * Java has more then 1 class compatible with a language-independent tag (!!int, !!float, !!timestamp etc) * * @param clazz * - Class to check compatibility - * @return true when the Class can be represented by this - * language-independent tag + * @return true when the Class can be represented by this language-independent tag */ public boolean isCompatible(Class clazz) { Set> set = COMPATIBILITY_MAP.get(this); diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/parser/ParserImpl.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/parser/ParserImpl.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/parser/ParserImpl.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/parser/ParserImpl.java 2021-02-22 05:54:32.000000000 +0000 @@ -21,9 +21,11 @@ import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions.Version; +import org.yaml.snakeyaml.comments.CommentType; import org.yaml.snakeyaml.error.Mark; import org.yaml.snakeyaml.error.YAMLException; import org.yaml.snakeyaml.events.AliasEvent; +import org.yaml.snakeyaml.events.CommentEvent; import org.yaml.snakeyaml.events.DocumentEndEvent; import org.yaml.snakeyaml.events.DocumentStartEvent; import org.yaml.snakeyaml.events.Event; @@ -42,6 +44,7 @@ import org.yaml.snakeyaml.tokens.AliasToken; import org.yaml.snakeyaml.tokens.AnchorToken; import org.yaml.snakeyaml.tokens.BlockEntryToken; +import org.yaml.snakeyaml.tokens.CommentToken; import org.yaml.snakeyaml.tokens.DirectiveToken; import org.yaml.snakeyaml.tokens.ScalarToken; import org.yaml.snakeyaml.tokens.StreamEndToken; @@ -132,6 +135,10 @@ this(new ScannerImpl(reader)); } + public ParserImpl(StreamReader reader, boolean emitComments) { + this(new ScannerImpl(reader).setEmitComments(emitComments)); + } + public ParserImpl(Scanner scanner) { this.scanner = scanner; currentEvent = null; @@ -171,6 +178,17 @@ return value; } + private CommentEvent produceCommentEvent(CommentToken token) { + Mark startMark = token.getStartMark(); + Mark endMark = token.getEndMark(); + String value = token.getValue(); + CommentType type = token.getCommentType(); + + // state = state, that no change in state + + return new CommentEvent(type, value, startMark, endMark); + } + /** *

      * stream    ::= STREAM-START implicit_document? explicit_document* STREAM-END
@@ -192,7 +210,9 @@
     private class ParseImplicitDocumentStart implements Production {
         public Event produce() {
             // Parse an implicit document.
-            if (!scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart, Token.ID.StreamEnd)) {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            } else if (!scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart, Token.ID.StreamEnd)) {
                 directives = new VersionTagsTuple(null, DEFAULT_TAGS);
                 Token token = scanner.peekToken();
                 Mark startMark = token.getStartMark();
@@ -211,38 +231,51 @@
 
     private class ParseDocumentStart implements Production {
         public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             // Parse any extra document end indicators.
             while (scanner.checkToken(Token.ID.DocumentEnd)) {
                 scanner.getToken();
             }
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             // Parse an explicit document.
             Event event;
             if (!scanner.checkToken(Token.ID.StreamEnd)) {
                 Token token = scanner.peekToken();
                 Mark startMark = token.getStartMark();
                 VersionTagsTuple tuple = processDirectives();
-                if (!scanner.checkToken(Token.ID.DocumentStart)) {
-                    throw new ParserException(null, null, "expected '', but found '"
-                            + scanner.peekToken().getTokenId() + "'", scanner.peekToken().getStartMark());
-                }
-                token = scanner.getToken();
-                Mark endMark = token.getEndMark();
-                event = new DocumentStartEvent(startMark, endMark, true, tuple.getVersion(),
-                        tuple.getTags());
-                states.push(new ParseDocumentEnd());
-                state = new ParseDocumentContent();
-            } else {
-                // Parse the end of the stream.
-                StreamEndToken token = (StreamEndToken) scanner.getToken();
-                event = new StreamEndEvent(token.getStartMark(), token.getEndMark());
-                if (!states.isEmpty()) {
-                    throw new YAMLException("Unexpected end of stream. States left: " + states);
-                }
-                if (!marks.isEmpty()) {
-                    throw new YAMLException("Unexpected end of stream. Marks left: " + marks);
+                while (scanner.checkToken(Token.ID.Comment)) {
+                    // TODO: till we figure out what todo with the comments
+                    scanner.getToken(); 
+                }
+                if (!scanner.checkToken(Token.ID.StreamEnd)) {
+                    if (!scanner.checkToken(Token.ID.DocumentStart)) {
+                        throw new ParserException(null, null, "expected '', but found '"
+                                + scanner.peekToken().getTokenId() + "'", scanner.peekToken().getStartMark());
+                    }
+                    token = scanner.getToken();
+                    Mark endMark = token.getEndMark();
+                    event = new DocumentStartEvent(startMark, endMark, true, tuple.getVersion(),
+                            tuple.getTags());
+                    states.push(new ParseDocumentEnd());
+                    state = new ParseDocumentContent();
+                    return event;
                 }
-                state = null;
             }
+            // Parse the end of the stream.
+            StreamEndToken token = (StreamEndToken) scanner.getToken();
+            event = new StreamEndEvent(token.getStartMark(), token.getEndMark());
+            if (!states.isEmpty()) {
+                throw new YAMLException("Unexpected end of stream. States left: " + states);
+            }
+            if (!marks.isEmpty()) {
+                throw new YAMLException("Unexpected end of stream. Marks left: " + marks);
+            }
+            state = null;
+            
             return event;
         }
     }
@@ -268,6 +301,9 @@
 
     private class ParseDocumentContent implements Production {
         public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             Event event;
             if (scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart,
                     Token.ID.DocumentEnd, Token.ID.StreamEnd)) {
@@ -443,6 +479,8 @@
                     event = new ScalarEvent(anchor, tag, implicitValues, token.getValue(),
                             startMark, endMark, token.getStyle());
                     state = states.pop();
+                } else if (scanner.checkToken(Token.ID.Comment)) {
+                    event = produceCommentEvent((CommentToken) scanner.getToken());
                 } else if (scanner.checkToken(Token.ID.FlowSequenceStart)) {
                     endMark = scanner.peekToken().getEndMark();
                     event = new SequenceStartEvent(anchor, tag, implicit, startMark, endMark,
@@ -499,6 +537,9 @@
 
     private class ParseBlockSequenceEntry implements Production {
         public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             if (scanner.checkToken(Token.ID.BlockEntry)) {
                 BlockEntryToken token = (BlockEntryToken) scanner.getToken();
                 if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.BlockEnd)) {
@@ -527,6 +568,9 @@
 
     private class ParseIndentlessSequenceEntry implements Production {
         public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             if (scanner.checkToken(Token.ID.BlockEntry)) {
                 Token token = scanner.getToken();
                 if (!scanner.checkToken(Token.ID.BlockEntry, Token.ID.Key, Token.ID.Value,
@@ -555,6 +599,9 @@
 
     private class ParseBlockMappingKey implements Production {
         public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return produceCommentEvent((CommentToken) scanner.getToken());
+            }
             if (scanner.checkToken(Token.ID.Key)) {
                 Token token = scanner.getToken();
                 if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
@@ -583,13 +630,19 @@
         public Event produce() {
             if (scanner.checkToken(Token.ID.Value)) {
                 Token token = scanner.getToken();
-                if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
+                if (scanner.checkToken(Token.ID.Comment)) {
+                    state = new ParseBlockMappingValueComment();
+                    return state.produce();
+                } else if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
                     states.push(new ParseBlockMappingKey());
                     return parseBlockNodeOrIndentlessSequence();
                 } else {
                     state = new ParseBlockMappingKey();
                     return processEmptyScalar(token.getEndMark());
                 }
+            } else if(scanner.checkToken(Token.ID.Scalar)) {
+                states.push(new ParseBlockMappingKey());
+                return parseBlockNodeOrIndentlessSequence();
             }
             state = new ParseBlockMappingKey();
             Token token = scanner.peekToken();
@@ -597,6 +650,21 @@
         }
     }
 
+    private class ParseBlockMappingValueComment implements Production {
+        public Event produce() {
+            if (scanner.checkToken(Token.ID.Comment)) {
+                return parseBlockNodeOrIndentlessSequence();
+            } else if (!scanner.checkToken(Token.ID.Key, Token.ID.Value, Token.ID.BlockEnd)) {
+                states.push(new ParseBlockMappingKey());
+                return parseBlockNodeOrIndentlessSequence();
+            } else {
+                state = new ParseBlockMappingKey();
+                Token token = scanner.getToken();
+                return processEmptyScalar(token.getEndMark());
+            }
+        }
+    }
+
     /**
      * 
      * flow_sequence     ::= FLOW-SEQUENCE-START
@@ -650,12 +718,25 @@
             }
             Token token = scanner.getToken();
             Event event = new SequenceEndEvent(token.getStartMark(), token.getEndMark());
-            state = states.pop();
             marks.pop();
+            if(!scanner.checkToken(Token.ID.Comment)) {
+                state = states.pop();               
+            } else {
+                state = new ParseFlowEndComment();
+            }
             return event;
         }
     }
 
+    private class ParseFlowEndComment implements Production {
+        public Event produce() {
+            Event event = produceCommentEvent((CommentToken)scanner.getToken());
+            if(!scanner.checkToken(Token.ID.Comment)) {
+                state = states.pop();               
+            }
+            return event;
+        }
+    }
     private class ParseFlowSequenceEntryMappingKey implements Production {
         public Event produce() {
             Token token = scanner.getToken();
@@ -749,9 +830,13 @@
             }
             Token token = scanner.getToken();
             Event event = new MappingEndEvent(token.getStartMark(), token.getEndMark());
-            state = states.pop();
             marks.pop();
-            return event;
+            if(!scanner.checkToken(Token.ID.Comment)) {
+                state = states.pop();               
+            } else {
+                state = new ParseFlowEndComment();
+            }
+            return event;            
         }
     }
 
diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/scanner/ScannerImpl.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/scanner/ScannerImpl.java
--- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/scanner/ScannerImpl.java	2020-09-01 13:59:55.000000000 +0000
+++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/scanner/ScannerImpl.java	2021-02-22 05:54:32.000000000 +0000
@@ -26,6 +26,7 @@
 import java.util.regex.Pattern;
 
 import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.comments.CommentType;
 import org.yaml.snakeyaml.error.Mark;
 import org.yaml.snakeyaml.error.YAMLException;
 import org.yaml.snakeyaml.reader.StreamReader;
@@ -35,6 +36,7 @@
 import org.yaml.snakeyaml.tokens.BlockEntryToken;
 import org.yaml.snakeyaml.tokens.BlockMappingStartToken;
 import org.yaml.snakeyaml.tokens.BlockSequenceStartToken;
+import org.yaml.snakeyaml.tokens.CommentToken;
 import org.yaml.snakeyaml.tokens.DirectiveToken;
 import org.yaml.snakeyaml.tokens.DocumentEndToken;
 import org.yaml.snakeyaml.tokens.DocumentStartToken;
@@ -59,6 +61,7 @@
  * Scanner produces tokens of the following types:
  * STREAM-START
  * STREAM-END
+ * COMMENT
  * DIRECTIVE(name, value)
  * DOCUMENT-START
  * DOCUMENT-END
@@ -175,6 +178,9 @@
     // Past indentation levels.
     private ArrayStack indents;
 
+    // A flag that indicates if comments should be emitted
+    private boolean emitComments;
+
     // Variables related to simple keys treatment. See PyYAML.
 
     /**
@@ -211,6 +217,7 @@
     private Map possibleSimpleKeys;
 
     public ScannerImpl(StreamReader reader) {
+        this.emitComments = false;
         this.reader = reader;
         this.tokens = new ArrayList(100);
         this.indents = new ArrayStack(10);
@@ -220,6 +227,20 @@
     }
 
     /**
+     * Set the scanner to ignore comments or emit them as a CommentToken.
+     * 
+     * @param emitComments true to emit; false to ignore
+     */
+    public ScannerImpl setEmitComments(boolean emitComments) {
+        this.emitComments = emitComments;
+        return this;
+    }
+
+    public boolean isEmitComments() {
+        return emitComments;
+    }
+
+    /**
      * Check whether the next token is one of the given types.
      */
     public boolean checkToken(Token.ID... choices) {
@@ -283,7 +304,7 @@
      * Fetch one or more tokens from the StreamReader.
      */
     private void fetchMoreTokens() {
-        // Eat whitespaces and comments until we reach the next token.
+        // Eat whitespaces and process comments until we reach the next token.
         scanToNextToken();
         // Remove obsolete possible simple keys.
         stalePossibleSimpleKeys();
@@ -614,8 +635,8 @@
         this.allowSimpleKey = false;
 
         // Scan and add DIRECTIVE.
-        Token tok = scanDirective();
-        this.tokens.add(tok);
+        List tok = scanDirective();
+        this.tokens.addAll(tok);
     }
 
     /**
@@ -991,8 +1012,8 @@
         removePossibleSimpleKey();
 
         // Scan and add SCALAR.
-        Token tok = scanBlockScalar(style);
-        this.tokens.add(tok);
+        List tok = scanBlockScalar(style);
+        this.tokens.addAll(tok);
     }
 
     /**
@@ -1178,7 +1199,10 @@
             reader.forward();
         }
         boolean found = false;
+        int inlineStartColumn = -1;
         while (!found) {
+            Mark startMark = reader.getMark();
+            boolean commentSeen = false;
             int ff = 0;
             // Peek ahead until we find the first non-space character, then
             // move forward directly to that character.
@@ -1193,17 +1217,32 @@
             // comments are from a # to the next new-line. We then forward
             // past the comment.
             if (reader.peek() == '#') {
-                ff = 0;
-                while (Constant.NULL_OR_LINEBR.hasNo(reader.peek(ff))) {
-                    ff++;
+                commentSeen = true;
+                CommentType type;
+                if(startMark.getColumn() != 0) {
+                    type = CommentType.IN_LINE;
+                    inlineStartColumn = reader.getColumn();
+                } else if(inlineStartColumn == reader.getColumn()) {
+                    type = CommentType.IN_LINE;
+                } else {
+                    inlineStartColumn = -1;
+                    type = CommentType.BLOCK;
                 }
-                if (ff > 0) {
-                    reader.forward(ff);
+                CommentToken token = scanComment(type);
+                if (emitComments) {
+                    this.tokens.add(token);
                 }
             }
             // If we scanned a line break, then (depending on flow level),
             // simple keys may be allowed.
-            if (scanLineBreak().length() != 0) {// found a line-break
+            String breaks = scanLineBreak();
+            if (breaks.length() != 0) {// found a line-break
+                if (emitComments && ! commentSeen) {
+                    if (startMark.getColumn() == 0) {
+                        Mark endMark = reader.getMark();
+                        this.tokens.add(new CommentToken(CommentType.BLANK_LINE, breaks, startMark, endMark));
+                    }
+                }
                 if (this.flowLevel == 0) {
                     // Simple keys are allowed at flow-level 0 after a line
                     // break
@@ -1215,8 +1254,21 @@
         }
     }
 
+    private CommentToken scanComment(CommentType type) {
+        // See the specification for details.
+        Mark startMark = reader.getMark();
+        reader.forward();
+        int length = 0;
+        while (Constant.NULL_OR_LINEBR.hasNo(reader.peek(length))) {
+            length++;
+        }
+        String value = reader.prefixForward(length);
+        Mark endMark = reader.getMark();
+        return new CommentToken(type, value, startMark, endMark);
+    }
+
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private Token scanDirective() {
+    private List scanDirective() {
         // See the specification for details.
         Mark startMark = reader.getMark();
         Mark endMark;
@@ -1239,8 +1291,9 @@
                 reader.forward(ff);
             }
         }
-        scanDirectiveIgnoredLine(startMark);
-        return new DirectiveToken(name, value, startMark, endMark);
+        CommentToken commentToken = scanDirectiveIgnoredLine(startMark);
+        DirectiveToken token = new DirectiveToken(name, value, startMark, endMark);
+        return makeTokenList(token, commentToken);
     }
 
     /**
@@ -1394,14 +1447,22 @@
         return value;
     }
 
-    private void scanDirectiveIgnoredLine(Mark startMark) {
+    private CommentToken scanDirectiveIgnoredLine(Mark startMark) {
         // See the specification for details.
         while (reader.peek() == ' ') {
             reader.forward();
         }
+        CommentToken commentToken = null;
         if (reader.peek() == '#') {
-            while (Constant.NULL_OR_LINEBR.hasNo(reader.peek())) {
-                reader.forward();
+            Mark commentStartMark = reader.getMark();
+            int length = 0;
+            while (Constant.NULL_OR_LINEBR.hasNo(reader.peek(length))) {
+                length++;
+            }
+            String comment = reader.prefixForward(length);
+            if(emitComments) {
+                Mark commentEndMark = reader.getMark();
+                commentToken = new CommentToken(CommentType.IN_LINE, comment, commentStartMark, commentEndMark);
             }
         }
         int c = reader.peek();
@@ -1412,8 +1473,17 @@
                     "expected a comment or a line break, but found " + s + "(" + c + ")",
                     reader.getMark());
         }
+        return commentToken;
     }
 
+    /**
+     * 
+     * The YAML 1.1 specification does not restrict characters for anchors and
+     * aliases. This may lead to problems.
+     * see https://bitbucket.org/asomov/snakeyaml/issues/485/alias-names-are-too-permissive-compared-to
+     * This implementation tries to follow https://github.com/yaml/yaml-spec/blob/master/rfc/RFC-0003.md
+     * 
+ */ private Token scanAnchor(boolean isAnchor) { Mark startMark = reader.getMark(); int indicator = reader.peek(); @@ -1421,9 +1491,7 @@ reader.forward(); int length = 0; int c = reader.peek(length); - // YAML 1.1 is unclear for the anchor names, we apply YAML 1.2 rules for the names. - // Anchor may not contain ",[]{}", the ":" was added by SnakeYAML -> should it be added to the spec 1.2 ? - while (Constant.NULL_BL_T_LINEBR.hasNo(c, ":,[]{}")) { + while (Constant.NULL_BL_T_LINEBR.hasNo(c, ":,[]{}/.*&")) { length++; c = reader.peek(length); } @@ -1454,7 +1522,7 @@ * Scan a Tag property. A Tag property may be specified in one of three * ways: c-verbatim-tag, c-ns-shorthand-tag, or c-ns-non-specific-tag *

- * + * *

* c-verbatim-tag takes the form !<ns-uri-char+> and must be delivered * verbatim (as-is) to the application. In particular, verbatim tags are not @@ -1549,7 +1617,7 @@ return new TagToken(value, startMark, endMark); } - private Token scanBlockScalar(char style) { + private List scanBlockScalar(char style) { // See the specification for details. boolean folded; // Depending on the given style, we determine whether the scalar is @@ -1565,7 +1633,7 @@ reader.forward(); Chomping chompi = scanBlockScalarIndicators(startMark); int increment = chompi.getIncrement(); - scanBlockScalarIgnoredLine(startMark); + CommentToken commentToken = scanBlockScalarIgnoredLine(startMark); // Determine the indentation level and go to the first non-empty line. int minIndent = this.indent + 1; @@ -1627,11 +1695,16 @@ if (chompi.chompTailIsNotFalse()) { chunks.append(lineBreak); } + CommentToken blankLineCommentToken = null; if (chompi.chompTailIsTrue()) { + if (emitComments) { + blankLineCommentToken = new CommentToken(CommentType.BLANK_LINE, breaks, startMark, endMark); + } chunks.append(breaks); } // We are done. - return new ScalarToken(chunks.toString(), false, startMark, endMark, DumperOptions.ScalarStyle.createStyle(style)); + ScalarToken scalarToken = new ScalarToken(chunks.toString(), false, startMark, endMark, DumperOptions.ScalarStyle.createStyle(style)); + return makeTokenList(commentToken, scalarToken, blankLineCommentToken); } /** @@ -1705,7 +1778,7 @@ * Scan to the end of the line after a block scalar has been scanned; the * only things that are permitted at this time are comments and spaces. */ - private String scanBlockScalarIgnoredLine(Mark startMark) { + private CommentToken scanBlockScalarIgnoredLine(Mark startMark) { // See the specification for details. // Forward past any number of trailing spaces @@ -1714,10 +1787,9 @@ } // If a comment occurs, scan to just before the end of line. + CommentToken commentToken = null; if (reader.peek() == '#') { - while (Constant.NULL_OR_LINEBR.hasNo(reader.peek())) { - reader.forward(); - } + commentToken = scanComment(CommentType.IN_LINE); } // If the next character is not a null or line break, an error has // occurred. @@ -1729,7 +1801,7 @@ "expected a comment or a line break, but found " + s + "(" + c + ")", reader.getMark()); } - return lineBreak; + return commentToken; } /** @@ -2245,6 +2317,20 @@ return ""; } + private List makeTokenList(Token... tokens) { + List tokenList = new ArrayList<>(); + for (int ix = 0; ix < tokens.length; ix++) { + if (tokens[ix] == null) { + continue; + } + if (!emitComments && (tokens[ix] instanceof CommentToken)) { + continue; + } + tokenList.add(tokens[ix]); + } + return tokenList; + } + /** * Chomping the tail may have 3 values - yes, no, not defined. */ diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java 2021-02-22 05:54:32.000000000 +0000 @@ -24,8 +24,10 @@ import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions.Version; +import org.yaml.snakeyaml.comments.CommentLine; import org.yaml.snakeyaml.emitter.Emitable; import org.yaml.snakeyaml.events.AliasEvent; +import org.yaml.snakeyaml.events.CommentEvent; import org.yaml.snakeyaml.events.DocumentEndEvent; import org.yaml.snakeyaml.events.DocumentStartEvent; import org.yaml.snakeyaml.events.ImplicitTuple; @@ -37,7 +39,6 @@ import org.yaml.snakeyaml.events.StreamEndEvent; import org.yaml.snakeyaml.events.StreamStartEvent; import org.yaml.snakeyaml.nodes.AnchorNode; -import org.yaml.snakeyaml.nodes.CollectionNode; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeId; @@ -151,7 +152,7 @@ } } - //parent Node is not used but might be used in the future + // parent Node is not used but might be used in the future private void serializeNode(Node node, Node parent) throws IOException { if (node.getNodeId() == NodeId.anchor) { node = ((AnchorNode) node).getRealNode(); @@ -164,6 +165,7 @@ switch (node.getNodeId()) { case scalar: ScalarNode scalarNode = (ScalarNode) node; + serializeComments(node.getBlockComments()); Tag detectedTag = this.resolver.resolve(NodeId.scalar, scalarNode.getValue(), true); Tag defaultTag = this.resolver.resolve(NodeId.scalar, scalarNode.getValue(), false); ImplicitTuple tuple = new ImplicitTuple(node.getTag().equals(detectedTag), node @@ -171,9 +173,12 @@ ScalarEvent event = new ScalarEvent(tAlias, node.getTag().getValue(), tuple, scalarNode.getValue(), null, null, scalarNode.getScalarStyle()); this.emitter.emit(event); + serializeComments(node.getInLineComments()); + serializeComments(node.getEndComments()); break; case sequence: SequenceNode seqNode = (SequenceNode) node; + serializeComments(node.getBlockComments()); boolean implicitS = node.getTag().equals(this.resolver.resolve(NodeId.sequence, null, true)); this.emitter.emit(new SequenceStartEvent(tAlias, node.getTag().getValue(), @@ -183,22 +188,40 @@ serializeNode(item, node); } this.emitter.emit(new SequenceEndEvent(null, null)); + serializeComments(node.getInLineComments()); + serializeComments(node.getEndComments()); break; default:// instance of MappingNode + serializeComments(node.getBlockComments()); Tag implicitTag = this.resolver.resolve(NodeId.mapping, null, true); boolean implicitM = node.getTag().equals(implicitTag); - this.emitter.emit(new MappingStartEvent(tAlias, node.getTag().getValue(), - implicitM, null, null, ((CollectionNode) node).getFlowStyle())); MappingNode mnode = (MappingNode) node; List map = mnode.getValue(); - for (NodeTuple row : map) { - Node key = row.getKeyNode(); - Node value = row.getValueNode(); - serializeNode(key, mnode); - serializeNode(value, mnode); + if (mnode.getTag() != Tag.COMMENT ) { + this.emitter.emit(new MappingStartEvent(tAlias, mnode.getTag().getValue(), implicitM, null, null, + mnode.getFlowStyle())); + for (NodeTuple row : map) { + Node key = row.getKeyNode(); + Node value = row.getValueNode(); + serializeNode(key, mnode); + serializeNode(value, mnode); + } + this.emitter.emit(new MappingEndEvent(null, null)); + serializeComments(node.getInLineComments()); + serializeComments(node.getEndComments()); } - this.emitter.emit(new MappingEndEvent(null, null)); } } } + + private void serializeComments(List comments) throws IOException { + if(comments == null) { + return; + } + for (CommentLine line : comments) { + CommentEvent commentEvent = new CommentEvent(line.getCommentType(), line.getValue(), line.getStartMark(), + line.getEndMark()); + this.emitter.emit(commentEvent); + } + } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/tokens/CommentToken.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/tokens/CommentToken.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/tokens/CommentToken.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/tokens/CommentToken.java 2021-02-22 05:54:32.000000000 +0000 @@ -15,18 +15,33 @@ */ package org.yaml.snakeyaml.tokens; +import java.util.Objects; + +import org.yaml.snakeyaml.comments.CommentType; import org.yaml.snakeyaml.error.Mark; -/** - * @deprecated it will be removed because it is not used - */ -public class CommentToken extends Token { - public CommentToken(Mark startMark, Mark endMark) { +public final class CommentToken extends Token { + private final CommentType type; + private final String value; + + public CommentToken(CommentType type, String value, Mark startMark, Mark endMark) { super(startMark, endMark); + Objects.requireNonNull(type); + this.type = type; + Objects.requireNonNull(value); + this.value = value; + } + + public CommentType getCommentType() { + return this.type; + } + + public String getValue() { + return this.value; } @Override - public ID getTokenId() { + public Token.ID getTokenId() { return ID.Comment; } } diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/util/EnumUtils.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/util/EnumUtils.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/util/EnumUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/util/EnumUtils.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.util; + +public class EnumUtils { + + /** + * Looks for an enumeration constant that matches the string without being case sensitive + * + * @param enumType - the Class object of the enum type from which to return a constant + * @param name - the name of the constant to return + * @param - the enum type whose constant is to be returned + * @return the enum constant of the specified enum type with the specified name, insensitive to case + * @throws IllegalArgumentException – if the specified enum type has no constant with the specified name, insensitive case + */ + public static > T findEnumInsensitiveCase(Class enumType, String name) { + for (T constant : enumType.getEnumConstants()) { + if (constant.name().compareToIgnoreCase(name) == 0) { + return constant; + } + } + throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name); + } +} diff -Nru snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/Yaml.java snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/Yaml.java --- snakeyaml-1.27+ds/src/main/java/org/yaml/snakeyaml/Yaml.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/main/java/org/yaml/snakeyaml/Yaml.java 2021-02-22 05:54:32.000000000 +0000 @@ -63,8 +63,7 @@ * Create Yaml instance. */ public Yaml() { - this(new Constructor(), new Representer(), new DumperOptions(), new LoaderOptions(), - new Resolver()); + this(new Constructor(), new Representer(), new DumperOptions(), new LoaderOptions(), new Resolver()); } /** @@ -130,7 +129,8 @@ * @param dumperOptions DumperOptions to configure outgoing objects */ public Yaml(Representer representer, DumperOptions dumperOptions) { - this(new Constructor(), representer, dumperOptions, new LoaderOptions(), new Resolver()); + this(new Constructor(), representer, dumperOptions, new LoaderOptions(), + new Resolver()); } /** @@ -177,14 +177,14 @@ * Create Yaml instance. It is safe to create a few instances and use them * in different Threads. * - * @param constructor BaseConstructor to construct incoming documents - * @param representer Representer to emit outgoing objects - * @param dumperOptions DumperOptions to configure outgoing objects - * @param loadingConfig LoadingConfig to control load behavior - * @param resolver Resolver to detect implicit type + * @param constructor BaseConstructor to construct incoming documents + * @param representer Representer to emit outgoing objects + * @param dumperOptions DumperOptions to configure outgoing objects + * @param loadingConfig LoadingConfig to control load behavior + * @param resolver Resolver to detect implicit type */ public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions, - LoaderOptions loadingConfig, Resolver resolver) { + LoaderOptions loadingConfig, Resolver resolver) { if (!constructor.isExplicitPropertyUtils()) { constructor.setPropertyUtils(representer.getPropertyUtils()); } else if (!representer.isExplicitPropertyUtils()) { @@ -353,7 +353,7 @@ } /** - * Serialize a YAML node into a YAML stream. + * Serialize (dump) a YAML node into a YAML stream. * * @param node YAML node to be serialized to YAML * @param output stream to write to @@ -568,7 +568,8 @@ * Overview */ public Node compose(Reader yaml) { - Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver, loadingConfig); + Composer composer = new Composer(new ParserImpl(new StreamReader(yaml), + loadingConfig.isProcessComments()), resolver, loadingConfig); return composer.getSingleNode(); } @@ -581,7 +582,8 @@ * @see Processing Overview */ public Iterable composeAll(Reader yaml) { - final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver, loadingConfig); + final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml), + loadingConfig.isProcessComments()), resolver, loadingConfig); Iterator result = new Iterator() { @Override public boolean hasNext() { diff -Nru snakeyaml-1.27+ds/src/test/java/examples/enumset/YamlEnumSetTest.java snakeyaml-1.28/src/test/java/examples/enumset/YamlEnumSetTest.java --- snakeyaml-1.27+ds/src/test/java/examples/enumset/YamlEnumSetTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/examples/enumset/YamlEnumSetTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -19,8 +19,10 @@ import org.junit.Assert; import org.junit.Test; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; import org.yaml.snakeyaml.nodes.Node; public class YamlEnumSetTest { @@ -80,8 +82,45 @@ Assert.assertEquals(yEST.setOfDays, loaded.setOfDays); } - private Yaml createYaml() { - Yaml yaml = new Yaml(); + @Test + public void enumSetLoadWithoutCaseSensitive() { + //given + LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setEnumCaseSensitive(false); + + YamlEnumSetTest yEST = new YamlEnumSetTest(); + yEST.day = Day.SUNDAY; + yEST.setOfDays = EnumSet.of(Day.MONDAY, Day.WEDNESDAY, Day.FRIDAY); + + String yamlStr = "day: SUNDAY\nsetOfDays: { MONDAY, wednesday, friDay }\n"; + + //when + YamlEnumSetTest loaded = createYaml(loaderOptions).loadAs(yamlStr, YamlEnumSetTest.class); + + //then + Assert.assertTrue(loaded.day == Day.SUNDAY); + + Object[] expected = yEST.setOfDays.toArray(); + Object[] actual = loaded.setOfDays.toArray(); + + Assert.assertArrayEquals(expected, actual); + Assert.assertEquals(yEST.setOfDays, loaded.setOfDays); + } + + @Test(expected = YAMLException.class) + public void enumSetLoadWithCaseSensitive() { + YamlEnumSetTest yEST = new YamlEnumSetTest(); + yEST.day = Day.SUNDAY; + yEST.setOfDays = EnumSet.of(Day.MONDAY, Day.WEDNESDAY, Day.FRIDAY); + + String yamlStr = "day: SUNDAY\nsetOfDays: { MONDAY, wednesday, friDay }\n"; + + //when + createYaml().loadAs(yamlStr, YamlEnumSetTest.class); + } + + private Yaml createYaml(LoaderOptions loaderOptions) { + Yaml yaml = loaderOptions != null ? new Yaml(loaderOptions) : new Yaml(); TypeDescription yamlEnumSetTD = new TypeDescription(YamlEnumSetTest.class) { @@ -100,4 +139,10 @@ return yaml; } -} \ No newline at end of file + private Yaml createYaml() { + return createYaml(null); + } + + + +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/pyyaml/CanonicalLoader.java snakeyaml-1.28/src/test/java/org/pyyaml/CanonicalLoader.java --- snakeyaml-1.27+ds/src/test/java/org/pyyaml/CanonicalLoader.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/pyyaml/CanonicalLoader.java 2021-02-22 05:54:32.000000000 +0000 @@ -33,7 +33,7 @@ buffer.append((char) ch); ch = yaml.read(); } - Composer composer = new Composer(new CanonicalParser(buffer.toString()), resolver); + Composer composer = new Composer(new CanonicalParser(buffer.toString().replace(System.lineSeparator(), "\n")), resolver); constructor.setComposer(composer); return constructor.getSingleData(Object.class); } catch (IOException e) { diff -Nru snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyCanonicalTest.java snakeyaml-1.28/src/test/java/org/pyyaml/PyCanonicalTest.java --- snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyCanonicalTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/pyyaml/PyCanonicalTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -48,7 +48,7 @@ buffer.append((char) ch); ch = input.read(); } - CanonicalScanner scanner = new CanonicalScanner(buffer.toString()); + CanonicalScanner scanner = new CanonicalScanner(buffer.toString().replace(System.lineSeparator(), "\n")); List result = new ArrayList(); while (scanner.peekToken() != null) { result.add(scanner.getToken()); diff -Nru snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyImportTest.java snakeyaml-1.28/src/test/java/org/pyyaml/PyImportTest.java --- snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyImportTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/pyyaml/PyImportTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -90,7 +90,7 @@ buffer.appendCodePoint(reader.peek()); reader.forward(); } - CanonicalParser parser = new CanonicalParser(buffer.toString()); + CanonicalParser parser = new CanonicalParser(buffer.toString().replace(System.lineSeparator(), "\n")); List result = new ArrayList(); while (parser.peekEvent() != null) { result.add(parser.getEvent()); diff -Nru snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyStructureTest.java snakeyaml-1.28/src/test/java/org/pyyaml/PyStructureTest.java --- snakeyaml-1.27+ds/src/test/java/org/pyyaml/PyStructureTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/pyyaml/PyStructureTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -199,7 +199,7 @@ buffer.appendCodePoint(reader.peek()); reader.forward(); } - CanonicalParser parser = new CanonicalParser(buffer.toString()); + CanonicalParser parser = new CanonicalParser(buffer.toString().replace(System.lineSeparator(), "\n")); Composer composer = new Composer(parser, new Resolver()); List documents = new ArrayList(); while (composer.checkNode()) { @@ -221,7 +221,7 @@ buffer.appendCodePoint(reader.peek()); reader.forward(); } - CanonicalParser parser = new CanonicalParser(buffer.toString()); + CanonicalParser parser = new CanonicalParser(buffer.toString().replace(System.lineSeparator(), "\n")); Composer composer = new Composer(parser, resolver); this.constructor.setComposer(composer); Iterator result = new Iterator() { diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ComposerWithCommentEnabledTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ComposerWithCommentEnabledTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ComposerWithCommentEnabledTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ComposerWithCommentEnabledTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,539 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comment; + +import org.junit.Test; +import org.yaml.snakeyaml.comments.CommentLine; +import org.yaml.snakeyaml.composer.Composer; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.MappingNode; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.nodes.NodeTuple; +import org.yaml.snakeyaml.nodes.ScalarNode; +import org.yaml.snakeyaml.nodes.SequenceNode; +import org.yaml.snakeyaml.parser.ParserImpl; +import org.yaml.snakeyaml.reader.StreamReader; +import org.yaml.snakeyaml.resolver.Resolver; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ComposerWithCommentEnabledTest { + private boolean DEBUG = false; + + private void printBlockComment(Node node, int level, PrintStream out) { + if (node.getBlockComments() != null) { + List blockComments = node.getBlockComments(); + for (int i = 0; i < blockComments.size(); i++) { + printWithIndent("Block Comment", level, out); + } + } + } + + private void printEndComment(Node node, int level, PrintStream out) { + if (node.getEndComments() != null) { + List endComments = node.getEndComments(); + for (int i = 0; i < endComments.size(); i++) { + printWithIndent("End Comment", level, out); + } + } + } + + private void printInLineComment(Node node, int level, PrintStream out) { + if (node.getInLineComments() != null) { + List inLineComments = node.getInLineComments(); + for (int i = 0; i < inLineComments.size(); i++) { + printWithIndent("InLine Comment", level + 1, out); + } + } + } + + private void printWithIndent(String line, int level, PrintStream out) { + for (int ix = 0; ix < level; ix++) { + out.print(" "); + } + out.print(line); + out.print("\n"); + } + + private void printNodeInternal(Node node, int level, PrintStream out) { + + if (node instanceof MappingNode) { + MappingNode mappingNode = (MappingNode) node; + printBlockComment(mappingNode, level, out); + printWithIndent(mappingNode.getClass().getSimpleName(), level, out); + for (NodeTuple childNodeTuple : mappingNode.getValue()) { + printWithIndent("Tuple", level + 1, out); + printNodeInternal(childNodeTuple.getKeyNode(), level + 2, out); + printNodeInternal(childNodeTuple.getValueNode(), level + 2, out); + } + printInLineComment(mappingNode, level, out); + printEndComment(mappingNode, level, out); + + } else if (node instanceof SequenceNode) { + SequenceNode sequenceNode = (SequenceNode) node; + printBlockComment(sequenceNode, level, out); + printWithIndent(sequenceNode.getClass().getSimpleName(), level, out); + for (Node childNode : sequenceNode.getValue()) { + printNodeInternal(childNode, level + 1, out); + } + printInLineComment(sequenceNode, level, out); + printEndComment(sequenceNode, level, out); + + } else if (node instanceof ScalarNode) { + ScalarNode scalarNode = (ScalarNode) node; + printBlockComment(scalarNode, level, out); + printWithIndent(scalarNode.getClass().getSimpleName() + ": " + scalarNode.getValue(), level, out); + printInLineComment(scalarNode, level, out); + printEndComment(scalarNode, level, out); + + } else { + printBlockComment(node, level, out); + printWithIndent(node.getClass().getSimpleName(), level, out); + printInLineComment(node, level, out); + printEndComment(node, level, out); + } + } + + private void printNodeList(List nodeList) { + if (DEBUG) { + System.out.println("BEGIN"); + boolean first = true; + for (Node node : nodeList) { + if (first) { + first = false; + } else { + System.out.println("---"); + } + printNodeInternal(node, 1, System.out); + } + System.out.println("DONE\n"); + } + } + + private List getNodeList(Composer composer) { + List nodeList = new ArrayList<>(); + while (composer.checkNode()) { + nodeList.add(composer.getNode()); + } + return nodeList; + } + + private void assertNodesEqual(String[] expecteds, List nodeList) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + boolean first = true; + try (PrintStream out = new PrintStream(baos)) { + for (Node node : nodeList) { + if (first) { + first = false; + } else { + out.print("---\n"); + } + printNodeInternal(node, 0, out); + } + } + String actualString = baos.toString(); + String[] actuals = actualString.split("\n"); + for (int ix = 0; ix < Math.min(expecteds.length, actuals.length); ix++) { + assertEquals(expecteds[ix], actuals[ix]); + } + assertEquals(expecteds.length, actuals.length); + } + + public Composer newComposerWithCommentsEnabled(String data) { + return new Composer(new ParserImpl(new StreamReader(data), true), new Resolver()); + } + + @Test + public void testEmpty() { + String data = ""; + String[] expecteds = new String[]{ // + "" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testParseWithOnlyComment() { + String data = "# Comment"; + String[] expecteds = new String[]{ // + "Block Comment", // + "MappingNode", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testCommentEndingALine() { + String data = "" + // + "key: # Comment\n" + // + " value\n"; + + String[] expecteds = new String[]{ // + "MappingNode", // + " Tuple", // + " ScalarNode: key", // + " InLine Comment", // + " ScalarNode: value" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testMultiLineComment() { + String data = "" + // + "key: # Comment\n" + // + " # lines\n" + // + " value\n" + // + "\n"; + + String[] expecteds = new String[]{ // + "MappingNode", // + " Tuple", // + " ScalarNode: key", // + " InLine Comment", // + " InLine Comment", // + " ScalarNode: value" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testBlankLine() { + String data = "" + // + "\n"; + + String[] expecteds = new String[]{ // + "Block Comment", // + "MappingNode", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testBlankLineComments() { + String data = "" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"; + + String[] expecteds = new String[]{ // + "Block Comment", // + "MappingNode", // + " Tuple", // + " ScalarNode: abc", // + " ScalarNode: def", // + " InLine Comment", // + "End Comment", // + "End Comment", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void test_blockScalar() { + String data = "" + // + "abc: > # Comment\n" + // + " def\n" + // + " hij\n" + // + "\n"; + + String[] expecteds = new String[]{ // + "MappingNode", // + " Tuple", // + " ScalarNode: abc", // + " InLine Comment", // + " ScalarNode: def hij" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testDirectiveLineEndComment() { + String data = "%YAML 1.1 #Comment\n"; + + String[] expecteds = new String[]{ // + "" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testSequence() { + String data = "" + // + "# Comment\n" + // + "list: # InlineComment1\n" + // + "# Block Comment\n" + // + "- item # InlineComment2\n" + // + "# Comment\n"; + + String[] expecteds = new String[]{ // + "Block Comment", // + "MappingNode", // + " Tuple", // + " ScalarNode: list", // + " InLine Comment", // + " Block Comment", // + " SequenceNode", // + " ScalarNode: item", // + " InLine Comment", // + "End Comment" // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testAllComments1() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "key: # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + " # Block Comment3a\n" + // + " # Block Comment3b\n" + // + " value # Inline Comment2\n" + // + "# Block Comment4\n" + // + "list: # InlineComment3a\n" + // + " # InlineComment3b\n" + // + "# Block Comment5\n" + // + "- item1 # InlineComment4\n" + // + "- item2: [ value2a, value2b ] # InlineComment5\n" + // + "- item3: { key3a: [ value3a1, value3a2 ], key3b: value3b } # InlineComment6\n" + // + "# Block Comment6\n" + // + "---\n" + // + "# Block Comment7\n" + // + ""; + + String[] expecteds = new String[]{ // + "Block Comment", // + "Block Comment", // + "MappingNode", // + " Tuple", // + " ScalarNode: key", // + " InLine Comment", // + " InLine Comment", // + " Block Comment", // + " Block Comment", // + " ScalarNode: value", // + " InLine Comment", // + " Tuple", // + " Block Comment", // + " ScalarNode: list", // + " InLine Comment", // + " InLine Comment", // + " Block Comment", // + " SequenceNode", // + " ScalarNode: item1", // + " InLine Comment", // + " MappingNode", // + " Tuple", // + " ScalarNode: item2", // + " SequenceNode", // + " ScalarNode: value2a", // + " ScalarNode: value2b", // + " InLine Comment", // + " MappingNode", // + " Tuple", // + " ScalarNode: item3", // + " MappingNode", // + " Tuple", // + " ScalarNode: key3a", // + " SequenceNode", // + " ScalarNode: value3a1", // + " ScalarNode: value3a2", // + " Tuple", // + " ScalarNode: key3b", // + " ScalarNode: value3b", // + " InLine Comment", // + "End Comment", // + "---", // + "Block Comment", // + "ScalarNode: ", // This is an empty scalar created as this is an empty document + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testAllComments2() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "- item1 # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + "# Block Comment3a\n" + // + "# Block Comment3b\n" + // + "- item2: value # Inline Comment2\n" + // + "# Block Comment4\n" + // + ""; + + String[] expecteds = new String[]{ // + "Block Comment", // + "Block Comment", // + "SequenceNode", // + " ScalarNode: item1", // + " InLine Comment", // + " InLine Comment", // + " Block Comment", // + " Block Comment", // + " MappingNode", // + " Tuple", // + " ScalarNode: item2", // + " ScalarNode: value", // + " InLine Comment", // + "End Comment", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testAllComments3() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "[ item1, item2: value2, {item3: value3} ] # Inline Comment1\n" + // + "# Block Comment2\n" + // + ""; + + String[] expecteds = new String[]{ // + "Block Comment", // + "SequenceNode", // + " ScalarNode: item1", // + " MappingNode", // + " Tuple", // + " ScalarNode: item2", // + " ScalarNode: value2", // + " MappingNode", // + " Tuple", // + " ScalarNode: item3", // + " ScalarNode: value3", // + " InLine Comment", // + "End Comment", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = getNodeList(sut); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + @Test + public void testGetSingleNode() { + String data = "" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"; + String[] expecteds = new String[]{ // + "MappingNode", // + " Tuple", // + " ScalarNode: abc", // + " ScalarNode: def", // + " InLine Comment", // + "End Comment", // + "End Comment", // + }; + + Composer sut = newComposerWithCommentsEnabled(data); + List result = Arrays.asList(sut.getSingleNode()); + + printNodeList(result); + assertNodesEqual(expecteds, result); + } + + private static class TestConstructor extends SafeConstructor { + } + + @Test + public void testBaseConstructorGetData() { + String data = "" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"; + + TestConstructor sut = new TestConstructor(); + sut.setComposer(newComposerWithCommentsEnabled(data)); + Object result = sut.getData(); + assertTrue(result instanceof LinkedHashMap); + @SuppressWarnings("unchecked") + LinkedHashMap map = (LinkedHashMap) result; + assertEquals(1, map.size()); + assertEquals(map.get("abc"), "def"); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/EmitterWithCommentEnabledTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/EmitterWithCommentEnabledTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/EmitterWithCommentEnabledTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/EmitterWithCommentEnabledTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,226 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comment; + +import org.junit.Test; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.DumperOptions.FlowStyle; +import org.yaml.snakeyaml.DumperOptions.ScalarStyle; +import org.yaml.snakeyaml.composer.Composer; +import org.yaml.snakeyaml.emitter.Emitter; +import org.yaml.snakeyaml.parser.ParserImpl; +import org.yaml.snakeyaml.reader.StreamReader; +import org.yaml.snakeyaml.resolver.Resolver; +import org.yaml.snakeyaml.serializer.Serializer; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.junit.Assert.assertEquals; + +public class EmitterWithCommentEnabledTest { + + private String runEmitterWithCommentsEnabled(String data) throws IOException { + StringWriter output = new StringWriter(); + + DumperOptions options = new DumperOptions(); + options.setDefaultScalarStyle(ScalarStyle.PLAIN); + options.setDefaultFlowStyle(FlowStyle.BLOCK); + Serializer serializer = new Serializer(new Emitter(output, options), new Resolver(), options, null); + + serializer.open(); + Composer composer = new Composer(new ParserImpl(new StreamReader(data), true), new Resolver()); + while (composer.checkNode()) { + serializer.serialize(composer.getNode()); + } + serializer.close(); + + return output.toString(); + } + + @Test + public void testEmpty() throws Exception { + String data = ""; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testWithOnlyComment() throws Exception { + String data = "# Comment\n\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testCommentEndingALine() throws Exception { + String data = "" + // + "key: # Comment\n" + // + " value\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testMultiLineComment() throws Exception { + String data = "" + // + "key: # Comment\n" + // + " # lines\n" + // + " value\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testBlankLine() throws Exception { + String data = "" + // + "\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testBlankLineComments() throws Exception { + String data = "" + // + "\n" + // + "abc: def # comment\n" + // + "\n" + // + "\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testBlockScalar() throws Exception { + String data = "" + // + "abc: | # Comment\n" + // + " def\n" + // + " hij\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testDirectiveLineEndComment() throws Exception { + String data = "%YAML 1.1 #Comment\n"; + + String result = runEmitterWithCommentsEnabled(data); + + // We currently strip Directive comments + assertEquals("", result); + } + + @Test + public void testSequence() throws Exception { + String data = "" + // + "# Comment\n" + // + "list: # InlineComment1\n" + // + " # Block Comment\n" + // + " - item # InlineComment2\n" + // + "# Comment\n"; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testAllComments1() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "key: # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + " # Block Comment3a\n" + // + " # Block Comment3b\n" + // + " value # Inline Comment2\n" + // + "# Block Comment4\n" + // + "list: # InlineComment3a\n" + // + " # InlineComment3b\n" + // + " # Block Comment5\n" + // + " - item1 # InlineComment4\n" + // + " - item2: [value2a, value2b] # InlineComment5\n" + // + " - item3: {key3a: [value3a1, value3a2], key3b: value3b} # InlineComment6\n" + // + "# Block Comment6\n" + // + "---\n" + // + "# Block Comment7\n" + // + ""; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testMultiDoc() throws Exception { + String data = "" + // + "key: value\n" + // + "# Block Comment\n" + // + "---\n" + // + "# Block Comment\n" + // + "key: value\n" + // + ""; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testAllComments2() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "- item1 # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + "# Block Comment3a\n" + // + "# Block Comment3b\n" + // + "- item2: value # Inline Comment2\n" + // + "# Block Comment4\n" + // + ""; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } + + @Test + public void testAllComments3() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "[item1, {item2: value2}, {item3: value3}] # Inline Comment1\n" + // + "# Block Comment2\n" + // + ""; + + String result = runEmitterWithCommentsEnabled(data); + + assertEquals(data, result); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ParserWithCommentEnabledTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ParserWithCommentEnabledTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ParserWithCommentEnabledTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ParserWithCommentEnabledTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,382 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comment; + +import org.junit.Test; +import org.yaml.snakeyaml.events.Event; +import org.yaml.snakeyaml.events.Event.ID; +import org.yaml.snakeyaml.parser.Parser; +import org.yaml.snakeyaml.parser.ParserImpl; +import org.yaml.snakeyaml.reader.StreamReader; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class ParserWithCommentEnabledTest { + private boolean DEBUG = false; + + private void println(String s) { + if (DEBUG) println(s); + } + + private void println() { + if (DEBUG) println(); + } + + + private void assertEventListEquals(List expectedEventIdList, Parser parser) { + for (ID expectedEventId : expectedEventIdList) { + parser.checkEvent(expectedEventId); + Event event = parser.getEvent(); + println("Expected: " + expectedEventId); + println("Got: " + event); + println(); + if (event == null) { + fail("Missing event: " + expectedEventId); + } + assertEquals(expectedEventId, event.getEventId()); + } + } + + @SuppressWarnings("unused") + private void printEventList(Parser parser) { + for (Event event = parser.getEvent(); event != null; event = parser.getEvent()) { + println("Got: " + event); + println(); + } + } + + private Parser createParser(String data) { + return new ParserImpl(new StreamReader(data), true); + } + + @Test + public void testEmpty() { + List expectedEventIdList = Arrays.asList(ID.StreamStart, ID.StreamEnd); + + String data = ""; + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testParseWithOnlyComment() { + String data = "# Comment"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.Comment, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testCommentEndingALine() { + String data = "" + // + "key: # Comment\n" + // + " value\n"; + + List expectedEventIdList = Arrays.asList(ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testMultiLineComment() { + String data = "" + // + "key: # Comment\n" + // + " # lines\n" + // + " value\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Comment, ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testBlankLine() { + String data = "" + // + "\n"; + + List expectedEventIdList = Arrays.asList(ID.StreamStart, // + ID.Comment, // + ID.StreamEnd); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testBlankLineComments() { + String data = "" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(ID.StreamStart, // + ID.Comment, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, ID.Comment, // + ID.Comment, // + ID.Comment, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void test_blockScalar() { + String data = "" + // + "abc: > # Comment\n" + // + " def\n" + // + " hij\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, // + ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testDirectiveLineEndComment() { + String data = "%YAML 1.1 #Comment\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testSequence() { + String data = "" + // + "# Comment\n" + // + "list: # InlineComment1\n" + // + "# Block Comment\n" + // + "- item # InlineComment2\n" + // + "# Comment\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.Comment, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, + ID.Comment, // + ID.SequenceStart, // + ID.Scalar, ID.Comment, // + ID.Comment, // + ID.SequenceEnd, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testAllComments1() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "key: # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + " # Block Comment3a\n" + // + " # Block Comment3b\n" + // + " value # Inline Comment2\n" + // + "# Block Comment4\n" + // + "list: # InlineComment3a\n" + // + " # InlineComment3b\n" + // + "# Block Comment5\n" + // + "- item1 # InlineComment4\n" + // + "- item2: [ value2a, value2b ] # InlineComment5\n" + // + "- item3: { key3a: [ value3a1, value3a2 ], key3b: value3b } # InlineComment6\n" + // + "# Block Comment6\n" + // + "---\n" + // + "# Block Comment7\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.Comment, // + ID.Comment, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Comment, // + + ID.Comment, ID.Comment, // + ID.Scalar, ID.Comment, // + + ID.Comment, // + ID.Scalar, ID.Comment, ID.Comment, // + ID.Comment, // + + ID.SequenceStart, // + ID.Scalar, ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.SequenceStart, ID.Scalar, ID.Scalar, ID.SequenceEnd, ID.Comment, // + ID.MappingEnd, + + ID.MappingStart, // + ID.Scalar, // value=item3 + ID.MappingStart, // + ID.Scalar, // value=key3a + ID.SequenceStart, // + ID.Scalar, // value=value3a + ID.Scalar, //value=value3a2 + ID.SequenceEnd, // + ID.Scalar, // value=key3b + ID.Scalar, // value=value3b + ID.MappingEnd, // + ID.Comment, // type=IN_LINE, value= InlineComment6 + ID.Comment, // + ID.MappingEnd, // + ID.SequenceEnd, // + ID.MappingEnd, + ID.DocumentEnd, // + + ID.DocumentStart, // + ID.Comment, // + ID.Scalar, // Empty + ID.DocumentEnd, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + + //printEventList(sut); + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testAllComments2() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "- item1 # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + "# Block Comment3a\n" + // + "# Block Comment3b\n" + // + "- item2: value # Inline Comment2\n" + // + "# Block Comment4\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.Comment, // + ID.Comment, // + ID.DocumentStart, // + ID.SequenceStart, // + ID.Scalar, ID.Comment, ID.Comment, // + ID.Comment, // + ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, ID.Comment, // + ID.Comment, // + ID.MappingEnd, // + ID.SequenceEnd, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + + assertEventListEquals(expectedEventIdList, sut); + } + + @Test + public void testAllComments3() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "[ item1, item2: value2, {item3: value3} ] # Inline Comment1\n" + // + "# Block Comment2\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.Comment, // + ID.DocumentStart, // + ID.SequenceStart, // + ID.Scalar, + ID.MappingStart, // + ID.Scalar, ID.Scalar, // + ID.MappingEnd, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, // + ID.MappingEnd, // + ID.SequenceEnd, // + ID.Comment, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + Parser sut = createParser(data); + +// printEventList(sut); + assertEventListEquals(expectedEventIdList, sut); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ScannerWithCommentEnabledTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ScannerWithCommentEnabledTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/ScannerWithCommentEnabledTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/ScannerWithCommentEnabledTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comment; + +import org.junit.Test; +import org.yaml.snakeyaml.reader.StreamReader; +import org.yaml.snakeyaml.scanner.Scanner; +import org.yaml.snakeyaml.scanner.ScannerImpl; +import org.yaml.snakeyaml.tokens.CommentToken; +import org.yaml.snakeyaml.tokens.ScalarToken; +import org.yaml.snakeyaml.tokens.Token; +import org.yaml.snakeyaml.tokens.Token.ID; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class ScannerWithCommentEnabledTest { + + private void assertTokensEqual(List expected, Scanner sut) { + assertTokensEqual(expected, null, sut); + } + + private void printToken(Token token) { + String value; + switch (token.getTokenId()) { + case Scalar: + value = "(value='" + ((ScalarToken) token).getValue() + "')"; + break; + case Comment: + CommentToken commentToken = (CommentToken) token; + value = "(type='" + commentToken.getCommentType() + ", value='" + commentToken.getValue() + "')"; + break; + default: + value = ""; + break; + } + //System.out.println(token.getTokenId().name() + value); + } + + private void assertTokenEquals(Iterator expectedIdIterator, Iterator expectedScalarValueIterator, + Token token) { + printToken(token); + assertTrue(expectedIdIterator.hasNext()); + ID expectedValue = expectedIdIterator.next(); + assertSame(expectedValue, token.getTokenId()); + if (expectedScalarValueIterator != null && token.getTokenId() == ID.Scalar) { + assertEquals(expectedScalarValueIterator.next(), ((ScalarToken) token).getValue()); + } + } + + private void assertTokensEqual(List expectedList, List expectedScalarValueList, Scanner sut) { + Iterator expectedIterator = expectedList.iterator(); + Iterator expectedScalarValueIterator = expectedScalarValueList == null ? null + : expectedScalarValueList.iterator(); + while (!sut.checkToken(Token.ID.StreamEnd)) { + Token token = sut.getToken(); + assertTokenEquals(expectedIterator, expectedScalarValueIterator, token); + } + Token token = sut.peekToken(); + assertTokenEquals(expectedIterator, expectedScalarValueIterator, token); + assertFalse(expectedIterator.hasNext()); + } + + private Scanner constructScanner(String input) { + return new ScannerImpl(new StreamReader(new StringReader(input))).setEmitComments(true); + } + + @Test + public void testEmitComments() { + ScannerImpl sutWithOutComments = new ScannerImpl(new StreamReader(new StringReader(""))).setEmitComments(false); + assertFalse(sutWithOutComments.isEmitComments()); + ScannerImpl sutWithComments = new ScannerImpl(new StreamReader(new StringReader(""))).setEmitComments(true); + assertTrue(sutWithComments.isEmitComments()); + } + + @Test + public void testEmpty() { + List expected = Arrays.asList(ID.StreamStart, ID.StreamEnd); + + Scanner sut = constructScanner(""); + + assertTokensEqual(expected, sut); + } + + @Test + public void testOnlyCommentLines() { + List expected = Arrays.asList(ID.StreamStart, // + ID.Comment, // + ID.Comment, // + ID.StreamEnd); + + Scanner sut = constructScanner("" + // + "# This stream contains no\n" + // + "# documents, only comments."); + + assertTokensEqual(expected, sut); + } + + @Test + public void testCommentEndingALine() { + List expected = Arrays.asList(ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, // + ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd); + List expectedScalarValue = Arrays.asList(// + "key", "value"); + + Scanner sut = constructScanner("" + // + "key: # Comment\n" + // + " value\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void testMultiLineComment() { + List expected = Arrays.asList(ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Comment, // + ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd); + List expectedScalarValue = Arrays.asList(// + "key", "value"); + + Scanner sut = constructScanner("" + // + "key: # Comment\n" + // + " # lines\n" + // + " value\n" + // + "\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void testBlankLine() { + List expected = Arrays.asList(ID.StreamStart, // + ID.Comment, // + ID.StreamEnd); + + Scanner sut = constructScanner("" + // + "\n"); + + assertTokensEqual(expected, sut); + } + + @Test + public void testBlankLineComments() { + List expected = Arrays.asList(ID.StreamStart, // + ID.Comment, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Scalar, ID.Comment, // + ID.Comment, // + ID.Comment, // + ID.BlockEnd, // + ID.StreamEnd); + + Scanner sut = constructScanner("" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"); + + assertTokensEqual(expected, sut); + } + + @Test + public void test_blockScalar_replaceNLwithSpaces_singleNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, // + ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def hij\n"); + + Scanner sut = constructScanner("abc: > # Comment\n def\n hij\n\n"); + + //printTokens(sut); + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void test_blockScalar_replaceNLwithSpaces_noNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def hij"); + + Scanner sut = constructScanner("abc: >- # Comment\n def\n hij\n\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void test_blockScalar_replaceNLwithSpaces_allNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Scalar, // + ID.Comment, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def hij\n\n"); + + Scanner sut = constructScanner("abc: >+ # Comment\n def\n hij\n\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void test_blockScalar_keepNL_singleNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def\nhij\n"); + + Scanner sut = constructScanner("abc: | # Comment\n def\n hij\n\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void test_blockScalar_keepNL_noNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Scalar, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def\nhij"); + + Scanner sut = constructScanner("abc: |- # Comment\n def\n hij\n\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void test_blockScalar_keepNL_allNLatEnd() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.BlockMappingStart, // + ID.Key, ID.Scalar, ID.Value, ID.Comment, ID.Scalar, // + ID.Comment, // + ID.BlockEnd, // + ID.StreamEnd // + ); + List expectedScalarValue = Arrays.asList(// + "abc", "def\nhij\n\n"); + + Scanner sut = constructScanner("abc: |+ # Comment\n def\n hij\n\n"); + + assertTokensEqual(expected, expectedScalarValue, sut); + } + + @Test + public void testDirectiveLineEndComment() { + List expected = Arrays.asList(// + ID.StreamStart, // + ID.Directive, // + ID.Comment, // + ID.StreamEnd // + ); + + Scanner sut = constructScanner("%YAML 1.1 #Comment\n"); + + assertTokensEqual(expected, sut); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/SerializerWithCommentEnabledTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/SerializerWithCommentEnabledTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/comment/SerializerWithCommentEnabledTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/comment/SerializerWithCommentEnabledTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,412 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.comment; + +import org.junit.Test; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.composer.Composer; +import org.yaml.snakeyaml.emitter.Emitable; +import org.yaml.snakeyaml.events.Event; +import org.yaml.snakeyaml.events.Event.ID; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.parser.ParserImpl; +import org.yaml.snakeyaml.reader.StreamReader; +import org.yaml.snakeyaml.resolver.Resolver; +import org.yaml.snakeyaml.serializer.Serializer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SerializerWithCommentEnabledTest { + private boolean DEBUG = false; + + private void println(String s) { + if (DEBUG) println(s); + } + + private void println() { + if (DEBUG) println(); + } + + private void assertEventListEquals(List expectedEventIdList, List actualEvents) { + Iterator iterator = actualEvents.iterator(); + for (ID expectedEventId : expectedEventIdList) { + println("Expected: " + expectedEventId); + assertTrue(iterator.hasNext()); + Event event = iterator.next(); + println("Got: " + event); + println(); + assertEquals(expectedEventId, event.getEventId()); + } + } + + private static class TestEmitter implements Emitable { + private List eventList = new ArrayList<>(); + + @Override + public void emit(Event event) throws IOException { + eventList.add(event); + } + + public List getEventList() { + return eventList; + } + } + + public List serializeWithCommentsEnabled(String data) throws IOException { + TestEmitter emitter = new TestEmitter(); + Tag rootTag = null; + Serializer serializer = new Serializer(emitter, new Resolver(), new DumperOptions(), rootTag); + serializer.open(); + Composer composer = new Composer(new ParserImpl(new StreamReader(data), true), new Resolver()); + while (composer.checkNode()) { + serializer.serialize(composer.getNode()); + } + serializer.close(); + List events = emitter.getEventList(); + println("RESULT: "); + for (Event event : events) { + println(event.toString()); + } + println(); + return events; + } + + + @Test + public void testEmpty() throws Exception { + List expectedEventIdList = Arrays.asList(ID.StreamStart, ID.StreamEnd); + + String data = ""; + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testParseWithOnlyComment() throws Exception { + String data = "# Comment"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testCommentEndingALine() throws Exception { + String data = "" + // + "key: # Comment\n" + // + " value\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testMultiLineComment() throws Exception { + String data = "" + // + "key: # Comment\n" + // + " # lines\n" + // + " value\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Comment, ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testBlankLine() throws Exception { + String data = "" + // + "\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testBlankLineComments() throws Exception { + String data = "" + // + "\n" + // + "abc: def # commment\n" + // + "\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, ID.Comment, // + ID.MappingEnd, // + ID.Comment, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void test_blockScalar() throws Exception { + String data = "" + // + "abc: > # Comment\n" + // + " def\n" + // + " hij\n" + // + "\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.MappingStart, // + ID.Scalar, ID.Comment, // + ID.Scalar, // + ID.MappingEnd, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testDirectiveLineEndComment() throws Exception { + String data = "%YAML 1.1 #Comment\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testSequence() throws Exception { + String data = "" + // + "# Comment\n" + // + "list: # InlineComment1\n" + // + "# Block Comment\n" + // + "- item # InlineComment2\n" + // + "# Comment\n"; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Comment, // + ID.SequenceStart, // + ID.Scalar, ID.Comment, // + ID.SequenceEnd, // + ID.MappingEnd, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testAllComments1() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "key: # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + " # Block Comment3a\n" + // + " # Block Comment3b\n" + // + " value # Inline Comment2\n" + // + "# Block Comment4\n" + // + "list: # InlineComment3a\n" + // + " # InlineComment3b\n" + // + "# Block Comment5\n" + // + "- item1 # InlineComment4\n" + // + "- item2: [ value2a, value2b ] # InlineComment5\n" + // + "- item3: { key3a: [ value3a1, value3a2 ], key3b: value3b } # InlineComment6\n" + // + "# Block Comment6\n" + // + "---\n" + // + "# Block Comment7\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.Comment, ID.Comment, // + + ID.Comment, ID.Comment, // + ID.Scalar, ID.Comment, // + + ID.Comment, // + ID.Scalar, ID.Comment, ID.Comment, // + ID.Comment, // + + ID.SequenceStart, // + ID.Scalar, ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.SequenceStart, ID.Scalar, ID.Scalar, ID.SequenceEnd, ID.Comment, // + ID.MappingEnd, + + ID.MappingStart, // + ID.Scalar, // value=item3 + ID.MappingStart, // + ID.Scalar, // value=key3a + ID.SequenceStart, // + ID.Scalar, // value=value3a + ID.Scalar, // value=value3a2 + ID.SequenceEnd, // + ID.Scalar, // value=key3b + ID.Scalar, // value=value3b + ID.MappingEnd, // + ID.Comment, // type=IN_LINE, value= InlineComment6 + ID.MappingEnd, // + ID.SequenceEnd, // + ID.MappingEnd, // + ID.Comment, // + ID.DocumentEnd, // + + ID.DocumentStart, // + ID.Comment, // + ID.Scalar, // Empty + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testAllComments2() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "# Block Comment2\n" + // + "- item1 # Inline Comment1a\n" + // + " # Inline Comment1b\n" + // + "# Block Comment3a\n" + // + "# Block Comment3b\n" + // + "- item2: value # Inline Comment2\n" + // + "# Block Comment4\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.Comment, // + ID.SequenceStart, // + ID.Scalar, ID.Comment, ID.Comment, // + ID.Comment, // + ID.Comment, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, ID.Comment, // + ID.MappingEnd, // + ID.SequenceEnd, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } + + @Test + public void testAllComments3() throws Exception { + String data = "" + // + "# Block Comment1\n" + // + "[ item1, item2: value2, {item3: value3} ] # Inline Comment1\n" + // + "# Block Comment2\n" + // + ""; + + List expectedEventIdList = Arrays.asList(// + ID.StreamStart, // + ID.DocumentStart, // + ID.Comment, // + ID.SequenceStart, // + ID.Scalar, ID.MappingStart, // + ID.Scalar, ID.Scalar, // + ID.MappingEnd, // + ID.MappingStart, // + ID.Scalar, ID.Scalar, // + ID.MappingEnd, // + ID.SequenceEnd, // + ID.Comment, // + ID.Comment, // + ID.DocumentEnd, // + ID.StreamEnd // + ); + + List result = serializeWithCommentsEnabled(data); + + assertEventListEquals(expectedEventIdList, result); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/emitter/EmitterTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/emitter/EmitterTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/emitter/EmitterTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/emitter/EmitterTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -130,6 +130,10 @@ emitter.emit(new DocumentStartEvent(null, null, false, null, null)); emitter.emit(new ScalarEvent(null, null, new ImplicitTuple(true, false), burger + halfBurger, null, null, DumperOptions.ScalarStyle.DOUBLE_QUOTED)); + // Needed as emitter won't process above event until it peeks at this one + // to be sure it is not a comment + emitter.emit(new ScalarEvent(null, null, new ImplicitTuple(true, false), "", null, + null, DumperOptions.ScalarStyle.PLAIN)); String expected = "! \"\\U0001f354\\ud83c\""; assertEquals(expected, output.toString()); } diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/emitter/EmptyStringOutputTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/emitter/EmptyStringOutputTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/emitter/EmptyStringOutputTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/emitter/EmptyStringOutputTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -45,6 +45,9 @@ emitter.emit(new StreamStartEvent(null, null)); emitter.emit(new DocumentStartEvent(null, null, false, null, null)); emitter.emit(new ScalarEvent(null, null, new ImplicitTuple(true, false), value, null, null, DumperOptions.ScalarStyle.PLAIN)); + // Needed as emitter won't process above event until it peeks at this one + // to be sure it is not a comment + emitter.emit(new ScalarEvent(null, null, new ImplicitTuple(true, false), value, null, null, DumperOptions.ScalarStyle.PLAIN)); return output.toString(); } } diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/env/EnvVariableTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/env/EnvVariableTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/env/EnvVariableTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/env/EnvVariableTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -86,4 +86,13 @@ String output = compose.toString(); assertTrue(output, output.endsWith("environment={URL1=EnvironmentValue1, URL2=, URL3=server3, URL4=, URL5=server5, URL6=server6}}}}")); } + + public void testIssue493() { + Yaml yaml = new Yaml(new EnvScalarConstructor()); + yaml.addImplicitResolver(EnvScalarConstructor.ENV_TAG, EnvFormatTest.ENV_FORMAT, "$"); + String resource = Util.getLocalResource("env/env-493.yaml"); + Map compose = yaml.load(resource); + String output = compose.toString(); + assertEquals("{database={url=jdbc:postgresql://localhost:5432/server493, user=user493, password=password493}}", output); + } } diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue307/OrderTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue307/OrderTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue307/OrderTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue307/OrderTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -38,7 +38,7 @@ String s = Util.getLocalResource("issues/issue307-order.yaml"); OrderBean orderBean = yaml.loadAs(s, OrderBean.class); String dump = yaml.dump(orderBean); - System.out.println(dump); + //System.out.println(dump); String str = "!!org.yaml.snakeyaml.issues.issue307.OrderBean\n" + "name: tian\n" + "type: {z: 256, y: 255, x: 254}\n" + @@ -55,7 +55,7 @@ CustomerBean orderBean2 = yaml.loadAs(s, CustomerBean.class); orderBean2.setCustomerName("customer"); String dump = yaml.dump(orderBean2); - System.out.println(dump); + //System.out.println(dump); String str = "!!org.yaml.snakeyaml.issues.issue307.CustomerBean\n" + "customerName: customer\n" + "name: tian\n" + diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue468/NonAsciiAnchorTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue468/NonAsciiAnchorTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue468/NonAsciiAnchorTest.java 2020-09-01 13:59:55.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue468/NonAsciiAnchorTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -19,19 +19,39 @@ import org.yaml.snakeyaml.Yaml; public class NonAsciiAnchorTest extends TestCase { - private final String NON_ANCHORS = ":,[]{}"; + private final String NON_ANCHORS = ":,[]{}*&./"; public void testNonAsciiAnchor() { Yaml loader = new Yaml(); - String floatValue = loader.load("&something_タスク タスク"); - assertEquals("タスク", floatValue); + String value = loader.load("&something_タスク タスク"); + assertEquals("タスク", value); + } + + public void testUnderscore() { + Yaml loader = new Yaml(); + String value = loader.load("&_ タスク"); + assertEquals("タスク", value); + } + + public void testSmile() { + Yaml loader = new Yaml(); + String value = loader.load("&\uD83D\uDE01 v1"); + //System.out.println("&\uD83D\uDE01 v1"); + assertEquals("v1", value); + } + + public void testAlpha() { + Yaml loader = new Yaml(); + String value = loader.load("&kääk v1"); + assertEquals("v1", value); } public void testNonAllowedAnchor() { for (int i = 0; i < NON_ANCHORS.length(); i++) { try { - loadWith(NON_ANCHORS.charAt(i)); - fail("Special chars should not be allowed in anchor name"); + Character c = NON_ANCHORS.charAt(i); + loadWith(c); + fail("Special chars should not be allowed in anchor name: " + c); } catch (Exception e) { assertTrue(e.getMessage(), e.getMessage().contains("while scanning an anchor")); assertTrue(e.getMessage(), e.getMessage().contains("unexpected character found")); diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue484/Base60FloatTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue484/Base60FloatTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue484/Base60FloatTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue484/Base60FloatTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.issues.issue484; + +import junit.framework.TestCase; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Util; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.serializer.AnchorGenerator; + +import java.io.StringReader; +import java.io.StringWriter; + +public class Base60FloatTest extends TestCase { + + public void test60Float() { + Yaml yamlProcessor = new Yaml(); + Double base60 = yamlProcessor.load("86:00.0"); + assertEquals(5160.0, base60); + } +} diff -Nru snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue485/RestrictAliasNamesTest.java snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue485/RestrictAliasNamesTest.java --- snakeyaml-1.27+ds/src/test/java/org/yaml/snakeyaml/issues/issue485/RestrictAliasNamesTest.java 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/java/org/yaml/snakeyaml/issues/issue485/RestrictAliasNamesTest.java 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2008, http://www.snakeyaml.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.yaml.snakeyaml.issues.issue485; + +import junit.framework.TestCase; +import org.yaml.snakeyaml.Yaml; + +public class RestrictAliasNamesTest extends TestCase { + + public void testAliasFromRuby() { + try { + Yaml yamlProcessor = new Yaml(); + yamlProcessor.load("Exclude: **/*_old.rb"); + fail("Should not accept Alias **/*_old.rb"); + } catch (Exception e) { + assertTrue(e.getMessage().contains("unexpected character found *(42)")); + } + } +} diff -Nru snakeyaml-1.27+ds/src/test/resources/env/env-493.yaml snakeyaml-1.28/src/test/resources/env/env-493.yaml --- snakeyaml-1.27+ds/src/test/resources/env/env-493.yaml 1970-01-01 00:00:00.000000000 +0000 +++ snakeyaml-1.28/src/test/resources/env/env-493.yaml 2021-02-22 05:54:32.000000000 +0000 @@ -0,0 +1,4 @@ +database: + url: ${DATABASE_URL:-jdbc:postgresql://localhost:5432/server493} + user: ${DATABASE_USER:-user493} + password: ${DATABASE_PASSWORD:-password493} \ No newline at end of file