Concourse: reconcile checking for non-existent resources
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
package org.springframework.ide.vscode.commons.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
@@ -23,7 +22,8 @@ import com.google.common.collect.ImmutableSet;
|
||||
public class EnumValueParser implements ValueParser {
|
||||
|
||||
private String typeName;
|
||||
private Set<String> values;
|
||||
private Collection<String> values;
|
||||
|
||||
|
||||
public EnumValueParser(String typeName, String... values) {
|
||||
this(typeName, ImmutableSet.copyOf(values));
|
||||
@@ -31,15 +31,21 @@ public class EnumValueParser implements ValueParser {
|
||||
|
||||
public EnumValueParser(String typeName, Collection<String> values) {
|
||||
this.typeName = typeName;
|
||||
this.values = ImmutableSet.copyOf(values);
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Object parse(String str) {
|
||||
if (values.contains(str)) {
|
||||
Collection<String> values = this.values;
|
||||
//If values is not known (null) then just assume the str is acceptable.
|
||||
if (values==null || values.contains(str)) {
|
||||
return str;
|
||||
} else {
|
||||
throw new IllegalArgumentException("'"+str+"' is not valid for Enum '"+typeName+"'. Valid values are: "+values);
|
||||
throw new IllegalArgumentException(createErrorMessage(str, values));
|
||||
}
|
||||
}
|
||||
|
||||
protected String createErrorMessage(String parseString, Collection<String> values2) {
|
||||
return "'"+parseString+"' is not valid for Enum '"+typeName+"'. Valid values are: "+values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.ide.vscode.commons.util;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* Utility methods to convert exceptions into other types of exceptions, status
|
||||
@@ -65,4 +66,14 @@ public class ExceptionUtil {
|
||||
return dump.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert throwables into exception try not to wrap if not needing to.
|
||||
*/
|
||||
public static Exception exception(Throwable cause) {
|
||||
if (cause instanceof Exception) {
|
||||
return (Exception)cause;
|
||||
}
|
||||
return new ExecutionException(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.springframework.ide.vscode.commons.yaml.ast;
|
||||
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.NodeId;
|
||||
import org.yaml.snakeyaml.nodes.ScalarNode;
|
||||
import org.yaml.snakeyaml.nodes.SequenceNode;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
@@ -47,4 +49,18 @@ public class NodeUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MappingNode asMapping(Node node) {
|
||||
if (node!=null && node.getNodeId()==NodeId.mapping) {
|
||||
return (MappingNode) node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SequenceNode asSequence(Node node) {
|
||||
if (node!=null && node.getNodeId()==NodeId.sequence) {
|
||||
return (SequenceNode) node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.List;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.IRequestor;
|
||||
import org.springframework.ide.vscode.commons.util.RememberLast;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
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.TupleKeyRef;
|
||||
@@ -25,9 +26,11 @@ import org.yaml.snakeyaml.nodes.SequenceNode;
|
||||
public class YamlFileAST {
|
||||
|
||||
private static final List<NodeRef<?>> NO_CHILDREN = Collections.emptyList();
|
||||
private List<Node> nodes;
|
||||
private final List<Node> nodes;
|
||||
private final IDocument doc;
|
||||
|
||||
public YamlFileAST(Iterable<Node> iter) {
|
||||
public YamlFileAST(IDocument doc, Iterable<Node> iter) {
|
||||
this.doc = doc;
|
||||
nodes = new ArrayList<Node>();
|
||||
for (Node node : iter) {
|
||||
nodes.add(node);
|
||||
@@ -141,5 +144,9 @@ public class YamlFileAST {
|
||||
nodes.set(index, value);
|
||||
}
|
||||
|
||||
public IDocument getDocument() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class YamlParser implements YamlASTProvider {
|
||||
public YamlFileAST getAST(IDocument doc) throws Exception {
|
||||
CharSequenceReader reader = new CharSequenceReader();
|
||||
reader.setInput(doc.get());
|
||||
return new YamlFileAST(yaml.composeAll(reader));
|
||||
return new YamlFileAST(doc, yaml.composeAll(reader));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.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;
|
||||
|
||||
/**
|
||||
* Pointer to a specific {@link Node} in Snake yaml parse tree. Supports navigation
|
||||
* using {@link YamlPath}s, including support for 'ambiguous' steps like
|
||||
* {@link YamlPathSegment}.anyChild()
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class NodeCursor implements YamlNavigable<NodeCursor> {
|
||||
|
||||
private final Node currentNode;
|
||||
|
||||
public NodeCursor(Node node) {
|
||||
Assert.isNotNull(node);
|
||||
this.currentNode = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<NodeCursor> traverseAmbiguously(YamlPathSegment s) {
|
||||
switch (s.getType()) {
|
||||
case KEY_AT_KEY: {
|
||||
String key = s.toPropString();
|
||||
MappingNode mappingNode = NodeUtil.asMapping(getNode());
|
||||
if (mappingNode!=null) {
|
||||
return mappingNode.getValue().stream()
|
||||
.filter((c) -> key.equals(NodeUtil.asScalar(c.getKeyNode())))
|
||||
.map((c) -> new NodeCursor(c.getKeyNode()));
|
||||
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
case ANY_CHILD: {
|
||||
MappingNode mappingNode = NodeUtil.asMapping(getNode());
|
||||
if (mappingNode!=null) {
|
||||
return mappingNode.getValue().stream()
|
||||
.map((c) -> new NodeCursor(c.getValueNode()));
|
||||
}
|
||||
SequenceNode sequenceNode = NodeUtil.asSequence(getNode());
|
||||
if (sequenceNode!=null) {
|
||||
return sequenceNode.getValue().stream().map(NodeCursor::new);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
case VAL_AT_INDEX: {
|
||||
SequenceNode seq = NodeUtil.asSequence(getNode());
|
||||
int index = s.toIndex();
|
||||
int size = seq.getValue().size();
|
||||
if (index<size && index >= 0) {
|
||||
return Stream.of(new NodeCursor(seq.getValue().get(index)));
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
case VAL_AT_KEY: {
|
||||
MappingNode mappingNode = NodeUtil.asMapping(getNode());
|
||||
if (mappingNode!=null) {
|
||||
String key = s.toPropString();
|
||||
return mappingNode.getValue().stream()
|
||||
.filter((c) -> key.equals(NodeUtil.asScalar(c.getKeyNode())))
|
||||
.map((c) -> new NodeCursor(c.getValueNode()));
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
default:
|
||||
Assert.isLegal(false, "Bug? Missing switch case?");
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public Node getNode() {
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ 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;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.YamlPathSegmentType;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
@@ -125,6 +126,15 @@ public class YamlPath {
|
||||
return traverseAmbiguously(startNode).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public Stream<Node> traverseAmbiguously(Node startNode) {
|
||||
if (startNode!=null) {
|
||||
return traverseAmbiguously(new NodeCursor(startNode))
|
||||
.map(NodeCursor::getNode);
|
||||
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
public <T extends YamlNavigable<T>> Stream<T> traverseAmbiguously(T startNode) {
|
||||
if (startNode!=null) {
|
||||
Stream<T> result = Stream.of(startNode);
|
||||
|
||||
@@ -22,7 +22,35 @@ public abstract class YamlPathSegment {
|
||||
public static enum YamlPathSegmentType {
|
||||
VAL_AT_KEY, //Go to value associate with given key in a map.
|
||||
KEY_AT_KEY, //Go to the key node associated with a given key in a map.
|
||||
VAL_AT_INDEX //Go to value associate with given index in a sequence
|
||||
VAL_AT_INDEX, //Go to value associate with given index in a sequence
|
||||
ANY_CHILD // Go to any child (assumes you are using ambiguous traversal method, otherwise this is probably not very useful)
|
||||
}
|
||||
|
||||
public static class AnyChild extends YamlPathSegment {
|
||||
|
||||
private static AnyChild INSTANCE = new AnyChild();
|
||||
|
||||
private AnyChild() {}
|
||||
|
||||
@Override
|
||||
public String toNavString() {
|
||||
return ".*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPropString() {
|
||||
return "*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer toIndex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlPathSegmentType getType() {
|
||||
return YamlPathSegmentType.ANY_CHILD;
|
||||
};
|
||||
}
|
||||
|
||||
public static class AtIndex extends YamlPathSegment {
|
||||
@@ -133,7 +161,7 @@ public abstract class YamlPathSegment {
|
||||
}
|
||||
}
|
||||
|
||||
private static class KeyAtKey extends ValAtKey {
|
||||
public static class KeyAtKey extends ValAtKey {
|
||||
|
||||
public KeyAtKey(String key) {
|
||||
super(key);
|
||||
@@ -144,6 +172,7 @@ public abstract class YamlPathSegment {
|
||||
return YamlPathSegmentType.KEY_AT_KEY;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -165,5 +194,9 @@ public abstract class YamlPathSegment {
|
||||
public static YamlPathSegment keyAt(String key) {
|
||||
return new KeyAtKey(key);
|
||||
}
|
||||
|
||||
public static YamlPathSegment anyChild() {
|
||||
return AnyChild.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemC
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
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.schema.ASTDynamicSchemaContext;
|
||||
@@ -39,23 +40,23 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler {
|
||||
List<Node> nodes = ast.getNodes();
|
||||
if (nodes!=null && !nodes.isEmpty()) {
|
||||
for (Node node : nodes) {
|
||||
reconcile(node, schema.getTopLevelType());
|
||||
reconcile(ast.getDocument(), node, schema.getTopLevelType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reconcile(Node node, YType type) {
|
||||
private void reconcile(IDocument doc, Node node, YType type) {
|
||||
if (type!=null) {
|
||||
DynamicSchemaContext schemaContext = new ASTDynamicSchemaContext(doc, node);
|
||||
switch (node.getNodeId()) {
|
||||
case mapping:
|
||||
MappingNode map = (MappingNode) node;
|
||||
if (typeUtil.isMap(type)) {
|
||||
for (NodeTuple entry : map.getValue()) {
|
||||
reconcile(entry.getKeyNode(), typeUtil.getKeyType(type));
|
||||
reconcile(entry.getValueNode(), typeUtil.getDomainType(type));
|
||||
reconcile(doc, entry.getKeyNode(), typeUtil.getKeyType(type));
|
||||
reconcile(doc, entry.getValueNode(), typeUtil.getDomainType(type));
|
||||
}
|
||||
} else if (typeUtil.isBean(type)) {
|
||||
DynamicSchemaContext schemaContext = new ASTDynamicSchemaContext(map);
|
||||
Map<String, YTypedProperty> beanProperties = typeUtil.getPropertiesMap(type, schemaContext);
|
||||
for (NodeTuple entry : map.getValue()) {
|
||||
Node keyNode = entry.getKeyNode();
|
||||
@@ -68,7 +69,7 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler {
|
||||
type = typeUtil.inferMoreSpecificType(type, schemaContext);
|
||||
unknownBeanProperty(keyNode, type, key);
|
||||
} else {
|
||||
reconcile(entry.getValueNode(), prop.getType());
|
||||
reconcile(doc, entry.getValueNode(), prop.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +81,7 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler {
|
||||
SequenceNode seq = (SequenceNode) node;
|
||||
if (typeUtil.isSequencable(type)) {
|
||||
for (Node el : seq.getValue()) {
|
||||
reconcile(el, typeUtil.getDomainType(type));
|
||||
reconcile(doc, el, typeUtil.getDomainType(type));
|
||||
}
|
||||
} else {
|
||||
expectTypeButFoundSequence(type, node);
|
||||
@@ -88,7 +89,7 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler {
|
||||
break;
|
||||
case scalar:
|
||||
if (typeUtil.isAtomic(type)) {
|
||||
ValueParser parser = typeUtil.getValueParser(type);
|
||||
ValueParser parser = typeUtil.getValueParser(type, schemaContext);
|
||||
if (parser!=null) {
|
||||
try {
|
||||
parser.parse(NodeUtil.asScalar(node));
|
||||
@@ -108,11 +109,10 @@ public class SchemaBasedYamlASTReconciler implements YamlASTReconciler {
|
||||
}
|
||||
|
||||
private void valueParseError(YType type, Node node, String parseErrorMsg) {
|
||||
String msg= "Couldn't parse as '"+describe(type)+"'";
|
||||
if (StringUtil.hasText(parseErrorMsg)) {
|
||||
msg += " ("+parseErrorMsg+")";
|
||||
if (!StringUtil.hasText(parseErrorMsg)) {
|
||||
parseErrorMsg= "Couldn't parse as '"+describe(type)+"'";
|
||||
}
|
||||
problem(node, msg);
|
||||
problem(node, parseErrorMsg);
|
||||
}
|
||||
|
||||
private void unknownBeanProperty(Node keyNode, YType type, String name) {
|
||||
|
||||
@@ -13,8 +13,10 @@ package org.springframework.ide.vscode.commons.yaml.schema;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.NodeTuple;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -28,9 +30,19 @@ import com.google.common.collect.ImmutableSet;
|
||||
public class ASTDynamicSchemaContext extends CachingSchemaContext {
|
||||
|
||||
private MappingNode mapNode;
|
||||
private IDocument doc;
|
||||
|
||||
public ASTDynamicSchemaContext(MappingNode map) {
|
||||
this.mapNode = map;
|
||||
public ASTDynamicSchemaContext(IDocument doc, Node node) {
|
||||
this.doc = doc;
|
||||
this.mapNode = as(MappingNode.class, node);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T as(Class<T> klass, Node node) {
|
||||
if (node!=null && klass.isInstance(node)) {
|
||||
return (T) node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,4 +59,9 @@ public class ASTDynamicSchemaContext extends CachingSchemaContext {
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDocument getDocument() {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ package org.springframework.ide.vscode.commons.yaml.schema;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
@@ -31,6 +33,11 @@ public interface DynamicSchemaContext {
|
||||
public Set<String> getDefinedProperties() {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDocument getDocument() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -45,6 +52,12 @@ public interface DynamicSchemaContext {
|
||||
* properties are defined in the surrounding object.
|
||||
*/
|
||||
Set<String> getDefinedProperties();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the IDocument the current context is in. This allows for some 'schemas' to have
|
||||
* arbitrarily complex analysis of anyhting in the IDocument or even documents related
|
||||
* to it based on its uri.
|
||||
*/
|
||||
IDocument getDocument();
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,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.structure.YamlStructureParser.SChildBearingNode;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SKeyNode;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode;
|
||||
@@ -55,5 +56,10 @@ public class SNodeDynamicSchemaContext extends CachingSchemaContext {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDocument getDocument() {
|
||||
return contextNode.getDocument();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.schema;
|
||||
|
||||
/**
|
||||
* Interface that can be implemented by something producing another
|
||||
* component (of some type `T`) where the returned component needs to
|
||||
* configured with a {@link DynamicSchemaContext}.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public interface SchemaContextAware<T> {
|
||||
T withContext(DynamicSchemaContext dc);
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
@@ -120,8 +122,8 @@ public class YTypeFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueParser getValueParser(YType type) {
|
||||
return ((AbstractType)type).getParser();
|
||||
public ValueParser getValueParser(YType type, DynamicSchemaContext dc) {
|
||||
return ((AbstractType)type).getParser(dc);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,7 +139,7 @@ public class YTypeFactory {
|
||||
*/
|
||||
public static abstract class AbstractType implements YType {
|
||||
|
||||
private ValueParser parser;
|
||||
private SchemaContextAware<ValueParser> parser;
|
||||
private List<YTypedProperty> propertyList = new ArrayList<>();
|
||||
private final List<YValueHint> hints = new ArrayList<>();
|
||||
private Map<String, YTypedProperty> cachedPropertyMap;
|
||||
@@ -246,11 +248,15 @@ public class YTypeFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public void parseWith(ValueParser parser) {
|
||||
public void parseWith(SchemaContextAware<ValueParser> parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
public ValueParser getParser() {
|
||||
return parser;
|
||||
|
||||
public void parseWith(ValueParser parser) {
|
||||
parseWith((DynamicSchemaContext dc) -> parser);
|
||||
}
|
||||
private ValueParser getParser(DynamicSchemaContext dc) {
|
||||
return parser == null ? null : parser.withContext(dc);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -577,6 +583,28 @@ public class YTypeFactory {
|
||||
return new YTypedPropertyImpl(name, type);
|
||||
}
|
||||
|
||||
public YAtomicType yenum(String name, BiFunction<String, Collection<String>, String> errorMessageFormatter, SchemaContextAware<Collection<String>> values) {
|
||||
YAtomicType t = yatomic(name);
|
||||
t.addHintProvider(() -> {
|
||||
Collection<String> strings = values.withContext(DynamicSchemaContext.NULL); //TODO: make this really context aware!
|
||||
return strings==null
|
||||
? null
|
||||
: strings.stream()
|
||||
.map((s) -> new BasicYValueHint(s))
|
||||
.collect(Collectors.toSet());
|
||||
});
|
||||
t.parseWith((DynamicSchemaContext dc) -> {
|
||||
EnumValueParser enumParser = new EnumValueParser(name, values.withContext(dc)) {
|
||||
@Override
|
||||
protected String createErrorMessage(String parseString, Collection<String> values) {
|
||||
return errorMessageFormatter.apply(parseString, values);
|
||||
}
|
||||
};
|
||||
return enumParser;
|
||||
});
|
||||
return t;
|
||||
}
|
||||
|
||||
public YAtomicType yenum(String name, String... values) {
|
||||
YAtomicType t = yatomic(name);
|
||||
t.addHints(values);
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface YTypeUtil {
|
||||
YValueHint[] getHintValues(YType yType);
|
||||
String niceTypeName(YType type);
|
||||
YType getKeyType(YType type);
|
||||
ValueParser getValueParser(YType type);
|
||||
ValueParser getValueParser(YType type, DynamicSchemaContext dc);
|
||||
|
||||
//TODO: only one of these two should be enough?
|
||||
List<YTypedProperty> getProperties(YType type, DynamicSchemaContext dc);
|
||||
@@ -44,5 +44,5 @@ public interface YTypeUtil {
|
||||
* present in the context to narrow the type, then the type itself
|
||||
* should be returned.
|
||||
*/
|
||||
YType inferMoreSpecificType(YType type, DynamicSchemaContext schemaContext);
|
||||
YType inferMoreSpecificType(YType type, DynamicSchemaContext dc);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.KeyAliases;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlNavigable;
|
||||
@@ -257,6 +258,10 @@ public class YamlStructureParser {
|
||||
return getStart()<=offset && offset<=getTreeEnd();
|
||||
}
|
||||
|
||||
public IDocument getDocument() {
|
||||
return doc.getDocument();
|
||||
}
|
||||
|
||||
public String getText() throws Exception {
|
||||
return doc.textBetween(start, end);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.concourse;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionOptions;
|
||||
@@ -25,22 +35,20 @@ import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
private Yaml yaml = new Yaml();
|
||||
private YamlSchema schema = new PipelineYmlSchema();
|
||||
|
||||
|
||||
public ConcourseLanguageServer() {
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
|
||||
YamlASTProvider parser = new YamlParser(yaml);
|
||||
|
||||
ConcourseModel models = new ConcourseModel(documents);
|
||||
YamlASTProvider currentAsts = models.getAstProvider(false);
|
||||
|
||||
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
|
||||
YamlSchema schema = new PipelineYmlSchema(models);
|
||||
YamlAssistContextProvider contextProvider = new SchemaBasedYamlAssistContextProvider(schema);
|
||||
YamlCompletionEngine yamlCompletionEngine = new YamlCompletionEngine(structureProvider, contextProvider);
|
||||
VscodeCompletionEngine completionEngine = new VscodeCompletionEngineAdapter(this, yamlCompletionEngine);
|
||||
HoverInfoProvider infoProvider = new YamlHoverInfoProvider(parser, structureProvider, contextProvider);
|
||||
HoverInfoProvider infoProvider = new YamlHoverInfoProvider(currentAsts, structureProvider, contextProvider);
|
||||
VscodeHoverEngine hoverEngine = new VscodeHoverEngineAdapter(this, infoProvider);
|
||||
IReconcileEngine engine = new YamlSchemaBasedReconcileEngine(parser, schema);
|
||||
IReconcileEngine engine = new YamlSchemaBasedReconcileEngine(currentAsts, schema);
|
||||
|
||||
// SimpleWorkspaceService workspace = getWorkspaceService();
|
||||
documents.onDidChangeContent(params -> {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.concourse;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.anyChild;
|
||||
import static org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.valueAt;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.TextDocumentContentChange;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
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.YamlASTProvider;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.concourse.util.StaleFallbackCache;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
* ConcourseModels is responsible for extracting various bits of information
|
||||
* out of .yml documents and caching them for use by various tools (reconcile engine
|
||||
* and completion engine).
|
||||
*/
|
||||
public class ConcourseModel {
|
||||
|
||||
private static final YamlPath RESOURCE_NAMES_PATH = new YamlPath(
|
||||
valueAt("resources"),
|
||||
anyChild(),
|
||||
valueAt("name")
|
||||
);
|
||||
|
||||
private final YamlParser parser;
|
||||
private StaleFallbackCache<String, YamlFileAST> asts = new StaleFallbackCache<>();
|
||||
|
||||
public ConcourseModel(SimpleTextDocumentService documents) {
|
||||
Yaml yaml = new Yaml();
|
||||
this.parser = new YamlParser(yaml);
|
||||
documents.onDidChangeContent(this::documentChanged);
|
||||
}
|
||||
|
||||
private void documentChanged(TextDocumentContentChange changeEvent) {
|
||||
String uri = changeEvent.getDocument().getUri();
|
||||
if (uri!=null) {
|
||||
asts.invalidate(uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource names that are defined by given IDocument. If the contents
|
||||
* of IDocument is not currently parseable then this may return stale information
|
||||
* retained from a previous successful parse.
|
||||
* <p>
|
||||
* It may also return null if its not currently possible to obtain the list of resource
|
||||
* names (e.g. because there hasn't been a successful parse yet and current document contents
|
||||
* can not be parsed).
|
||||
*/
|
||||
public Set<String> getResourceNames(IDocument doc) {
|
||||
try {
|
||||
if (doc!=null) {
|
||||
String uri = doc.getUri();
|
||||
if (uri!=null) {
|
||||
YamlFileAST ast = getAst(doc);
|
||||
Node root = ast.get(0);
|
||||
return RESOURCE_NAMES_PATH
|
||||
.traverseAmbiguously(root)
|
||||
.map(NodeUtil::asScalar)
|
||||
.filter((string) -> string!=null)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
} catch (YAMLException e) {
|
||||
// ignore: garbage in the doc. Can't compute stuff and that's to be expected.
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private YamlFileAST getAst(IDocument doc) throws Exception {
|
||||
return getAstProvider(true).getAST(doc);
|
||||
}
|
||||
|
||||
public YamlASTProvider getAstProvider(boolean allowStaleAsts) {
|
||||
return (IDocument doc) -> {
|
||||
String uri = doc.getUri();
|
||||
if (uri!=null) {
|
||||
return asts.get(uri, allowStaleAsts, () -> {
|
||||
return parser.getAST(doc);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.concourse;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
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;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.AbstractType;
|
||||
@@ -31,7 +32,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
|
||||
private final YTypeFactory f = new YTypeFactory();
|
||||
|
||||
public PipelineYmlSchema() {
|
||||
public PipelineYmlSchema(ConcourseModel models) {
|
||||
TYPE_UTIL = f.TYPE_UTIL;
|
||||
|
||||
// define schema types
|
||||
@@ -81,9 +82,18 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
//
|
||||
// The vagrant-cloud r
|
||||
);
|
||||
|
||||
YType resourceName = f.yenum("ResourceName",
|
||||
(parseString, validValues) -> {
|
||||
return "The '"+parseString+"' resource does not exist. Existing resources: "+validValues;
|
||||
},
|
||||
(DynamicSchemaContext dc) -> {
|
||||
return models.getResourceNames(dc.getDocument());
|
||||
}
|
||||
);
|
||||
|
||||
YBeanType getStep = f.ybean("GetStep");
|
||||
prop(getStep, "get", t_ne_string);
|
||||
prop(getStep, "get", resourceName);
|
||||
prop(getStep, "resource", t_string);
|
||||
prop(getStep, "version", t_version);
|
||||
prop(getStep, "passed", t_strings);
|
||||
@@ -91,7 +101,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
prop(getStep, "trigger", t_boolean);
|
||||
|
||||
YBeanType putStep = f.ybean("PutStep");
|
||||
prop(putStep, "put", t_ne_string);
|
||||
prop(putStep, "put", resourceName);
|
||||
prop(putStep, "resource", t_string);
|
||||
prop(putStep, "params", t_params);
|
||||
prop(putStep, "get_params", t_params);
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.concourse.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
/**
|
||||
* Simple cache implementation that falls back on 'stale' cache entry if
|
||||
* a new entry can not be computed. The api is loosely modeled after
|
||||
* guava's Cache interface (but only the subset we use is implemented to reduce the
|
||||
* complexity of its implementation).
|
||||
*/
|
||||
public class StaleFallbackCache<K, V>{
|
||||
|
||||
Map<K, V> staleEntries = new HashMap<>();
|
||||
Cache<K, CompletableFuture<V>> validEntries = CacheBuilder.newBuilder().build();
|
||||
|
||||
|
||||
public synchronized V get(K key, boolean allowStaleEntries, Callable<? extends V> valueLoader) throws Exception {
|
||||
CompletableFuture<V> valid = validEntries.get(key, () -> load(valueLoader));
|
||||
if (!allowStaleEntries) {
|
||||
return future_get(valid);
|
||||
} else {
|
||||
if (valid.isCompletedExceptionally()) {
|
||||
V staleValue = staleEntries.get(key);
|
||||
if (staleValue!=null) {
|
||||
return staleValue;
|
||||
}
|
||||
}
|
||||
return future_get(valid);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void invalidate(K key) {
|
||||
CompletableFuture<V> staleEntry = validEntries.getIfPresent(key);
|
||||
if (staleEntry!=null) {
|
||||
validEntries.invalidate(key);
|
||||
try {
|
||||
staleEntries.put(key, future_get(staleEntry));
|
||||
} catch (Exception e) {
|
||||
//ignore. Don't overwrite stale entry if current entry represents an error.
|
||||
// We only keep 'good quality' stale entries not failed attempts to compute a value.
|
||||
// as it is kind of the point to fall back on a 'good' old entry when the current
|
||||
// entry is unavailable because of a problem (e.g. problems parsing the AST).
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private V future_get(CompletableFuture<V> f) throws Exception {
|
||||
try {
|
||||
return f.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (ExecutionException e) {
|
||||
throw ExceptionUtil.exception(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<V> load(Callable<? extends V> valueLoader) {
|
||||
CompletableFuture<V> future = new CompletableFuture<V>();
|
||||
try {
|
||||
V value = valueLoader.call();
|
||||
Assert.isNotNull(value);
|
||||
future.complete(value);
|
||||
} catch (Throwable e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.manifest.yaml;
|
||||
package org.springframework.ide.vscode.concourse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.manifest.yaml;
|
||||
package org.springframework.ide.vscode.concourse;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.assertContains;
|
||||
|
||||
@@ -259,12 +259,15 @@ public class PipelineYamlEditorTest {
|
||||
);
|
||||
editor.assertProblems(
|
||||
"boohoo|boolean",
|
||||
"-1|Positive Integer",
|
||||
"-1|must be positive",
|
||||
"git|resource does not exist",
|
||||
"yohoho|boolean"
|
||||
);
|
||||
|
||||
//check that correct values are indeed accepted
|
||||
editor = harness.newEditor(
|
||||
"resources:\n" +
|
||||
"- name: git\n" +
|
||||
"jobs:\n" +
|
||||
"- name: foo\n" +
|
||||
" serial: true\n" +
|
||||
@@ -379,6 +382,33 @@ public class PipelineYamlEditorTest {
|
||||
editor.assertHoverContains("jobs", "At a high level, a job describes some actions to perform");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reconcileResourceReferences() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"resources:\n" +
|
||||
"- name: sts4\n" +
|
||||
" type: git\n" +
|
||||
" source:\n" +
|
||||
" repository: https://github.com/kdvolder/somestuff\n" +
|
||||
"jobs:\n" +
|
||||
"- name: job1\n" +
|
||||
" plan:\n" +
|
||||
" - get: sts4\n" +
|
||||
" - get: bogus-get\n" +
|
||||
" - put: bogus-put\n"
|
||||
);
|
||||
editor.assertProblems(
|
||||
"bogus-get|resource does not exist",
|
||||
"bogus-put|resource does not exist"
|
||||
);
|
||||
|
||||
editor.assertProblems(
|
||||
"bogus-get|[sts4]",
|
||||
"bogus-put|[sts4]"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void assertContextualCompletions(String conText, String textBefore, String... textAfter) throws Exception {
|
||||
@@ -1,129 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2016 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.manifest.yaml;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.concourse.PipelineYmlSchema;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class PipelineYmlSchemaTest {
|
||||
|
||||
// @Test
|
||||
// public void shouldMakeSomeTests() {
|
||||
// fail("We should make some tests for this");
|
||||
// }
|
||||
//
|
||||
// private static final String[] NESTED_PROP_NAMES = {
|
||||
//// "applications",
|
||||
// "buildpack",
|
||||
// "command",
|
||||
// "disk_quota",
|
||||
// "domain",
|
||||
// "domains",
|
||||
// "env",
|
||||
// "health-check-type",
|
||||
// "host",
|
||||
// "hosts",
|
||||
//// "inherit",
|
||||
// "instances",
|
||||
// "memory",
|
||||
// "name",
|
||||
// "no-hostname",
|
||||
// "no-route",
|
||||
// "path",
|
||||
// "random-route",
|
||||
// "services",
|
||||
// "stack",
|
||||
// "timeout"
|
||||
// };
|
||||
//
|
||||
private static final String[] TOPLEVEL_PROP_NAMES = {
|
||||
"resources",
|
||||
"jobs",
|
||||
"resource-types"
|
||||
//groups
|
||||
};
|
||||
|
||||
PipelineYmlSchema schema = new PipelineYmlSchema();
|
||||
//
|
||||
// @Test
|
||||
// public void toplevelProperties() throws Exception {
|
||||
// assertPropNames(schema.getTopLevelType().getProperties(DynamicSchemaContext.NULL), TOPLEVEL_PROP_NAMES);
|
||||
// assertPropNames(schema.getTopLevelType().getPropertiesMap(DynamicSchemaContext.NULL), TOPLEVEL_PROP_NAMES);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void nestedProperties() throws Exception {
|
||||
// assertPropNames(getNestedProps(), NESTED_PROP_NAMES);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void toplevelPropertiesHaveDescriptions() {
|
||||
// for (YTypedProperty p : schema.getTopLevelType().getProperties(DynamicSchemaContext.NULL)) {
|
||||
// if (!p.getName().equals("applications")) {
|
||||
// assertHasRealDescription(p);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void nestedPropertiesHaveDescriptions() {
|
||||
// for (YTypedProperty p : getNestedProps()) {
|
||||
// assertHasRealDescription(p);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// private void assertHasRealDescription(YTypedProperty p) {
|
||||
// {
|
||||
// String noDescriptionText = Renderables.NO_DESCRIPTION.toHtml();
|
||||
// String actual = p.getDescription().toHtml();
|
||||
// String msg = "Description missing for '"+p.getName()+"'";
|
||||
// assertTrue(msg, StringUtil.hasText(actual));
|
||||
// assertFalse(msg, noDescriptionText.equals(actual));
|
||||
// }
|
||||
// {
|
||||
// String noDescriptionText = Renderables.NO_DESCRIPTION.toMarkdown();
|
||||
// String actual = p.getDescription().toMarkdown();
|
||||
// String msg = "Description missing for '"+p.getName()+"'";
|
||||
// assertTrue(msg, StringUtil.hasText(actual));
|
||||
// assertFalse(msg, noDescriptionText.equals(actual));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private List<YTypedProperty> getNestedProps() {
|
||||
// YSeqType applications = (YSeqType) schema.getTopLevelType().getPropertiesMap().get("applications").getType();
|
||||
// YBeanType application = (YBeanType) applications.getDomainType();
|
||||
// return application.getProperties();
|
||||
// }
|
||||
//
|
||||
// private void assertPropNames(List<YTypedProperty> properties, String... expectedNames) {
|
||||
// assertEquals(ImmutableSet.copyOf(expectedNames), getNames(properties));
|
||||
// }
|
||||
//
|
||||
// private void assertPropNames(Map<String, YTypedProperty> propertiesMap, String[] toplevelPropNames) {
|
||||
// assertEquals(ImmutableSet.copyOf(toplevelPropNames), ImmutableSet.copyOf(propertiesMap.keySet()));
|
||||
// }
|
||||
//
|
||||
// private ImmutableSet<String> getNames(Iterable<YTypedProperty> properties) {
|
||||
// Builder<String> builder = ImmutableSet.builder();
|
||||
// for (YTypedProperty p : properties) {
|
||||
// builder.add(p.getName());
|
||||
// }
|
||||
// return builder.build();
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
resources:
|
||||
- name: sts4
|
||||
type: git
|
||||
source:
|
||||
repository: https://github.com/kdvolder/somestuff
|
||||
jobs:
|
||||
- name: job1
|
||||
plan:
|
||||
- get: sts4
|
||||
- get: bogus-get
|
||||
- put: bogus-put
|
||||
Reference in New Issue
Block a user