Relaxed indentation context... support for sequence context
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
set -e
|
||||
workdir=`pwd`
|
||||
|
||||
#if [ -d "maven-cache" ]; then
|
||||
if [ -d "maven-cache" ]; then
|
||||
echo "Prepopulating maven cache"
|
||||
tar xzf maven-cache/*.tar.gz -C ${HOME}
|
||||
#else
|
||||
# echo "!!!No stored maven cache found!!! "
|
||||
# echo "!!!This may slow down the build!!!"
|
||||
#fi
|
||||
else
|
||||
echo "!!!No stored maven cache found!!! "
|
||||
echo "!!!This may slow down the build!!!"
|
||||
fi
|
||||
|
||||
cd sts4/vscode-extensions
|
||||
./build-all.sh
|
||||
|
||||
@@ -22,6 +22,7 @@ public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
* A sorter suitable for sorting ScoreableProposals based on their score.
|
||||
*/
|
||||
public static final Comparator<ICompletionProposal> COMPARATOR = new Comparator<ICompletionProposal>() {
|
||||
@Override
|
||||
public int compare(ICompletionProposal p1, ICompletionProposal p2) {
|
||||
if (p1 instanceof ScoreableProposal && p2 instanceof ScoreableProposal) {
|
||||
double s1 = ((ScoreableProposal)p1).getScore();
|
||||
@@ -41,6 +42,7 @@ public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
public final double getScore() {
|
||||
return getBaseScore() - deemphasizedBy;
|
||||
}
|
||||
@Override
|
||||
public ScoreableProposal deemphasize() {
|
||||
deemphasizedBy+= DEEMP_VALUE;
|
||||
return this;
|
||||
@@ -113,4 +115,9 @@ public abstract class ScoreableProposal implements ICompletionProposal {
|
||||
// return completionOffset;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getLabel();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,6 +83,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
if (!completions.isEmpty()) {
|
||||
List<ICompletionProposal> transformed = new ArrayList<>();
|
||||
for (ICompletionProposal p : completions) {
|
||||
System.out.println(p.getLabel());
|
||||
transformed.add(indented(p));
|
||||
}
|
||||
return transformed;
|
||||
@@ -137,8 +138,8 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
}
|
||||
|
||||
private Collection<? extends ICompletionProposal> getRelaxedCompletions(int offset, YamlDocument doc, SNode preciseContextNode, SNode currentNode) throws Exception {
|
||||
if (preciseContextNode!=null) {
|
||||
SNode contextNode = getRelaxedContextNode(preciseContextNode, currentNode);
|
||||
SNode contextNode = getContextNode(doc, currentNode, offset, YamlIndentUtil.INDENT_BY);
|
||||
if (preciseContextNode!=contextNode && isRelaxable(contextNode)) {
|
||||
YamlAssistContext context = getContext(doc, contextNode);
|
||||
if (context!=null) {
|
||||
return context.getCompletions(doc, currentNode, offset);
|
||||
@@ -147,6 +148,13 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private boolean isRelaxable(SNode contextNode) throws Exception {
|
||||
return contextNode!=null && (
|
||||
isBarrenKey(contextNode) ||
|
||||
contextNode.getNodeType()==SNodeType.SEQ
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isBarrenKey(SNode node) throws Exception {
|
||||
if (node.getNodeType()==SNodeType.KEY) {
|
||||
SKeyNode keyNode = (SKeyNode) node;
|
||||
@@ -156,20 +164,6 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return false;
|
||||
}
|
||||
|
||||
private SNode getRelaxedContextNode(SNode preciseContextNode, SNode currentNode) throws Exception {
|
||||
while (currentNode!=null) {
|
||||
if (currentNode.getParent()==preciseContextNode) {
|
||||
if (isBarrenKey(currentNode)) {
|
||||
return currentNode;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
currentNode = currentNode.getParent();
|
||||
}
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
protected Collection<ICompletionProposal> getPreciseCompletions(int offset, YamlDocument doc, SNode current, SNode contextNode)
|
||||
throws Exception {
|
||||
if (contextNode!=null) {
|
||||
@@ -211,7 +205,8 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected SNode getContextNode(YamlDocument doc, SNode node, int offset) throws Exception {
|
||||
protected SNode getContextNode(YamlDocument doc, SNode node, int offset, int adjustIndent) throws Exception {
|
||||
Assert.isLegal(adjustIndent>=0); //The code doesn't handle negative indents yet.
|
||||
if (node==null) {
|
||||
return null;
|
||||
} else if (node.getNodeType()==SNodeType.KEY) {
|
||||
@@ -232,11 +227,12 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
// the correct context depends on text the user has not typed yet.(which will change the
|
||||
// indentation level of the current line. So we must use the cursorIndentation
|
||||
// rather than the structure-tree to determine the 'context' node.
|
||||
int cursorIndent = doc.getColumn(offset);
|
||||
int nodeIndent = node.getIndent();
|
||||
int cursorIndent = YamlIndentUtil.add(doc.getColumn(offset), adjustIndent);
|
||||
int nodeIndent = YamlIndentUtil.add(node.getIndent(), adjustIndent);
|
||||
int currentIndent = YamlIndentUtil.minIndent(cursorIndent, nodeIndent);
|
||||
while (node.getIndent()==-1 || (node.getIndent()>=currentIndent && node.getNodeType()!=SNodeType.DOC)) {
|
||||
while (nodeIndent==-1 || (nodeIndent>=currentIndent && node.getNodeType()!=SNodeType.DOC)) {
|
||||
node = node.getParent();
|
||||
nodeIndent = node.getIndent();
|
||||
}
|
||||
return node;
|
||||
} else if (node.getNodeType()==SNodeType.SEQ) {
|
||||
@@ -252,6 +248,10 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected SNode getContextNode(YamlDocument doc, SNode node, int offset) throws Exception {
|
||||
return getContextNode(doc, node, offset, 0);
|
||||
}
|
||||
|
||||
protected YamlPath getContextPath(YamlDocument doc, SNode node, int offset) throws Exception {
|
||||
if (node==null) {
|
||||
return YamlPath.EMPTY;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class YamlIndentUtil {
|
||||
* for the current document).
|
||||
*/
|
||||
public final String NEWLINE;
|
||||
|
||||
|
||||
public YamlIndentUtil(String newline) {
|
||||
this.NEWLINE = newline;
|
||||
Assert.isNotNull(NEWLINE);
|
||||
@@ -100,4 +100,16 @@ public class YamlIndentUtil {
|
||||
return offset + indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given offset to an indent, correctly handling the case
|
||||
* were the indent is -1 (unknown)
|
||||
*/
|
||||
public static int add(int indent, int adjustment) {
|
||||
if (indent==-1) {
|
||||
return indent; //indent remains unknown
|
||||
}
|
||||
indent += adjustment;
|
||||
return indent>=0 ? indent : 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,10 +45,12 @@ public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
ConcourseModel models = new ConcourseModel(documents);
|
||||
YamlASTProvider currentAsts = models.getAstProvider(false);
|
||||
private SchemaSpecificPieces forPipelines;
|
||||
private SchemaSpecificPieces forTasks;
|
||||
|
||||
private class SchemaSpecificPieces {
|
||||
|
||||
final VscodeCompletionEngine completionEngine;
|
||||
final VscodeCompletionEngineAdapter completionEngine;
|
||||
final VscodeHoverEngineAdapter hoverEngine;
|
||||
final YamlSchemaBasedReconcileEngine reconcileEngine;
|
||||
|
||||
@@ -64,13 +66,16 @@ public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
reconcileEngine.setTypeCollector(models.getAstTypeCache());
|
||||
}
|
||||
|
||||
public void setMaxCompletions(int max) {
|
||||
completionEngine.setMaxCompletionsNumber(max);
|
||||
}
|
||||
}
|
||||
|
||||
public ConcourseLanguageServer() {
|
||||
PipelineYmlSchema pipelineSchema = new PipelineYmlSchema(models);
|
||||
|
||||
SchemaSpecificPieces forPipelines = new SchemaSpecificPieces(pipelineSchema);
|
||||
SchemaSpecificPieces forTasks = new SchemaSpecificPieces(pipelineSchema.getTaskSchema());
|
||||
this.forPipelines = new SchemaSpecificPieces(pipelineSchema);
|
||||
this.forTasks = new SchemaSpecificPieces(pipelineSchema.getTaskSchema());
|
||||
ConcourseDefinitionFinder definitionFinder = new ConcourseDefinitionFinder(this, models, pipelineSchema);
|
||||
|
||||
// SimpleWorkspaceService workspace = getWorkspaceService();
|
||||
@@ -134,6 +139,11 @@ public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
}
|
||||
return super.getDiagnosticSeverity(problem);
|
||||
}
|
||||
public SimpleLanguageServer setMaxCompletions(int max) {
|
||||
forPipelines.setMaxCompletions(max);
|
||||
forTasks.setMaxCompletions(max);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerCapabilities getServerCapabilities() {
|
||||
@@ -150,4 +160,5 @@ public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,12 @@ public class ConcourseEditorTest {
|
||||
LanguageServerHarness harness;
|
||||
|
||||
@Before public void setup() throws Exception {
|
||||
harness = new LanguageServerHarness(ConcourseLanguageServer::new, LanguageIds.CONCOURSE_PIPELINE);
|
||||
harness = new LanguageServerHarness(() -> {
|
||||
return new ConcourseLanguageServer()
|
||||
.setMaxCompletions(100);
|
||||
},
|
||||
LanguageIds.CONCOURSE_PIPELINE
|
||||
);
|
||||
harness.intialize(null);
|
||||
}
|
||||
|
||||
@@ -2704,6 +2709,46 @@ public class ConcourseEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void relaxedIndentContextMoreSpaces3() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"jobs:\n" +
|
||||
"- name: job-hello-world\n" +
|
||||
" public: true\n" +
|
||||
" plan:\n" +
|
||||
" - get: resource-tutorial\n" +
|
||||
" - task: hello-world\n" +
|
||||
" <*>"
|
||||
);
|
||||
|
||||
editor.assertCompletionLabels(
|
||||
//completions for current (i.e Job) context:
|
||||
"build_logs_to_retain",
|
||||
"disable_manual_trigger",
|
||||
"max_in_flight",
|
||||
"serial",
|
||||
"serial_groups",
|
||||
"name",
|
||||
"plan",
|
||||
"public",
|
||||
//Completions for nested context (i.e. task step)
|
||||
"➔ attempts",
|
||||
"➔ config",
|
||||
"➔ ensure",
|
||||
"➔ file",
|
||||
"➔ image",
|
||||
"➔ input_mapping",
|
||||
"➔ on_failure",
|
||||
"➔ on_success",
|
||||
"➔ output_mapping",
|
||||
"➔ params",
|
||||
"➔ privileged",
|
||||
"➔ tags",
|
||||
"➔ task",
|
||||
"➔ timeout"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void assertContextualCompletions(String conText, String textBefore, String... textAfter) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user