Snippets now mostly working all tests passing.
This commit is contained in:
@@ -16,6 +16,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SnippetBuilder;
|
||||
import org.springframework.ide.vscode.commons.util.CollectorUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
|
||||
@@ -84,17 +85,13 @@ public class SchemaBasedSnippetGenerator implements TypeBasedSnippetProvider {
|
||||
SnippetBuilder builder = snippetBuilderFactory.get();
|
||||
List<YTypedProperty> requiredProps = typeUtil.getProperties(type).stream()
|
||||
.filter(p -> p.isPrimary() || p.isRequired())
|
||||
.collect(Collectors.toList());
|
||||
.collect(CollectorUtil.toImmutableList());
|
||||
if (!requiredProps.isEmpty()) {
|
||||
generateBeanSnippet(requiredProps, builder, indent, maxNesting);
|
||||
}
|
||||
if (builder.getPlaceholderCount()>=2) {
|
||||
//place holder count is a good indicator of snippet complexity and allows us to
|
||||
// avoid creating trivial snippets (which aren't very useful).
|
||||
ImmutableSet<YTypedProperty> vetoProps = ImmutableSet.copyOf(requiredProps);
|
||||
// Do not suggest snippet if it contains properties that are already defined.
|
||||
return new Snippet(typeUtil.niceTypeName(type)+" Snippet", builder.toString(), (dc) ->
|
||||
dc.getDefinedProperties().stream().noneMatch(vetoProps::contains)
|
||||
requiredProps.stream().noneMatch(p -> dc.getDefinedProperties().contains(p.getName()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.Editor.PLAIN_COMPLETION;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.Editor.*;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.assertContains;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DiagnosticSeverity;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.bosh.mocks.MockCloudConfigProvider;
|
||||
import org.springframework.ide.vscode.bosh.models.BoshCommandReleasesProvider;
|
||||
@@ -1609,4 +1610,159 @@ public class BoshEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void snippet_toplevel() throws Exception {
|
||||
Editor editor = harness.newEditor("<*>");
|
||||
editor.assertCompletions(SNIPPET_COMPLETION,
|
||||
"name: $1\n" +
|
||||
"releases:\n" +
|
||||
"- name: $2\n" +
|
||||
" version: $3\n" +
|
||||
"stemcells:\n" +
|
||||
"- alias: $4\n" +
|
||||
" version: $5\n" +
|
||||
"update:\n" +
|
||||
" canaries: $6\n" +
|
||||
" max_in_flight: $7\n" +
|
||||
" canary_watch_time: $8\n" +
|
||||
" update_watch_time: $9\n" +
|
||||
"instance_groups:\n" +
|
||||
"- name: $10\n" +
|
||||
" azs:\n" +
|
||||
" - $11\n" +
|
||||
" instances: $12\n" +
|
||||
" jobs:\n" +
|
||||
" - name: $13\n" +
|
||||
" release: $14\n" +
|
||||
" vm_type: $15\n" +
|
||||
" stemcell: $16\n" +
|
||||
" networks:\n" +
|
||||
" - name: $17<*>"
|
||||
, // ------------------
|
||||
"instance_groups:\n" +
|
||||
"- name: $1\n" +
|
||||
" azs:\n" +
|
||||
" - $2\n" +
|
||||
" instances: $3\n" +
|
||||
" jobs:\n" +
|
||||
" - name: $4\n" +
|
||||
" release: $5\n" +
|
||||
" vm_type: $6\n" +
|
||||
" stemcell: $7\n" +
|
||||
" networks:\n" +
|
||||
" - name: $8<*>"
|
||||
, // ----------------
|
||||
"releases:\n" +
|
||||
"- name: $1\n" +
|
||||
" version: $2<*>"
|
||||
, // ----------------
|
||||
"stemcells:\n" +
|
||||
"- alias: $1\n" +
|
||||
" version: $2<*>"
|
||||
, // ----------------
|
||||
"update:\n" +
|
||||
" canaries: $1\n" +
|
||||
" max_in_flight: $2\n" +
|
||||
" canary_watch_time: $3\n" +
|
||||
" update_watch_time: $4<*>"
|
||||
, // -----------------
|
||||
"variables:\n" +
|
||||
"- name: $1\n" +
|
||||
" type: $2<*>"
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void snippet_disabledWhenPropertiesAlreadyDefined() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"name:\n" +
|
||||
"releases:\n" +
|
||||
"stemcells:\n" +
|
||||
"<*>"
|
||||
);
|
||||
|
||||
editor.assertCompletionLabels(SNIPPET_COMPLETION,
|
||||
//"BoshDeploymentManifest Snippet",
|
||||
"instance_groups Snippet",
|
||||
// "releases Snippet",
|
||||
// "stemcells Snippet"
|
||||
"update Snippet",
|
||||
"variables Snippet",
|
||||
"- Stemcell Snippet"
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void snippet_nested_plain() throws Exception {
|
||||
Editor editor;
|
||||
//Plain exact completion
|
||||
editor = harness.newEditor(
|
||||
"instance_groups:\n" +
|
||||
"- name: blah\n" +
|
||||
" <*>"
|
||||
);
|
||||
editor.assertContextualCompletions(LanguageId.BOSH_DEPLOYMENT, c -> c.getLabel().equals("jobs Snippet"),
|
||||
"jo<*>"
|
||||
, // ------
|
||||
"jobs:\n" +
|
||||
" - name: $1\n" +
|
||||
" release: $2<*>"
|
||||
);
|
||||
editor.assertCompletionWithLabel("jobs Snippet",
|
||||
"instance_groups:\n" +
|
||||
"- name: blah\n" +
|
||||
" jobs:\n" +
|
||||
" - name: $1\n" +
|
||||
" release: $2<*>"
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void snippet_nested_indenting() throws Exception {
|
||||
Editor editor;
|
||||
//With extra indent:
|
||||
editor = harness.newEditor(
|
||||
"instance_groups:\n" +
|
||||
"- name: blah\n" +
|
||||
"<*>"
|
||||
);
|
||||
editor.assertCompletionWithLabel("→ jobs Snippet",
|
||||
"instance_groups:\n" +
|
||||
"- name: blah\n" +
|
||||
" jobs:\n" +
|
||||
" - name: $1\n" +
|
||||
" release: $2<*>"
|
||||
);
|
||||
editor.assertContextualCompletions(LanguageId.BOSH_DEPLOYMENT, c -> c.getLabel().equals("→ jobs Snippet"),
|
||||
"jo<*>"
|
||||
, // ------
|
||||
" jobs:\n" +
|
||||
" - name: $1\n" +
|
||||
" release: $2<*>"
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void relaxedCAmoreSpaces() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"name: foo\n" +
|
||||
"instance_groups:\n" +
|
||||
"- name: \n" +
|
||||
"<*>"
|
||||
);
|
||||
editor.assertContextualCompletions(LanguageId.BOSH_DEPLOYMENT, c -> c.getLabel().equals("→ jobs"),
|
||||
"jo<*>"
|
||||
, // ==>
|
||||
" jobs:\n" +
|
||||
" - <*>"
|
||||
);
|
||||
}
|
||||
|
||||
@Test @Ignore public void keyCompletionThatNeedANewline() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"name: foo\n" +
|
||||
"update: canwa<*>"
|
||||
);
|
||||
editor.assertCompletions(
|
||||
"name: foo\n" +
|
||||
"update: \n" +
|
||||
" canary_watch_time: <*>"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ public class DocumentEdits implements ProposalApplier {
|
||||
|
||||
private static final Pattern NON_WS_CHAR = Pattern.compile("\\S");
|
||||
|
||||
private boolean isRelativeIndent = false;
|
||||
|
||||
// Note: for small number of edits this implementation is okay.
|
||||
// for large number of edits it is potentially slow because of the
|
||||
// way it transforms edit coordinates (a growing chain of
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.*;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_DASH_PROPOSAL;
|
||||
import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.DEEMP_DEPRECATION;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -33,7 +34,6 @@ import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.PartialCollection;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParseException;
|
||||
import org.springframework.ide.vscode.commons.yaml.completion.DefaultCompletionFactory.ValueProposal;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyInfoTemplates;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
|
||||
@@ -107,13 +107,12 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
for (Snippet snippet : snippets) {
|
||||
String snippetName = snippet.getName();
|
||||
double score = FuzzyMatcher.matchScore(query, snippetName);
|
||||
if (score!=0.0) {
|
||||
String textBeforeQuery = doc.getLineTextBefore(offset);
|
||||
if (score!=0.0 && snippet.isApplicable(getSchemaContext())) {
|
||||
DocumentEdits edits = new DocumentEdits(doc.getDocument());
|
||||
int start = offset - query.length();
|
||||
edits.delete(start, query);
|
||||
int referenceIndent = textBeforeQuery.length();
|
||||
boolean needsSpace = start > 0 && !Character.isWhitespace(doc.getChar(offset-1));
|
||||
int referenceIndent = doc.getColumn(start);
|
||||
boolean needsSpace = start > 0 && !Character.isWhitespace(doc.getChar(start-1));
|
||||
if (needsSpace) {
|
||||
referenceIndent++;
|
||||
edits.insert(start, " ");
|
||||
@@ -133,7 +132,6 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
|
||||
public List<ICompletionProposal> getKeyCompletions(YamlDocument doc, int offset, String query) throws Exception {
|
||||
int queryOffset = offset - query.length();
|
||||
SNode contextNode = getContextNode();
|
||||
DynamicSchemaContext dynamicCtxt = getSchemaContext();
|
||||
List<YTypedProperty> allProperties = typeUtil.getProperties(type);
|
||||
if (CollectionUtil.hasElements(allProperties)) {
|
||||
@@ -141,6 +139,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
Set<String> definedProps = dynamicCtxt.getDefinedProperties();
|
||||
List<ICompletionProposal> proposals = new ArrayList<>();
|
||||
boolean suggestDeprecated = typeUtil.suggestDeprecatedProperties();
|
||||
YamlIndentUtil indenter = new YamlIndentUtil(doc);
|
||||
for (List<YTypedProperty> thisTier : tieredProperties) {
|
||||
List<YTypedProperty> undefinedProps = thisTier.stream()
|
||||
.filter(p -> !definedProps.contains(p.getName()) && (suggestDeprecated || !p.isDeprecated()))
|
||||
@@ -150,15 +149,17 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
String name = p.getName();
|
||||
double score = FuzzyMatcher.matchScore(query, name);
|
||||
if (score!=0) {
|
||||
YamlPath relativePath = YamlPath.fromSimpleProperty(name);
|
||||
YamlPathEdits edits = new YamlPathEdits(doc);
|
||||
DocumentEdits edits = new DocumentEdits(doc.getDocument());
|
||||
YType YType = p.getType();
|
||||
edits.delete(queryOffset, query);
|
||||
int referenceIndent = doc.getColumn(queryOffset);
|
||||
if (queryOffset>0 && !Character.isWhitespace(doc.getChar(queryOffset-1))) {
|
||||
//See https://www.pivotaltracker.com/story/show/137722057
|
||||
edits.insert(queryOffset, " ");
|
||||
referenceIndent++;
|
||||
}
|
||||
edits.createPathInPlace(contextNode, relativePath, queryOffset, appendTextFor(YType));
|
||||
String snippet = p.getName()+":" +appendTextFor(YType);
|
||||
edits.insert(queryOffset, indenter.applyIndentation(snippet, referenceIndent));
|
||||
ICompletionProposal completion = completionFactory().beanProperty(doc.getDocument(),
|
||||
contextPath.toPropString(), getType(),
|
||||
query, p, score, edits, typeUtil);
|
||||
@@ -405,18 +406,20 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
@Override
|
||||
protected DocumentEdits transformEdit(DocumentEdits textEdit) {
|
||||
textEdit.transformFirstNonWhitespaceEdit((Integer offset, String insertText) -> {
|
||||
YamlIndentUtil indenter = new YamlIndentUtil("\n");
|
||||
if (needNewline(textEdit)) {
|
||||
return insertText.substring(0, offset)
|
||||
+ "\n" +Strings.repeat(" ", node.getIndent())+"- "
|
||||
+ insertText.substring(offset);
|
||||
+ indenter.applyIndentation(insertText.substring(offset), YamlIndentUtil.INDENT_BY);
|
||||
} else if (offset > 2) {
|
||||
String prefix = insertText.substring(offset-2, offset);
|
||||
if (" ".equals(prefix)) {
|
||||
//special case don't add the "- " in front, but replace the inserted spaces instead.
|
||||
return insertText.substring(0, offset-2)+"- "+insertText.substring(offset);
|
||||
return insertText.substring(0, offset-2)
|
||||
+ "- "+ insertText.substring(offset);
|
||||
}
|
||||
}
|
||||
return insertText.substring(0, offset) + "- "+insertText.substring(offset);
|
||||
return insertText.substring(0, offset) + "- "+indenter.applyIndentation(insertText.substring(offset), YamlIndentUtil.INDENT_BY);
|
||||
});
|
||||
return textEdit;
|
||||
}
|
||||
@@ -425,11 +428,9 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
//value proposals which are inserted right after a key will not automatically include a newline, as
|
||||
// its not required for them. So we should add it along with the dash.
|
||||
try {
|
||||
if (original instanceof ValueProposal) {
|
||||
Integer insertAt = textEdit.getFirstEditStart();
|
||||
if (insertAt!=null) {
|
||||
return !"".equals(doc.getLineTextBefore(insertAt).trim());
|
||||
}
|
||||
Integer insertAt = textEdit.getFirstEditStart();
|
||||
if (insertAt!=null) {
|
||||
return !"".equals(doc.getLineTextBefore(insertAt).trim());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
|
||||
@@ -52,7 +52,7 @@ import com.google.common.collect.ImmutableList;
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class YamlCompletionEngine implements ICompletionEngine {
|
||||
|
||||
|
||||
Pattern SPACES = Pattern.compile("[ ]+");
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(YamlCompletionEngine.class);
|
||||
@@ -110,7 +110,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
|
||||
protected Collection<? extends ICompletionProposal> getRelaxedCompletions(int offset, YamlDocument doc, SNode current, SNode contextNode, int baseIndent, double deempasizeBy) {
|
||||
try {
|
||||
return fixIndentations(getBaseCompletions(offset, doc, current, contextNode),
|
||||
return fixIndentations(getBaseCompletions(offset, doc, current, contextNode),
|
||||
current, contextNode, baseIndent, deempasizeBy);
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
@@ -118,7 +118,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
protected Collection<? extends ICompletionProposal> fixIndentations(Collection<ICompletionProposal> completions, SNode currentNode,
|
||||
protected Collection<? extends ICompletionProposal> fixIndentations(Collection<ICompletionProposal> completions, SNode currentNode,
|
||||
SNode contextNode, int baseIndent, double deempasizeBy) {
|
||||
if (!completions.isEmpty()) {
|
||||
int dashyIndent = getTargetIndent(contextNode, currentNode, true);
|
||||
@@ -144,7 +144,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
if (isExtraIndentRelaxable(contextNode, fixIndentBy)) {
|
||||
return indented(p, Strings.repeat(" ", fixIndentBy));
|
||||
}
|
||||
} else { // fixIndentBy < 0
|
||||
} else { // fixIndentBy < 0
|
||||
if (isLesserIndentRelaxable(currentNode, contextNode)) {
|
||||
return dedented(p, -fixIndentBy, contextNode.getDocument());
|
||||
}
|
||||
@@ -168,7 +168,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the indentation level needed to line up with other contextNode children.
|
||||
* Determine the indentation level needed to line up with other contextNode children.
|
||||
* If the contextNode has no children, then compute a proper default indentation where
|
||||
* a new child could be added.
|
||||
*/
|
||||
@@ -182,8 +182,8 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
if (child.isPresent()) {
|
||||
return child.get().getIndent();
|
||||
}
|
||||
return (dashy || contextNode.getNodeType()==SNodeType.DOC)
|
||||
? contextNode.getIndent()
|
||||
return (dashy || contextNode.getNodeType()==SNodeType.DOC)
|
||||
? contextNode.getIndent()
|
||||
: contextNode.getIndent() + YamlIndentUtil.INDENT_BY;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
};
|
||||
transformed.deemphasize(DEEMP_DEDENTED_PROPOSAL*numArrows);
|
||||
return transformed;
|
||||
}
|
||||
}
|
||||
// we can't dedent the proposal by the requested amount of space. So err on the safe
|
||||
// side and ignore the proposal. (Otherwise me might end up deleting non-space chars
|
||||
// in our attempt to de-dent.)
|
||||
@@ -226,7 +226,13 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
return Strings.repeat(Unicodes.RIGHT_ARROW+" ", numArrows) + originalLabel;
|
||||
}
|
||||
@Override public DocumentEdits transformEdit(DocumentEdits originalEdit) {
|
||||
originalEdit.indentFirstEdit(indentStr);
|
||||
// originalEdit.indentFirstEdit(indentStr);
|
||||
YamlIndentUtil indenter = new YamlIndentUtil("\n");
|
||||
originalEdit.transformFirstNonWhitespaceEdit((Integer offset, String insertText) -> {
|
||||
String prefix = insertText.substring(0, offset);
|
||||
String target = insertText.substring(offset);
|
||||
return prefix + indentStr + indenter.applyIndentation(target, indentStr);
|
||||
});
|
||||
return originalEdit;
|
||||
}
|
||||
};
|
||||
@@ -306,14 +312,14 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get context node candidates taking into account that we want to have a 'relaxed' interpretation
|
||||
* of the context node with respect to the current indentation where we ask for a completion.
|
||||
* To allow for the ambiguity in indentation a list of context nodes is returned instead of a
|
||||
* To allow for the ambiguity in indentation a list of context nodes is returned instead of a
|
||||
* single node. (Note we may still return a singleton list for cases where relaxed indentation
|
||||
* doesn't seem desirable).
|
||||
* @param baseIndent
|
||||
* @param baseIndent
|
||||
*/
|
||||
protected List<SNode> getContextNodes(YamlDocument doc, SNode node, int offset, int baseIndent) {
|
||||
if (node==null) {
|
||||
@@ -340,7 +346,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
|
||||
//This node has flexibility around indentation. So this is where me need to build a list of candidates!
|
||||
ImmutableList.Builder<SNode> contextNodes = ImmutableList.builder();
|
||||
while (node!=null ) {
|
||||
//Any node that represents a 'step' between contexts and is not too deeply nested is kept.
|
||||
//Any node that represents a 'step' between contexts and is not too deeply nested is kept.
|
||||
if (node.getSegment()!=null && node.getIndent()<=baseIndent) {
|
||||
contextNodes.add(node);
|
||||
}
|
||||
|
||||
@@ -37,4 +37,10 @@ public class Snippet {
|
||||
public String toString() {
|
||||
return "Snippet [ name="+name+",\n" +snippet +"\n]";
|
||||
}
|
||||
public Predicate<DynamicSchemaContext> getApplicability() {
|
||||
return applicability;
|
||||
}
|
||||
public boolean isApplicable(DynamicSchemaContext dc) {
|
||||
return applicability==null || applicability.test(dc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.commons.yaml.util;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
@@ -42,7 +43,11 @@ public class YamlIndentUtil {
|
||||
}
|
||||
|
||||
public YamlIndentUtil(YamlDocument doc) {
|
||||
this(doc.getDocument().getDefaultLineDelimiter());
|
||||
this(doc.getDocument());
|
||||
}
|
||||
|
||||
public YamlIndentUtil(IDocument doc) {
|
||||
this(doc.getDefaultLineDelimiter());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,6 +94,10 @@ public class YamlIndentUtil {
|
||||
return text.replaceAll("\\n", newlineWithIndent(indentBy));
|
||||
}
|
||||
|
||||
public String applyIndentation(String text, String indentStr) {
|
||||
return text.replaceAll("\\n", "\n"+indentStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase offset by indentation. Take care when 'indent' is -1 (unkownn) to
|
||||
* just return offset unmodified.
|
||||
|
||||
@@ -63,6 +63,7 @@ public class Editor {
|
||||
public static final Predicate<CompletionItem> PLAIN_COMPLETION = c -> !RELAXED_COMPLETION.test(c);
|
||||
public static final Predicate<CompletionItem> DEDENTED_COMPLETION = c -> c.getLabel().startsWith(Unicodes.LEFT_ARROW+" ");
|
||||
public static final Predicate<CompletionItem> INDENTED_COMPLETION = c -> c.getLabel().startsWith(Unicodes.RIGHT_ARROW+" ");
|
||||
public static final Predicate<CompletionItem> SNIPPET_COMPLETION = c -> c.getLabel().endsWith("Snippet");
|
||||
|
||||
static class EditorState {
|
||||
String documentContents;
|
||||
@@ -327,6 +328,10 @@ public class Editor {
|
||||
}
|
||||
|
||||
public List<CompletionItem> assertCompletionLabels(String... expectedLabels) throws Exception {
|
||||
return assertCompletionLabels(c -> true, expectedLabels);
|
||||
}
|
||||
|
||||
public List<CompletionItem> assertCompletionLabels(Predicate<CompletionItem> isInteresting, String... expectedLabels) throws Exception {
|
||||
StringBuilder expect = new StringBuilder();
|
||||
StringBuilder actual = new StringBuilder();
|
||||
for (String label : expectedLabels) {
|
||||
@@ -336,8 +341,10 @@ public class Editor {
|
||||
|
||||
List<CompletionItem> completions;
|
||||
for (CompletionItem completion : completions = getCompletions()) {
|
||||
actual.append(completion.getLabel());
|
||||
actual.append("\n");
|
||||
if (isInteresting.test(completion)) {
|
||||
actual.append(completion.getLabel());
|
||||
actual.append("\n");
|
||||
}
|
||||
}
|
||||
assertEquals(expect.toString(), actual.toString());
|
||||
return completions;
|
||||
|
||||
Reference in New Issue
Block a user