Content assist in app-yml partially working

This commit is contained in:
Kris De Volder
2016-11-01 10:55:30 -07:00
parent e42737bd38
commit 54035b0a39
13 changed files with 97 additions and 76 deletions

View File

@@ -7,9 +7,13 @@ import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexProvider {
private JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
private JavaProjectFinder javaProjectFinder;
private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(ValueProviderRegistry.getDefault());
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder) {
this.javaProjectFinder = javaProjectFinder;
}
@Override
public FuzzyMap<PropertyInfo> getIndex(IDocument doc) {
IJavaProject jp = javaProjectFinder.find(doc);

View File

@@ -16,6 +16,7 @@ import org.springframework.ide.vscode.commons.languageserver.util.BadLocationExc
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
import org.springframework.ide.vscode.commons.languageserver.util.Region;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
import org.springframework.ide.vscode.commons.util.Assert;
import io.typefox.lsapi.TextEdit;
@@ -322,12 +323,12 @@ public class DocumentEdits implements ProposalApplier {
return null;
}
public TextReplace asReplacement(IDocument doc) throws BadLocationException {
public TextReplace asReplacement(TextDocument doc) throws BadLocationException {
if (!edits.isEmpty()) {
int start = edits.stream().mapToInt(Edit::getStart).min().getAsInt();
int end = edits.stream().mapToInt(Edit::getEnd).max().getAsInt();
DocumentState state = new DocumentState(doc);
DocumentState state = new DocumentState(doc.copy());
for (Edit edit : edits) {
edit.apply(state);
}

View File

@@ -28,6 +28,8 @@ import io.typefox.lsapi.impl.TextEditImpl;
*/
public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
final private int MAX_COMPLETIONS = 10;
final static Logger logger = LoggerFactory.getLogger(VscodeCompletionEngineAdapter.class);
public static final String VS_CODE_CURSOR_MARKER = "{{}}";
@@ -56,7 +58,13 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
list.setIncomplete(false);
List<CompletionItemImpl> items = new ArrayList<>(completions.size());
SortKeys sortkeys = new SortKeys();
int count = 0;
for (ICompletionProposal c : completions) {
count++;
if (count>MAX_COMPLETIONS) {
list.setIncomplete(true);
break;
}
try {
items.add(adaptItem(doc, c, sortkeys));
} catch (Exception e) {

View File

@@ -133,6 +133,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
@Override
public void didClose(DidCloseTextDocumentParams params) {
System.out.println("closing: "+params.getTextDocument().getUri());
String url = params.getTextDocument().getUri();
if (url!=null) {
documents.remove(url);

View File

@@ -105,8 +105,9 @@ public class YamlPathEdits extends DocumentEdits {
buf.append(":");
if (i<path.size()-1) {
indent += YamlIndentUtil.INDENT_BY;
} else {
buf.append(indentUtil.applyIndentation(appendText, indent));
}
buf.append(indentUtil.applyIndentation(appendText, indent));
}
return buf.toString();
}

View File

@@ -258,8 +258,9 @@ public class LanguageServerHarness {
public void assertCompletion(String textBefore, String expectTextAfter) throws Exception {
Editor editor = newEditor(textBefore);
assertNotNull(editor.getCompletions());
assertFalse(editor.getCompletions().isEmpty());
List<CompletionItem> completions = editor.getCompletions();
assertNotNull(completions);
assertFalse(completions.isEmpty());
CompletionItem completion = editor.getFirstCompletion();
editor.apply(completion);
assertEquals(expectTextAfter, editor.getText());

View File

@@ -14,6 +14,7 @@ import org.springframework.ide.vscode.application.properties.metadata.SpringProp
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
@@ -32,6 +33,8 @@ public abstract class AbstractPropsEditorTest {
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
protected PropertyIndexHarness md;
protected final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject();
private LanguageServerHarness harness;
private IJavaProject testProject;
private TypeUtil typeUtil;
@@ -47,6 +50,10 @@ public abstract class AbstractPropsEditorTest {
return harness.newEditor(contents);
}
private IJavaProject getTestProject() {
return testProject;
}
@Before
public void setup() throws Exception {
md = new PropertyIndexHarness();

View File

@@ -24,6 +24,7 @@ import org.springframework.ide.vscode.application.properties.metadata.DefaultSpr
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.LoggingFormat;
@@ -130,9 +131,9 @@ public class Main {
* When the request stream is closed, wait for 5s for all outstanding responses to compute, then return.
*/
public static void run(Connection connection) {
SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider();
TypeUtil typeUtil = new TypeUtil(null);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> typeUtil;
JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
ApplicationPropertiesLanguageServer server = new ApplicationPropertiesLanguageServer(indexProvider, typeUtilProvider);

View File

@@ -1,27 +1,24 @@
package org.springframework.ide.vscode.application.yaml;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.completions.RelaxedNameConfig;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.application.yaml.completions.ApplicationYamlCompletionEngine;
import org.springframework.ide.vscode.application.yaml.completions.ApplicationYamlStructureProvider;
import org.springframework.ide.vscode.application.yaml.reconcile.ApplicationYamlReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
import org.springframework.ide.vscode.commons.util.Futures;
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngine;
import org.yaml.snakeyaml.Yaml;
import io.typefox.lsapi.CompletionItem;
import io.typefox.lsapi.CompletionItemKind;
import io.typefox.lsapi.CompletionList;
import io.typefox.lsapi.TextDocumentSyncKind;
import io.typefox.lsapi.impl.CompletionItemImpl;
import io.typefox.lsapi.impl.CompletionListImpl;
import io.typefox.lsapi.impl.CompletionOptionsImpl;
import io.typefox.lsapi.impl.ServerCapabilitiesImpl;
@@ -32,7 +29,7 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
private SpringPropertyIndexProvider indexProvider;
private TypeUtilProvider typeUtilProvider;
public ApplicationYamlLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider) {
public ApplicationYamlLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder javaProjectFinder) {
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
SimpleTextDocumentService documents = getTextDocumentService();
@@ -54,54 +51,16 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
// }
// });
documents.onCompletion(params -> {
CompletableFuture<CompletionList> promise = new CompletableFuture<>();
CompletionListImpl completions = new CompletionListImpl();
completions.setIncomplete(false);
List<CompletionItemImpl> items = new ArrayList<>();
{
// {
// label: 'TypeScript',
// kind: CompletionItemKind.Text,
// data: 1
// },
CompletionItemImpl item = new CompletionItemImpl();
item.setLabel("TypeScript");
item.setKind(CompletionItemKind.Text);
item.setData(1);
items.add(item);
}
{
// {
// label: 'JavaScript',
// kind: CompletionItemKind.Text,
// data: 2
// }
CompletionItemImpl item = new CompletionItemImpl();
item.setLabel("JavaScript");
item.setKind(CompletionItemKind.Text);
item.setData(2);
items.add(item);
}
completions.setItems(items);
promise.complete(completions);
return promise;
});
documents.onCompletionResolve((_item) -> {
CompletionItemImpl item = (CompletionItemImpl) _item;
Object data = item.getData();
if (Integer.valueOf(1).equals(data)) {
item.setDetail("TypeScript details");
item.setDocumentation("TypeScript docs");
} else {
item.setDetail("JavaScript details");
item.setDocumentation("JavaScript docs");
}
return Futures.of((CompletionItem)item);
});
YamlCompletionEngine yamlCompletionEngine = ApplicationYamlCompletionEngine.create(
indexProvider,
javaProjectFinder,
ApplicationYamlStructureProvider.INSTANCE,
typeUtilProvider,
RelaxedNameConfig.COMPLETION_DEFAULTS
);
VscodeCompletionEngine completionEngine = new VscodeCompletionEngineAdapter(this, yamlCompletionEngine);
documents.onCompletion(completionEngine::getCompletions);
documents.onCompletionResolve(completionEngine::resolveCompletion);
}
protected IReconcileEngine getReconcileEngine() {
@@ -115,7 +74,7 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
c.setTextDocumentSync(TextDocumentSyncKind.Full);
CompletionOptionsImpl completionProvider = new CompletionOptionsImpl();
completionProvider.setResolveProvider(true);
completionProvider.setResolveProvider(false);
c.setCompletionProvider(completionProvider);
return c;

View File

@@ -13,6 +13,7 @@ import org.springframework.ide.vscode.application.properties.metadata.DefaultSpr
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.LoggingFormat;
@@ -83,14 +84,14 @@ public class Main {
* When the request stream is closed, wait for 5s for all outstanding responses to compute, then return.
*/
public static void run(Connection connection) {
//TODO: proper TypeUtilProvider and IndexProvider that somehow determine classpath that should be
JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
//TODO: proper TypeUtilProvider and IndexProvider that somehow determine classpath that should be
// in effect for given IDocument and provide TypeUtil or SpringPropertyIndex parsed from that classpath.
// Note that the provider is responsible for doing some kind of sensible caching so that indexes are not
// rebuilt every time the index is being used.
SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider();
TypeUtil typeUtil = new TypeUtil(null);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> typeUtil;
ApplicationYamlLanguageServer server = new ApplicationYamlLanguageServer(indexProvider, typeUtilProvider);
SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
ApplicationYamlLanguageServer server = new ApplicationYamlLanguageServer(indexProvider, typeUtilProvider, javaProjectFinder);
LoggingJsonAdapter jsonServer = new LoggingJsonAdapter(server);
jsonServer.setMessageLog(new PrintWriter(System.out));

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* 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.application.yaml.completions;
import java.util.Collections;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.yaml.path.KeyAliases;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
public class ApplicationYamlStructureProvider {
private static final KeyAliases KEY_ALIASES = new KeyAliases() {
@Override
public Iterable<String> getKeyAliases(String base) {
String camelCased = StringUtil.hyphensToCamelCase(base, false);
if (!camelCased.equals(base)) {
return Collections.singletonList(camelCased);
}
return Collections.emptyList();
}
};
public static final YamlStructureProvider INSTANCE = YamlStructureProvider.withAliases(KEY_ALIASES);
}

View File

@@ -21,6 +21,7 @@ import org.junit.Test;
import org.springframework.ide.vscode.application.properties.metadata.CachingValueProvider;
import org.springframework.ide.vscode.application.properties.metadata.PropertyInfo;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -41,6 +42,8 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
////////////////////////////////////////////////////////////////////////////////////////
private JavaProjectFinder javaProjectFinder;
@Test public void linterRunsOnDocumentOpenAndChange() throws Exception {
Editor editor = newEditor(
"somemap: val\n"+
@@ -3519,7 +3522,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
@Override
protected SimpleLanguageServer newLanguageServer() {
return new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider);
return new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider, javaProjectFinder);
}
}

View File

@@ -22,7 +22,7 @@ public class ApplicationYamlLanguageServerTests {
}
private LanguageServerHarness newHarness() throws Exception {
Callable<? extends LanguageServer> f = () -> new ApplicationYamlLanguageServer((d) -> null, (d) -> null);
Callable<? extends LanguageServer> f = () -> new ApplicationYamlLanguageServer((d) -> null, (d) -> null, (d) -> null);
return new LanguageServerHarness(f);
}