Bug 574900: [Yaml-Source] Add unit tests for AST node properties

Change-Id: I5b301f62aa5a7c7b7e96dc163f40cab2cb1f5493
diff --git a/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/internal/yaml/snakeyaml/scanner/Ast2EventConverter.java b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/internal/yaml/snakeyaml/scanner/Ast2EventConverter.java
index cd42e93..083cd14 100644
--- a/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/internal/yaml/snakeyaml/scanner/Ast2EventConverter.java
+++ b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/internal/yaml/snakeyaml/scanner/Ast2EventConverter.java
@@ -206,7 +206,7 @@
 	
 	@Override
 	public void visit(final Scalar node) throws InvocationTargetException {
-		String value= String.valueOf(node.getOperator());
+		String value= (node.getOperator() != 0) ? String.valueOf(node.getOperator()) : ":";
 		if (node.getText() != null) {
 			value+= node.getText();
 		}
diff --git a/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlAstTests.java b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlAstTests.java
new file mode 100644
index 0000000..e5ffcb6
--- /dev/null
+++ b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlAstTests.java
@@ -0,0 +1,49 @@
+/*=============================================================================#
+ # Copyright (c) 2022 Stephan Wahlbrink and others.
+ # 
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ # 
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ # 
+ # Contributors:
+ #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.yaml.core.source.ast;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.text.core.TextRegion;
+
+
+@NonNullByDefault
+public class YamlAstTests {
+	
+	
+	public static void assertNoChildren(final YamlAstNode node) {
+		assertEquals(0, node.getChildCount(), "childCount");
+		assertFalse(node.hasChildren(), "hasChildren");
+	}
+	
+	public static void assertChildren(final int expectedCount, final YamlAstNode node) {
+		assertEquals(expectedCount, node.getChildCount(), "childCount");
+		assertTrue(node.hasChildren(), "hasChildren");
+	}
+	
+	public static void assertRegion(final int expectedOffset, final int expectedLength,
+			final TextRegion actual) {
+		assertEquals(expectedOffset, actual.getStartOffset(), "startOffset");
+		assertEquals(expectedOffset +  expectedLength, actual.getEndOffset(), "endOffset");
+	}
+	
+	
+	private YamlAstTests() {
+	}
+	
+}
diff --git a/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlParserTest.java b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlParserTest.java
new file mode 100644
index 0000000..50474de
--- /dev/null
+++ b/yaml/org.eclipse.statet.yaml.core-tests/src/org/eclipse/statet/yaml/core/source/ast/YamlParserTest.java
@@ -0,0 +1,292 @@
+/*=============================================================================#
+ # Copyright (c) 2022 Stephan Wahlbrink and others.
+ # 
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ # 
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ # 
+ # Contributors:
+ #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.yaml.core.source.ast;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import static org.eclipse.statet.yaml.core.source.ast.YamlAstTests.assertChildren;
+import static org.eclipse.statet.yaml.core.source.ast.YamlAstTests.assertNoChildren;
+import static org.eclipse.statet.yaml.core.source.ast.YamlAstTests.assertRegion;
+
+import org.junit.jupiter.api.Test;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+
+@NonNullByDefault
+public class YamlParserTest {
+	
+	
+	private final YamlParser parser;
+	
+	
+	public YamlParserTest() {
+		this.parser= new YamlParser();
+		this.parser.setScalarText(true);
+	}
+	
+	
+	@Test
+	public void parseScalar_Plain() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("ABC");
+		
+		final YamlAstNode node= assertNodeInDoc(3, sourceComponent);
+		assertEquals(NodeType.SCALAR, node.getNodeType());
+		assertEquals('\0', node.getOperator());
+		assertRegion(0, 3, node);
+		assertNoChildren(node);
+		assertEquals("ABC", node.getText());
+	}
+	
+	@Test
+	public void parseScalar_SingleQuoted() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("'ABC'");
+		
+		final YamlAstNode node= assertNodeInDoc(5, sourceComponent);
+		assertEquals(NodeType.SCALAR, node.getNodeType());
+		assertEquals('\'', node.getOperator());
+		assertRegion(0, 5, node);
+		assertNoChildren(node);
+		assertEquals("ABC", node.getText());
+	}
+	
+	@Test
+	public void parseScalar_DoubleQuoted() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("\"ABC\"");
+		
+		final YamlAstNode node= assertNodeInDoc(5, sourceComponent);
+		assertEquals(NodeType.SCALAR, node.getNodeType());
+		assertEquals('\"', node.getOperator());
+		assertRegion(0, 5, node);
+		assertNoChildren(node);
+		assertEquals("ABC", node.getText());
+	}
+	
+	@Test
+	public void parseAlias() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("*name");
+		
+		final YamlAstNode node= assertNodeInDoc(5, sourceComponent);
+		assertEquals(NodeType.ALIAS, node.getNodeType());
+		assertEquals('*', node.getOperator());
+		assertRegion(0, 5, node);
+		assertNoChildren(node);
+		assertEquals("name", node.getText());
+	}
+	
+	@Test
+	public void parseNodeWithProperties() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("&alias !!str 'A'");
+		
+		final YamlAstNode node= assertNodeInDoc(16, sourceComponent);
+		assertEquals(NodeType.PROPERTIES_CONTAINER, node.getNodeType());
+		final var nodeWithProperties= (NodeWithProperties)node;
+		final var properties= nodeWithProperties.getProperties();
+		
+		assertRegion(0, 16, node);
+		assertChildren(3, node);
+		assertEquals(2, properties.size());
+		assertNull(node.getText());
+		
+		assertRegion(0, 6, node.getChild(0));
+		assertRegion(7, 5, node.getChild(1));
+		assertRegion(13, 3, node.getChild(2));
+	}
+	
+	@Test
+	public void parseAnchor() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("&name 'A'");
+		
+		final YamlAstNode containerNode= assertNodeInDoc(9, sourceComponent);
+		assertEquals(NodeType.PROPERTIES_CONTAINER, containerNode.getNodeType());
+		final var properties= ((NodeWithProperties)containerNode).getProperties();
+		assertEquals(1, properties.size());
+		
+		final YamlAstNode node= containerNode.getChild(0);
+		assertEquals(NodeType.ANCHOR, node.getNodeType());
+		assertTrue(node == properties.get(0));
+		assertEquals('&', node.getOperator());
+		assertRegion(0, 5, node);
+		assertNoChildren(node);
+		assertEquals("name", node.getText());
+	}
+	
+	@Test
+	public void parseTag_Shorthand() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("!!str 'A'");
+		
+		final YamlAstNode containerNode= assertNodeInDoc(9, sourceComponent);
+		assertEquals(NodeType.PROPERTIES_CONTAINER, containerNode.getNodeType());
+		final var properties= ((NodeWithProperties)containerNode).getProperties();
+		assertEquals(1, properties.size());
+		
+		final YamlAstNode node= containerNode.getChild(0);
+		assertEquals(NodeType.TAG, node.getNodeType());
+		final var tagNode= (Tag)node;
+		assertTrue(node == properties.get(0));
+		assertRegion(0, 5, node);
+		assertNoChildren(node);
+		assertEquals("str", node.getText());
+		assertEquals("!!", tagNode.getHandle());
+		assertEquals("str", tagNode.getSuffix());
+	}
+	
+	@Test
+	public void parseTag_Verbatim() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("!<!test> 'A'");
+		
+		final YamlAstNode containerNode= assertNodeInDoc(12, sourceComponent);
+		assertEquals(NodeType.PROPERTIES_CONTAINER, containerNode.getNodeType());
+		final var properties= ((NodeWithProperties)containerNode).getProperties();
+		assertEquals(1, properties.size());
+		
+		final YamlAstNode node= containerNode.getChild(0);
+		assertEquals(NodeType.TAG, node.getNodeType());
+		final var tagNode= (Tag)node;
+		assertTrue(node == properties.get(0));
+		assertRegion(0, 8, node);
+		assertNoChildren(node);
+		assertEquals("!test", node.getText());
+		assertNull(tagNode.getHandle());
+		assertEquals("!test", tagNode.getSuffix());
+	}
+	
+	
+	@Test
+	public void parseSeq_Block() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("- A\n- B");
+		
+		final YamlAstNode node= assertNodeInDoc(7, sourceComponent);
+		assertEquals(NodeType.SEQ, node.getNodeType());
+		assertEquals('-', node.getOperator());
+		assertRegion(0, 7, node);
+		assertChildren(2, node);
+		
+		final YamlAstNode entry0= node.getChild(0);
+		assertEquals(NodeType.SEQ_ENTRY, entry0.getNodeType());
+		assertRegion(0, 3, entry0);
+		assertChildren(1, entry0);
+		assertEquals(NodeType.SCALAR, entry0.getChild(0).getNodeType());
+		
+		final YamlAstNode entry1= node.getChild(1);
+		assertEquals(NodeType.SEQ_ENTRY, entry1.getNodeType());
+		assertRegion(4, 3, entry1);
+		assertChildren(1, entry1);
+		assertEquals(NodeType.SCALAR, entry1.getChild(0).getNodeType());
+		
+		assertNull(node.getText());
+	}
+	
+	@Test
+	public void parseSeq_Flow() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("[ A, B ]");
+		
+		final YamlAstNode node= assertNodeInDoc(8, sourceComponent);
+		assertEquals(NodeType.SEQ, node.getNodeType());
+		assertEquals('[', node.getOperator());
+		assertRegion(0, 8, node);
+		assertChildren(2, node);
+		
+		final YamlAstNode entry0= node.getChild(0);
+		assertEquals("A", entry0.getText());
+		assertRegion(2, 1, entry0);
+		
+		final YamlAstNode entry1= node.getChild(1);
+		assertEquals("B", entry1.getText());
+		assertRegion(5, 1, entry1);
+		
+		assertNull(node.getText());
+	}
+	
+	
+	@Test
+	public void parseMap_Block() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("key1 : A\nkey2 : B");
+		
+		final YamlAstNode node= assertNodeInDoc(17, sourceComponent);
+		assertEquals(NodeType.MAP, node.getNodeType());
+		assertEquals('?', node.getOperator());
+		assertRegion(0, 17, node);
+		assertChildren(2, node);
+		
+		final YamlAstNode entry0= node.getChild(0);
+		assertEquals(NodeType.MAP_ENTRY, entry0.getNodeType());
+		final var mapEntry0= (MapEntry)entry0;
+		assertRegion(0, 8, entry0);
+		assertChildren(2, entry0);
+		assertEquals("key1", entry0.getChild(0).getText());
+		assertEquals(5, mapEntry0.getValueIndicatorOffset());
+		assertEquals("A", entry0.getChild(1).getText());
+		
+		final YamlAstNode entry1= node.getChild(1);
+		assertEquals(NodeType.MAP_ENTRY, entry1.getNodeType());
+		final var mapEntry1= (MapEntry)entry1;
+		assertRegion(9, 8, entry1);
+		assertChildren(2, entry1);
+		assertEquals("key2", entry1.getChild(0).getText());
+		assertEquals(9 + 5, mapEntry1.getValueIndicatorOffset());
+		assertEquals("B", entry1.getChild(1).getText());
+		
+		assertNull(node.getText());
+	}
+	
+	@Test
+	public void parseMap_Flow() {
+		final SourceComponent sourceComponent= this.parser.parseSourceUnit("{ key1 : A, key2 : B }");
+		
+		final YamlAstNode node= assertNodeInDoc(22, sourceComponent);
+		assertEquals(NodeType.MAP, node.getNodeType());
+		assertEquals('{', node.getOperator());
+		assertRegion(0, 22, node);
+		assertChildren(2, node);
+		
+		final YamlAstNode entry0= node.getChild(0);
+		assertEquals(NodeType.MAP_ENTRY, entry0.getNodeType());
+		final var mapEntry0= (MapEntry)entry0;
+		assertRegion(2, 8, entry0);
+		assertChildren(2, entry0);
+		assertEquals("key1", entry0.getChild(0).getText());
+		assertEquals(7, mapEntry0.getValueIndicatorOffset());
+		assertEquals("A", entry0.getChild(1).getText());
+		
+		final YamlAstNode entry1= node.getChild(1);
+		assertEquals(NodeType.MAP_ENTRY, entry1.getNodeType());
+		final var mapEntry1= (MapEntry)entry1;
+		assertRegion(12, 8, entry1);
+		assertChildren(2, entry1);
+		assertEquals("key2", entry1.getChild(0).getText());
+		assertEquals(12 + 5, mapEntry1.getValueIndicatorOffset());
+		assertEquals("B", entry1.getChild(1).getText());
+		
+		assertNull(node.getText());
+	}
+	
+	
+	private YamlAstNode assertNodeInDoc(final int expectedLength, final YamlAstNode rootNode) {
+		assertEquals(NodeType.SOURCELINES, rootNode.getNodeType());
+		assertRegion(0, expectedLength, rootNode);
+		assertChildren(1, rootNode);
+		
+		final YamlAstNode documentNode= rootNode.getChild(0);
+		assertEquals(NodeType.DOCUMENT, documentNode.getNodeType());
+		assertRegion(0, expectedLength, rootNode);
+		assertChildren(1, documentNode);
+		
+		return documentNode.getChild(0);
+	}
+	
+}
diff --git a/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Scalar.java b/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Scalar.java
index 4c60b29..aae0334 100644
--- a/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Scalar.java
+++ b/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Scalar.java
@@ -96,7 +96,7 @@
 		
 		@Override
 		public char getOperator() {
-			return ':';
+			return 0;
 		}
 		
 	}
diff --git a/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Tag.java b/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Tag.java
index cfe9773..c72bb64 100644
--- a/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Tag.java
+++ b/yaml/org.eclipse.statet.yaml.core/src/org/eclipse/statet/yaml/core/source/ast/Tag.java
@@ -46,6 +46,14 @@
 	}
 	
 	
+	public @Nullable String getHandle() {
+		return this.handle;
+	}
+	
+	public String getSuffix() {
+		return this.suffix;
+	}
+	
 	@Override
 	public String getText() {
 		return this.suffix;