Concourse: ca and reconcile 'Job Names' in 'passed' attribute

This commit is contained in:
Kris De Volder
2016-12-21 18:28:06 -08:00
parent 65451b0ff2
commit 9fd2026b7e
3 changed files with 100 additions and 10 deletions

View File

@@ -13,7 +13,9 @@ 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.Collection;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
@@ -42,9 +44,15 @@ public class ConcourseModel {
anyChild(),
valueAt("name")
);
private static final YamlPath JOB_NAMES_PATH = new YamlPath(
valueAt("jobs"),
anyChild(),
valueAt("name")
);
private final YamlParser parser;
private StaleFallbackCache<String, YamlFileAST> asts = new StaleFallbackCache<>();
private final StaleFallbackCache<String, YamlFileAST> asts = new StaleFallbackCache<>();
public ConcourseModel(SimpleTextDocumentService documents) {
Yaml yaml = new Yaml();
@@ -69,17 +77,41 @@ public class ConcourseModel {
* can not be parsed).
*/
public Set<String> getResourceNames(IDocument doc) {
return getStringsFromAst(doc, RESOURCE_NAMES_PATH);
}
/**
* Returns the job 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> getJobNames(IDocument doc) {
return getStringsFromAst(doc, JOB_NAMES_PATH);
}
private Set<String> getStringsFromAst(IDocument doc, YamlPath path) {
return getFromAst(doc, (ast) -> {
Node root = ast.get(0);
return path
.traverseAmbiguously(root)
.map(NodeUtil::asScalar)
.filter((string) -> string!=null)
.collect(Collectors.toSet());
});
}
private <T> T getFromAst(IDocument doc, Function<YamlFileAST, T> getResourceNames) {
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());
return getResourceNames.apply(ast);
}
}
} catch (YAMLException e) {
@@ -106,4 +138,5 @@ public class ConcourseModel {
};
}
}

View File

@@ -89,7 +89,7 @@ public class PipelineYmlSchema implements YamlSchema {
// The vagrant-cloud r
);
YType resourceName = f.yenum("ResourceName",
YType resourceName = f.yenum("Resource Name",
(parseString, validValues) -> {
return "The '"+parseString+"' resource does not exist. Existing resources: "+validValues;
},
@@ -98,17 +98,26 @@ public class PipelineYmlSchema implements YamlSchema {
}
);
YType jobName = f.yenum("Job Name",
(parseString, validValues) -> {
return "The '"+parseString+"' resource does not exist. Existing resources: "+validValues;
},
(DynamicSchemaContext dc) -> {
return models.getJobNames(dc.getDocument());
}
);
YBeanType getStep = f.ybean("GetStep");
prop(getStep, "get", resourceName);
prop(getStep, "resource", t_string);
prop(getStep, "version", t_version);
prop(getStep, "passed", t_strings);
prop(getStep, "passed", f.yseq(jobName));
prop(getStep, "params", t_params);
prop(getStep, "trigger", t_boolean);
YBeanType putStep = f.ybean("PutStep");
prop(putStep, "put", resourceName);
prop(putStep, "resource", t_string);
prop(putStep, "resource", jobName);
prop(putStep, "params", t_params);
prop(putStep, "get_params", t_params);

View File

@@ -511,6 +511,54 @@ public class PipelineYamlEditorTest {
"type|Duplicate key"
);
}
@Test
public void reconcileJobNames() throws Exception {
Editor editor = harness.newEditor(
"resources:\n" +
"- name: git-repo\n" +
"- name: build-artefact\n" +
"jobs:\n" +
"- name: build\n" +
" plan:\n" +
" - get: git-repo\n" +
" - task: run-build\n" +
" - put: build-artefact\n" +
"- name: test\n" +
" plan:\n" +
" - get: git-repo\n" +
" passed:\n" +
" - not-a-job\n" +
" - build\n"
);
editor.assertProblems("not-a-job|does not exist");
}
@Test
public void contentAssistJobNames() throws Exception {
assertContextualCompletions(
"resources:\n" +
"- name: git-repo\n" +
"- name: build-artefact\n" +
"jobs:\n" +
"- name: build\n" +
" plan:\n" +
" - get: git-repo\n" +
" - task: run-build\n" +
" - put: build-artefact\n" +
"- name: test\n" +
" plan:\n" +
" - get: git-repo\n" +
" passed:\n" +
" - <*>\n"
, ///////////////////////////
"<*>"
, // =>
"build<*>",
"test<*>"
);
}
//////////////////////////////////////////////////////////////////////////////