Fix for PT-167494938

Snippet completion was broken for concourse resource type
'extra insertions'.
This commit is contained in:
Kris De Volder
2019-07-25 16:46:00 -07:00
parent bd061a4ec3
commit d9f48ed693
8 changed files with 63 additions and 12 deletions

View File

@@ -17,6 +17,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.lsp4j.TextEdit;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -322,7 +323,7 @@ public class DocumentEdits implements ProposalApplier {
private List<Edit> edits = new ArrayList<Edit>();
private IDocument doc;
final private boolean hasSnippets;
private boolean hasSnippets;
/**
* When this is true, the cursor is moved after each edit, to be positioned right after the
@@ -337,7 +338,7 @@ public class DocumentEdits implements ProposalApplier {
this.doc = doc;
this.hasSnippets = hasSnippets;
}
public void delete(int start, int end) {
Assert.isLegal(start<=end);
edits.add(new Deletion(grabCursor, start, end));
@@ -347,6 +348,17 @@ public class DocumentEdits implements ProposalApplier {
delete(offset, offset+text.length());
}
public void insertSnippet(int offset, String snippet) {
//The way we track/handle snippet usage is not totally correct.
//There is a bug here that if we compose multiple edits, some of which
//use snippet placeholders and others which don't, all will be considered
//as using snippets. This may pose problems if somehow literal text that
//looks like a placeholder is combined with real snippet. Then all will
//be treated as a snippet.
hasSnippets |= true;
edits.add(new Insertion(grabCursor, offset, snippet.toString()));
}
public void insert(int offset, String insert) {
edits.add(new Insertion(grabCursor, offset, insert));
}
@@ -499,5 +511,4 @@ public class DocumentEdits implements ProposalApplier {
final public boolean hasSnippets() {
return hasSnippets;
}
}

View File

@@ -77,6 +77,18 @@ public class PlaceHolderString {
this.string = string;
}
public boolean hasPlaceHolders() {
if (placeHolders.isEmpty()) {
return false;
}
if (placeHolders.size()==1) {
PlaceHolder placeHolder = CollectionUtil.getAny(placeHolders.values());
if (string.length()==placeHolder.getEnd()) {
return false;
}
}
return true;
}
@Override
public String toString() {

View File

@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
@@ -279,9 +280,14 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
edits.insert(offset, " ");
}
edits.insert(offset, value.getValue());
String extraInsertion = value.getExtraInsertion();
PlaceHolderString extraInsertion = value.getExtraInsertion();
if (extraInsertion!=null) {
edits.insert(offset, indenter.applyIndentation(extraInsertion, referenceIndent));
String insertText = indenter.applyIndentation(extraInsertion.toString(), referenceIndent);
if (extraInsertion.hasPlaceHolders()) {
edits.insertSnippet(offset, insertText);
} else {
edits.insert(offset, insertText);
}
}
completions.add(completionFactory().valueProposal(
value.getValue(), query, value.getLabel(), type,

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.schema;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.Renderable;
@@ -19,7 +20,7 @@ public class BasicYValueHint implements YValueHint {
private final String value;
private String label;
private Supplier<String> extraInsertion = null;
private Supplier<PlaceHolderString> extraInsertion = null;
private Renderable documentation;
public BasicYValueHint(String value, String label) {
@@ -85,12 +86,12 @@ public class BasicYValueHint implements YValueHint {
}
@Override
public String getExtraInsertion() {
Supplier<String> ei = this.extraInsertion;
public PlaceHolderString getExtraInsertion() {
Supplier<PlaceHolderString> ei = this.extraInsertion;
return ei==null ? null : ei.get();
}
public BasicYValueHint setExtraInsertion(Supplier<String> insertions) {
public BasicYValueHint setExtraInsertion(Supplier<PlaceHolderString> insertions) {
Assert.isLegal(this.extraInsertion==null);
this.extraInsertion = insertions;
return this;

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.schema;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
import org.springframework.ide.vscode.commons.util.Renderable;
public interface YValueHint {
@@ -22,7 +23,7 @@ public interface YValueHint {
* on the next line and indented to line-up relative to the indentation of
* the line where the value itself is being inserted.
*/
String getExtraInsertion();
PlaceHolderString getExtraInsertion();
/**
* An optional documentation string (i.e. shown in javadoc side hover in Eclipse style

View File

@@ -717,12 +717,13 @@ public class Editor {
setText(saveText);
}
public void assertCompletionWithLabel(Predicate<String> expectLabel, String expectedResult) throws Exception {
public CompletionItem assertCompletionWithLabel(Predicate<String> expectLabel, String expectedResult) throws Exception {
CompletionItem completion = assertCompletionWithLabel(expectLabel);
String saveText = getText();
apply(completion);
assertEquals(expectedResult, getText());
setText(saveText);
return completion;
}
public void setSelection(int start, int end) {

View File

@@ -424,7 +424,7 @@ public class ConcourseModel {
snippet.text("\n "+p.getName()+": ");
snippet.placeHolder();
}
return snippet.toString();
return snippet.build();
}
}
return null;

View File

@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.InsertTextFormat;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
@@ -4382,6 +4383,24 @@ public class ConcourseEditorTest {
);
editor.assertProblems(/*NONE*/);
}
@Test public void cfResourceTypeCompletion() throws Exception {
Editor editor = harness.newEditor(
"resources:\n" +
"- name: foo\n" +
" type: <*>"
);
CompletionItem item = editor.assertCompletionWithLabel(label -> label.startsWith("cf"),
"resources:\n" +
"- name: foo\n" +
" type: cf\n" +
" source:\n" +
" api: $1\n" +
" organization: $2\n" +
" space: $3<*>"
);
assertEquals(InsertTextFormat.Snippet, item.getInsertTextFormat());
}
@Test public void cfResourceSourceCompletions() throws Exception {
Editor editor = harness.newEditor(