diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java index 0b686c596..ef99875a6 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java @@ -54,7 +54,7 @@ public class NodeUtil { * @return String value or null if node is not a Scalar node. */ public static String asScalar(Node node) { - if (node.getNodeId()==NodeId.scalar) { + if (node!=null && node.getNodeId()==NodeId.scalar) { return ((ScalarNode)node).getValue(); } return null; diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTCursor.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTCursor.java new file mode 100644 index 000000000..26a667af9 --- /dev/null +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTCursor.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2017 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.yaml.path; + +import java.util.stream.Stream; + +import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; +import org.yaml.snakeyaml.nodes.Node; + +/** + * Pointer to a specific node in Snake yaml parse tree. Supports navigation + * using {@link YamlPath}s, including support for 'ambiguous' steps like + * {@link YamlPathSegment}.anyChild() + *

+ * Because the 'root node' of a parsed Yaml file is not actually {@link Node} + * in snake yaml. A cursor pointing at the root of a tree is implemented + * differently than a pointer to a node inside the tree. Therefore + * this class is abstract and has two concrete subclasses. + * + * @author Kris De Volder + */ +public abstract class ASTCursor implements YamlNavigable { + + public abstract Stream traverseAmbiguously(YamlPathSegment s); + + /** + * Return the node this cursor is pointing to. This is either a {@link Node} or + * a {@link YamlFileAST}. + */ + public abstract Object getNode(); + +} diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTRootCursor.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTRootCursor.java new file mode 100644 index 000000000..22e58e8bf --- /dev/null +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/ASTRootCursor.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2017 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.commons.yaml.path; + +import java.util.List; +import java.util.stream.Stream; + +import org.springframework.ide.vscode.commons.util.Assert; +import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; +import org.yaml.snakeyaml.nodes.Node; + +public class ASTRootCursor extends ASTCursor { + + private final YamlFileAST currentNode; + + public ASTRootCursor(YamlFileAST astRoot) { + Assert.isNotNull(astRoot); + this.currentNode = astRoot; + } + + @Override + public YamlFileAST getNode() { + return currentNode; + } + + @Override + public Stream traverseAmbiguously(YamlPathSegment s) { + switch (s.getType()) { + case KEY_AT_KEY: { + return Stream.empty(); + } + case ANY_CHILD: { + return getNode().getNodes().stream().map(NodeCursor::new); + } + case VAL_AT_INDEX: { + List nodes = getNode().getNodes(); + int index = s.toIndex(); + int size = nodes.size(); + if (index= 0) { + return Stream.of(new NodeCursor(nodes.get(index))); + } + return Stream.empty(); + } + case VAL_AT_KEY: { + return Stream.empty(); + } + default: + Assert.isLegal(false, "Bug? Missing switch case?"); + return Stream.empty(); + } + } + +} diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/NodeCursor.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/NodeCursor.java index 732d1eeec..d9975245c 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/NodeCursor.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/NodeCursor.java @@ -14,8 +14,6 @@ import java.util.stream.Stream; import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; -import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.KeyAtKey; -import org.yaml.snakeyaml.nodes.CollectionNode; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.SequenceNode; @@ -27,7 +25,7 @@ import org.yaml.snakeyaml.nodes.SequenceNode; * * @author Kris De Volder */ -public class NodeCursor implements YamlNavigable { +public class NodeCursor extends ASTCursor { private final Node currentNode; @@ -35,9 +33,11 @@ public class NodeCursor implements YamlNavigable { Assert.isNotNull(node); this.currentNode = node; } + + @Override - public Stream traverseAmbiguously(YamlPathSegment s) { + public Stream traverseAmbiguously(YamlPathSegment s) { switch (s.getType()) { case KEY_AT_KEY: { String key = s.toPropString(); @@ -87,6 +87,7 @@ public class NodeCursor implements YamlNavigable { } } + @Override public Node getNode() { return currentNode; } diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java index 9c601d744..98076aefa 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/path/YamlPath.java @@ -17,6 +17,7 @@ import java.util.stream.Stream; import org.springframework.ide.vscode.commons.yaml.ast.NodeRef; import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; +import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.RootRef; import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.SeqRef; import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.TupleValueRef; @@ -121,6 +122,14 @@ public class YamlPath { newPath[segments.length] = s; return new YamlPath(newPath); } + + public Node traverseToNode(YamlFileAST root) { + ASTCursor cursor = traverse(new ASTRootCursor(root)); + if (cursor instanceof NodeCursor) { + return ((NodeCursor)cursor).getNode(); + } + return null; + } public > T traverse(T startNode) { return traverseAmbiguously(startNode).findFirst().orElse(null); @@ -129,8 +138,7 @@ public class YamlPath { public Stream traverseAmbiguously(Node startNode) { if (startNode!=null) { return traverseAmbiguously(new NodeCursor(startNode)) - .map(NodeCursor::getNode); - + .map((ASTCursor cursor) -> (Node)cursor.getNode()); } return Stream.empty(); } diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java index 32532108a..38879041e 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/SchemaBasedYamlASTReconciler.java @@ -26,6 +26,8 @@ import org.springframework.ide.vscode.commons.util.ValueParser; import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; +import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment; import org.springframework.ide.vscode.commons.yaml.schema.ASTDynamicSchemaContext; import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext; import org.springframework.ide.vscode.commons.yaml.schema.YType; @@ -54,23 +56,26 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { public void reconcile(YamlFileAST ast) { List nodes = ast.getNodes(); if (nodes!=null && !nodes.isEmpty()) { - for (Node node : nodes) { - reconcile(ast.getDocument(), node, schema.getTopLevelType()); + for (int i = 0; i < nodes.size(); i++) { + Node node = nodes.get(i); + reconcile(ast.getDocument(), new YamlPath(YamlPathSegment.valueAt(i)), node, schema.getTopLevelType()); } } } - private void reconcile(IDocument doc, Node node, YType type) { + private void reconcile(IDocument doc, YamlPath path, Node node, YType type) { if (type!=null) { - DynamicSchemaContext schemaContext = new ASTDynamicSchemaContext(doc, node); + DynamicSchemaContext schemaContext = new ASTDynamicSchemaContext(doc, path, node); + type = typeUtil.inferMoreSpecificType(type, schemaContext); switch (node.getNodeId()) { case mapping: MappingNode map = (MappingNode) node; checkForDuplicateKeys(map); if (typeUtil.isMap(type)) { for (NodeTuple entry : map.getValue()) { - reconcile(doc, entry.getKeyNode(), typeUtil.getKeyType(type)); - reconcile(doc, entry.getValueNode(), typeUtil.getDomainType(type)); + String key = NodeUtil.asScalar(entry.getKeyNode()); + reconcile(doc, keyAt(path, key), entry.getKeyNode(), typeUtil.getKeyType(type)); + reconcile(doc, valueAt(path, key), entry.getValueNode(), typeUtil.getDomainType(type)); } } else if (typeUtil.isBean(type)) { Map beanProperties = typeUtil.getPropertiesMap(type, schemaContext); @@ -82,10 +87,9 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { } else { YTypedProperty prop = beanProperties.get(key); if (prop==null) { - type = typeUtil.inferMoreSpecificType(type, schemaContext); unknownBeanProperty(keyNode, type, key); } else { - reconcile(doc, entry.getValueNode(), prop.getType()); + reconcile(doc, valueAt(path, key), entry.getValueNode(), prop.getType()); } } } @@ -96,8 +100,9 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { case sequence: SequenceNode seq = (SequenceNode) node; if (typeUtil.isSequencable(type)) { - for (Node el : seq.getValue()) { - reconcile(doc, el, typeUtil.getDomainType(type)); + for (int i = 0; i < seq.getValue().size(); i++) { + Node el = seq.getValue().get(i); + reconcile(doc, valueAt(path, i), el, typeUtil.getDomainType(type)); } } else { expectTypeButFoundSequence(type, node); @@ -124,6 +129,27 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler { } } + private YamlPath keyAt(YamlPath path, String key) { + if (path!=null && key!=null) { + return path.append(YamlPathSegment.keyAt(key)); + } + return null; + } + + private YamlPath valueAt(YamlPath path, int index) { + if (path!=null) { + return path.append(YamlPathSegment.valueAt(index)); + } + return null; + } + + private YamlPath valueAt(YamlPath path, String key) { + if (path!=null && key!=null) { + return path.append(YamlPathSegment.valueAt(key)); + } + return null; + } + private void checkForDuplicateKeys(MappingNode node) { Set duplicateKeys = new HashSet<>(); Set seenKeys = new HashSet<>(); diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/ASTDynamicSchemaContext.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/ASTDynamicSchemaContext.java index d6b7aed09..f2508fa3e 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/ASTDynamicSchemaContext.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/ASTDynamicSchemaContext.java @@ -15,6 +15,7 @@ import java.util.Set; import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeTuple; @@ -31,9 +32,11 @@ public class ASTDynamicSchemaContext extends CachingSchemaContext { private MappingNode mapNode; private IDocument doc; + private YamlPath path; - public ASTDynamicSchemaContext(IDocument doc, Node node) { + public ASTDynamicSchemaContext(IDocument doc, YamlPath path, Node node) { this.doc = doc; + this.path = path; this.mapNode = as(MappingNode.class, node); } @@ -64,4 +67,9 @@ public class ASTDynamicSchemaContext extends CachingSchemaContext { public IDocument getDocument() { return doc; } + + @Override + public YamlPath getPath() { + return path; + } } diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/DynamicSchemaContext.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/DynamicSchemaContext.java index fcf5450a9..211e93f41 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/DynamicSchemaContext.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/DynamicSchemaContext.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.commons.yaml.schema; import java.util.Set; import org.springframework.ide.vscode.commons.util.text.IDocument; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; import com.google.common.collect.ImmutableSet; @@ -38,6 +39,12 @@ public interface DynamicSchemaContext { public IDocument getDocument() { return null; } + + @Override + public YamlPath getPath() { + return null; + } + }; /** @@ -60,4 +67,9 @@ public interface DynamicSchemaContext { */ IDocument getDocument(); + /** + * Returns the yamlpath leading to the current node. + */ + YamlPath getPath(); + } diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/SNodeDynamicSchemaContext.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/SNodeDynamicSchemaContext.java index 7f25f284a..9d6818ecc 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/SNodeDynamicSchemaContext.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/SNodeDynamicSchemaContext.java @@ -18,6 +18,7 @@ import java.util.Set; import org.springframework.ide.vscode.commons.util.CollectionUtil; import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.text.IDocument; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SChildBearingNode; import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SKeyNode; import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode; @@ -61,5 +62,11 @@ public class SNodeDynamicSchemaContext extends CachingSchemaContext { return contextNode.getDocument(); } + @Override + public YamlPath getPath() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YTypeFactory.java b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YTypeFactory.java index 20c02c500..e7e8f74d6 100644 --- a/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YTypeFactory.java +++ b/vscode-extensions/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YTypeFactory.java @@ -44,6 +44,10 @@ import com.google.common.collect.ImmutableMap; */ public class YTypeFactory { + public YType contextAware(String name, SchemaContextAware guessType) { + return new YContextSensitive(name, guessType); + } + public YType yany(String name) { return new YAny(name); } @@ -264,6 +268,32 @@ public class YTypeFactory { } } + + /** + * Represents a type that depends on the DynamicSchemaContext + */ + public static class YContextSensitive extends YAny { + + private final SchemaContextAware typeGuesser; + + public YContextSensitive(String name, SchemaContextAware typeGuesser) { + super(name); + this.typeGuesser = typeGuesser; + } + + @Override + public YType inferMoreSpecificType(DynamicSchemaContext dc) { + if (dc!=null) { + YType inferred = typeGuesser.withContext(dc); + if (inferred!=null) { + return inferred; + } + } + return this; + } + + } + /** * Represents a type that is completely unconstrained. Anything goes: A map, a sequence or some @@ -415,7 +445,7 @@ public class YTypeFactory { * this property is being assigned a value we can infer from that which * specific bean-type we are dealing with. */ - public class YBeanUnionType extends AbstractType { + public static class YBeanUnionType extends AbstractType { private final String name; private List types; @@ -424,10 +454,13 @@ public class YTypeFactory { public YBeanUnionType(String name, YBeanType... types) { this.name = name; - this.types = new ArrayList<>(Arrays.asList(types)); + this.types = new ArrayList<>(); + for (YBeanType t : types) { + addUnionMember(t); + } } - public synchronized void addUnionMember(YBeanType type) { + private void addUnionMember(YBeanType type) { types.add(type); } diff --git a/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/ConcourseModel.java b/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/ConcourseModel.java index 4128b2b7b..1a5731099 100644 --- a/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/ConcourseModel.java +++ b/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/ConcourseModel.java @@ -122,7 +122,15 @@ public class ConcourseModel { return null; } - private YamlFileAST getAst(IDocument doc) throws Exception { + public YamlFileAST getSafeAst(IDocument doc) { + try { + return getAst(doc); + } catch (Exception e) { + return null; + } + } + + public YamlFileAST getAst(IDocument doc) throws Exception { return getAstProvider(true).getAST(doc); } diff --git a/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java b/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java index b079d81e5..76822796d 100644 --- a/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java +++ b/vscode-extensions/vscode-concourse/src/main/java/org/springframework/ide/vscode/concourse/PipelineYmlSchema.java @@ -10,8 +10,14 @@ *******************************************************************************/ package org.springframework.ide.vscode.concourse; +import java.util.Set; + import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.Renderables; +import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; +import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; +import org.springframework.ide.vscode.commons.yaml.path.YamlPath; +import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment; import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext; import org.springframework.ide.vscode.commons.yaml.schema.YType; import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory; @@ -153,18 +159,39 @@ public class PipelineYmlSchema implements YamlSchema { prop(doStep, "do", f.yseq(step)); prop(tryStep, "try", step); - // shared properties applicable for any type of Step: - prop(step, "on_success", step); - prop(step, "on_failure", step); - prop(step, "ensure", step); - prop(step, "attempts", t_strictly_pos_integer); - prop(step, "tags", t_strings); - prop(step, "timeout", t_duration); + // shared properties applicable for any subtype of Step: + for (YBeanType subStep : stepTypes) { + prop(step, subStep, "on_success", step); + prop(step, subStep, "on_failure", step); + prop(step, subStep, "ensure", step); + prop(step, subStep, "attempts", t_strictly_pos_integer); + prop(step, subStep, "tags", t_strings); + prop(step, subStep, "timeout", t_duration); + } + + YType gitResourceSource = t_any; + + YType resourceSource = f.contextAware("ResourceSource", (dc) -> { + YamlPath path = dc.getPath(); + if (path!=null) { + YamlFileAST root = models.getSafeAst(dc.getDocument()); + if (root!=null) { + String typeTag = NodeUtil.asScalar(path.dropLast().append(YamlPathSegment.valueAt("type")).traverseToNode(root)); + switch (typeTag) { + case "git": + return gitResourceSource; + default: + break; + } + } + } + return t_any; + }); YBeanType resource = f.ybean("Resource"); prop(resource, "name", resourceNameDef); prop(resource, "type", t_resource_type_name); - prop(resource, "source", t_any); + prop(resource, "source", resourceSource); prop(resource, "check_every", t_duration); YBeanType job = f.ybean("Job"); @@ -194,8 +221,12 @@ public class PipelineYmlSchema implements YamlSchema { } + private void prop(AbstractType superType, AbstractType bean, String name, YType type) { + bean.addProperty(name, type, descriptionFor(superType, name)); + } + private void prop(AbstractType bean, String name, YType type) { - bean.addProperty(name, type, descriptionFor(bean, name)); + prop(bean, bean, name, type); } private Renderable descriptionFor(YType owner, String propName) { diff --git a/vscode-extensions/vscode-concourse/src/test/java/org/springframework/ide/vscode/concourse/PipelineYamlEditorTest.java b/vscode-extensions/vscode-concourse/src/test/java/org/springframework/ide/vscode/concourse/PipelineYamlEditorTest.java index 2f4124c2f..8c5a24b6a 100644 --- a/vscode-extensions/vscode-concourse/src/test/java/org/springframework/ide/vscode/concourse/PipelineYamlEditorTest.java +++ b/vscode-extensions/vscode-concourse/src/test/java/org/springframework/ide/vscode/concourse/PipelineYamlEditorTest.java @@ -638,6 +638,23 @@ public class PipelineYamlEditorTest { "not-a-resource|does not exist" ); } + + @Test + public void reconcileGitResource() throws Exception { + Editor editor = harness.newEditor( + "resources:\n" + + "- name: sts4-out\n" + + " type: git\n" + + " source:\n" + + " uri: git@github.com:spring-projects/sts4.git\n" + + " bogus: bad\n" + + " branch: {{branch}}\n" + + " private_key: {{rsa_id}}\n" + ); + editor.assertProblems( + "bogus|Unknown property" + ); + } @Test public void contentAssistJobNames() throws Exception {