From 93b6a704d5f306c4ba7caca73608937a97dfce79 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 2 Dec 2020 15:10:41 -0800 Subject: [PATCH] Re-enable and fix failing concourse editor tests Signed-off-by: Kris De Volder --- concourse/experimental-pipeline.yml | 38 ++-- .../commons/yaml/ast/NodeMergeSupport.java | 162 ++++++++++-------- .../vscode/commons/yaml/ast/YamlParser.java | 6 +- .../SchemaBasedYamlASTReconciler.java | 7 +- .../vscode/concourse/ConcourseEditorTest.java | 39 ++++- 5 files changed, 157 insertions(+), 95 deletions(-) diff --git a/concourse/experimental-pipeline.yml b/concourse/experimental-pipeline.yml index 642c327d3..a065e1c07 100644 --- a/concourse/experimental-pipeline.yml +++ b/concourse/experimental-pipeline.yml @@ -1,17 +1,25 @@ -resources: -- name: docker-base - type: registry-image - source: - repository: alpine +sleep: &sleep + config: + platform: linux + image_resource: + type: docker-image + source: + repository: alpine + tag: latest + run: + path: sh + args: + - -exc + - sleep 60 + +########## + +resource_types: +- name: pool + type: docker-image + jobs: -- name: publish-jvm-launch-utils +- name: acquire-1 plan: - - get: docker-base - trigger: true - params: - skip_download: true - - put: docker-base - get_params: - skip_download: true - params: - image: blah + - task: sleep + <<: *sleep diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeMergeSupport.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeMergeSupport.java index 65bf0be08..bbeb641d6 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeMergeSupport.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeMergeSupport.java @@ -28,6 +28,9 @@ import java.util.Map; import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector; import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaProblems; +import org.springframework.ide.vscode.commons.yaml.util.YamlUtil; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.events.Event; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeTuple; @@ -48,83 +51,90 @@ public class NodeMergeSupport { this.problems = problems; } - public void flattenMapping(MappingNode node) { - // perform merging only on nodes containing merge node(s) - //processDuplicateKeys(node); - if (node.isMerged()) { - node.setValue(mergeNode(node, true, new HashMap(), - new ArrayList())); - node.setMerged(false); - } - } + public void flattenMapping(Node node) { + if (node instanceof MappingNode) { + flattenMapping((MappingNode)node); + } + } - /** - * Does merge for supplied mapping node. - * - * @param node - * where to merge - * @param isPreffered - * true if keys of node should take precedence over others... - * @param key2index - * maps already merged keys to index from values - * @param values - * collects merged NodeTuple - * @return list of the merged NodeTuple (to be set as value for the - * MappingNode) - */ - private List mergeNode(MappingNode node, boolean isPreffered, - Map key2index, List values) { - Iterator iter = node.getValue().iterator(); - while (iter.hasNext()) { - final NodeTuple nodeTuple = iter.next(); - final Node keyNode = nodeTuple.getKeyNode(); - final Node valueNode = nodeTuple.getValueNode(); - if (keyNode.getTag().equals(Tag.MERGE)) { - iter.remove(); - switch (valueNode.getNodeId()) { - case mapping: - MappingNode mn = (MappingNode) valueNode; - mergeNode(mn, false, key2index, values); - break; - case sequence: - SequenceNode sn = (SequenceNode) valueNode; - List vals = sn.getValue(); - for (Node subnode : vals) { - if (!(subnode instanceof MappingNode)) { - problems.accept(YamlSchemaProblems.schemaProblem( - "Expected a mapping for merging, but found "+subnode.getNodeId(), subnode - )); - } else { - MappingNode mnode = (MappingNode) subnode; - mergeNode(mnode, false, key2index, values); - } - } - break; - default: - problems.accept(YamlSchemaProblems.schemaProblem( - "Expected a mapping or list of mappings for merging, but found " - + valueNode.getNodeId(), - valueNode - )); - } - } else { - // we need to construct keys to avoid duplications - String key = NodeUtil.asScalar(keyNode); - if (key!=null) { - if (!key2index.containsKey(key)) { // 1st time merging key - values.add(nodeTuple); - // keep track where tuple for the key is - key2index.put(key, values.size() - 1); - } else if (isPreffered) { // there is value for the key, but we - // need to override it - // change value for the key using saved position - values.set(key2index.get(key), nodeTuple); - } - } - } - } - return values; - } + private void flattenMapping(MappingNode node) { + // perform merging only on nodes containing merge node(s) + //processDuplicateKeys(node); + + if (node.isMerged()) { + node.setValue(mergeNode(node, true, new HashMap(), + new ArrayList())); + node.setMerged(false); + } + } + + /** + * Does merge for supplied mapping node. + * + * @param node + * where to merge + * @param isPreffered + * true if keys of node should take precedence over others... + * @param key2index + * maps already merged keys to index from values + * @param values + * collects merged NodeTuple + * @return list of the merged NodeTuple (to be set as value for the + * MappingNode) + */ + private List mergeNode(MappingNode node, boolean isPreffered, + Map key2index, List values) { + Iterator iter = node.getValue().iterator(); + while (iter.hasNext()) { + final NodeTuple nodeTuple = iter.next(); + final Node keyNode = nodeTuple.getKeyNode(); + final Node valueNode = nodeTuple.getValueNode(); + if (keyNode.getTag().equals(Tag.MERGE)) { + iter.remove(); + switch (valueNode.getNodeId()) { + case mapping: + MappingNode mn = (MappingNode) valueNode; + mergeNode(mn, false, key2index, values); + break; + case sequence: + SequenceNode sn = (SequenceNode) valueNode; + List vals = sn.getValue(); + for (Node subnode : vals) { + if (!(subnode instanceof MappingNode)) { + problems.accept(YamlSchemaProblems.schemaProblem( + "Expected a mapping for merging, but found "+subnode.getNodeId(), subnode + )); + } else { + MappingNode mnode = (MappingNode) subnode; + mergeNode(mnode, false, key2index, values); + } + } + break; + default: + problems.accept(YamlSchemaProblems.schemaProblem( + "Expected a mapping or list of mappings for merging, but found " + + valueNode.getNodeId(), + valueNode + )); + } + } else { + // we need to construct keys to avoid duplications + String key = NodeUtil.asScalar(keyNode); + if (key!=null) { + if (!key2index.containsKey(key)) { // 1st time merging key + values.add(nodeTuple); + // keep track where tuple for the key is + key2index.put(key, values.size() - 1); + } else if (isPreffered) { // there is value for the key, but we + // need to override it + // change value for the key using saved position + values.set(key2index.get(key), nodeTuple); + } + } + } + } + return values; + } } diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java index 07786aaa9..7795f1d4c 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java @@ -16,6 +16,8 @@ import java.util.regex.Pattern; import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.text.IDocument; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.nodes.Node; @@ -32,7 +34,9 @@ public class YamlParser implements YamlASTProvider { public YamlFileAST getAST(IDocument doc) throws Exception { CharSequenceReader reader = new CharSequenceReader(); reader.setInput(atTokenTransformHack(doc.get())); - Iterable nodes = new Yaml().composeAll(reader); + LoaderOptions loaderOpts = new LoaderOptions(); + loaderOpts.setMaxAliasesForCollections(1000); + Iterable nodes = new Yaml(loaderOpts).composeAll(reader); return new YamlFileAST(doc, ImmutableList.copyOf(nodes)); } diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java index 99d7fdff3..852908640 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java @@ -40,6 +40,7 @@ import org.springframework.ide.vscode.commons.util.ValueParseException; import org.springframework.ide.vscode.commons.util.ValueParser; import org.springframework.ide.vscode.commons.util.text.DocumentRegion; import org.springframework.ide.vscode.commons.util.text.IDocument; +import org.springframework.ide.vscode.commons.yaml.ast.AstDumper; import org.springframework.ide.vscode.commons.yaml.ast.NodeMergeSupport; import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; @@ -142,6 +143,11 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { } private void reconcile(YamlFileAST ast, YamlPath path, Node parent, Node node, YType _type) { + nodeMerger.flattenMapping(node); + +// System.out.println("--------- Reconciling ---------"); +// AstDumper.dump(node, 0); + if (_type!=null && !skipReconciling(node)) { DynamicSchemaContext schemaContext = new ASTDynamicSchemaContext(ast, path, node); YType type = typeUtil.inferMoreSpecificType(_type, schemaContext); @@ -152,7 +158,6 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { switch (getNodeId(node)) { case mapping: MappingNode map = (MappingNode) node; - nodeMerger.flattenMapping(map); checkForDuplicateKeys(map); if (typeUtil.isMap(type)) { for (NodeTuple entry : map.getValue()) { diff --git a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java index 905dab0fd..1199649f6 100644 --- a/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java +++ b/headless-services/concourse-language-server/src/test/java/org/springframework/ide/vscode/concourse/ConcourseEditorTest.java @@ -268,7 +268,6 @@ public class ConcourseEditorTest { } @Test - @Ignore public void complexOutlineWithAnchors() throws Exception { harness.enableHierarchicalDocumentSymbols(true); //See: https://github.com/spring-projects/sts4/issues/483 @@ -5807,8 +5806,8 @@ public class ConcourseEditorTest { ); } + @Test - @Ignore public void anchorsAndReferenceSample_1() throws Exception { Editor editor = harness.newEditor( "pool-template: &pool-template\n" + @@ -5888,6 +5887,42 @@ public class ConcourseEditorTest { editor.assertProblems(/*none*/); } + @Test + public void anchorsAndReferenceSample_1_simple() throws Exception { + Editor editor = harness.newEditor( + "sleep: &sleep\n" + + " config:\n" + + " platform: linux\n" + + " image_resource:\n" + + " type: docker-image\n" + + " source:\n" + + " repository: alpine\n" + + " tag: latest\n" + + " run:\n" + + " path: sh\n" + + " args:\n" + + " - -exc\n" + + " - sleep 60\n" + + "\n" + + "##########\n" + + "\n" + + "resource_types:\n" + + "- name: pool\n" + + " type: docker-image\n" + + "\n" + + "jobs:\n" + + "- name: acquire-1\n" + + " plan:\n" + + " - task: sleep\n" + + " <<: *sleep\n" + ); + + System.out.println("============================"); + System.out.println(editor.getRawText()); + System.out.println("============================"); + editor.assertProblems(/*none*/); + } + @Test public void anchorsAndReferenceSample_2() throws Exception { Editor editor = harness.newEditor(