fixed an exception when executing code completion on a non-boot java project

This commit is contained in:
Martin Lippert
2018-02-02 12:59:19 +01:00
parent 3feb037188
commit 6685beb68b
6 changed files with 37 additions and 66 deletions

View File

@@ -247,7 +247,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
"@PutMapping(value=\"${path}/{${id}}\")\n"
+ "public ${SomeEnityData} ${putMethodName}(@PathVariable ${pvt:String} ${id}, @RequestBody ${SomeEnityData} ${entity}) {\n"
+ " //TODO: process PUT request\n" + " ${cursor}\n" + " return ${entity};\n" + "}"));
return new BootJavaCompletionEngine(javaProjectFinder, providers, snippetManager);
return new BootJavaCompletionEngine(this, providers, snippetManager);
}
protected BootJavaHoverProvider createHoverHandler(JavaProjectFinder javaProjectFinder,

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2018 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
@@ -10,76 +10,53 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.handlers;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippetManager;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public class BootJavaCompletionEngine implements ICompletionEngine {
private JavaProjectFinder projectFinder;
private Map<String, CompletionProvider> completionProviders;
private JavaSnippetManager snippets;
private BootJavaLanguageServer server;
public BootJavaCompletionEngine(JavaProjectFinder projectFinder, Map<String, CompletionProvider> specificProviders, JavaSnippetManager snippets) {
this.projectFinder = projectFinder;
public BootJavaCompletionEngine(BootJavaLanguageServer server, Map<String, CompletionProvider> specificProviders, JavaSnippetManager snippets) {
this.server = server;
this.completionProviders = specificProviders;
this.snippets = snippets;
}
@Override
public Collection<ICompletionProposal> getCompletions(IDocument document, int offset) throws Exception {
ASTParser parser = ASTParser.newParser(AST.JLS9);
Map<String, String> options = JavaCore.getOptions();
JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
parser.setCompilerOptions(options);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setResolveBindings(true);
public Collection<ICompletionProposal> getCompletions(TextDocument document, int offset) throws Exception {
return server.getCompilationUnitCache().withCompilationUnit(document, cu -> {
if (cu != null) {
ASTNode node = NodeFinder.perform(cu, offset, 0);
String[] classpathEntries = getClasspathEntries(document);
String[] sourceEntries = new String[] {};
parser.setEnvironment(classpathEntries, sourceEntries, null, true);
if (node != null) {
Collection<ICompletionProposal> completions = new ArrayList<ICompletionProposal>();
completions.addAll(collectCompletionsForAnnotations(node, offset, document));
completions.addAll(snippets.getCompletions(document, offset, node, cu));
return completions;
}
}
String docURI = document.getUri();
String unitName = docURI.substring(docURI.lastIndexOf("/"));
parser.setUnitName(unitName);
parser.setSource(document.get(0, document.getLength()).toCharArray());
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
ASTNode node = NodeFinder.perform(cu, offset, 0);
if (node != null) {
Collection<ICompletionProposal> completions = new ArrayList<ICompletionProposal>();
completions.addAll(collectCompletionsForAnnotations(node, offset, document));
completions.addAll(snippets.getCompletions(document, offset, node, cu));
return completions;
}
return Collections.emptyList();
return Collections.emptyList();
});
}
private Collection<ICompletionProposal> collectCompletionsForAnnotations(ASTNode node, int offset, IDocument doc) {
@@ -107,13 +84,4 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
return Collections.emptyList();
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(doc.getUri())).get();
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries().stream();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Pivotal, Inc.
* Copyright (c) 2016, 2018 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
@@ -59,6 +59,7 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
private static final String PROPERTIES = ".properties";
private static final YamlCompletionEngineOptions COMPLETION_OPTIONS = new YamlCompletionEngineOptions() {
@Override
public boolean includeDeindentedProposals() { return false; };
};
// Shared:
@@ -80,14 +81,14 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
public BootPropertiesLanguageServer(LSFactory<BootPropertiesLanguageServerParams> _params) {
super("vscode-boot-properties");
BootPropertiesLanguageServerParams serverParams = _params.create(this);
this.indexProvider = serverParams.indexProvider;
this.typeUtilProvider = serverParams.typeUtilProvider;
this.javaProjectFinder = serverParams.projectFinder;
this.projectObserver = serverParams.projectObserver;
this.completionFactory = new PropertyCompletionFactory(javaProjectFinder);
this.yamlAssistContextProvider = new YamlAssistContextProvider() {
@Override
@@ -114,13 +115,13 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
HoverInfoProvider hoverInfoProvider = getHoverProvider();
hoverEngine = new VscodeHoverEngineAdapter(this, hoverInfoProvider);
documents.onHover(hoverEngine::getHover);
documents.onHover(hoverEngine::getHover);
}
private ICompletionEngine getCompletionEngine() {
ICompletionEngine propertiesCompletions = new SpringPropertiesCompletionEngine(indexProvider, typeUtilProvider, javaProjectFinder);
ICompletionEngine yamlCompletions = new YamlCompletionEngine(yamlStructureProvider, yamlAssistContextProvider, COMPLETION_OPTIONS);
return (IDocument document, int offset) -> {
return (TextDocument document, int offset) -> {
String uri = document.getUri();
if (uri!=null) {
if (uri.endsWith(PROPERTIES)) {
@@ -182,7 +183,7 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
public ProjectObserver getProjectObserver() {
return projectObserver;
}
public SpringPropertyIndexProvider getPropertiesIndexProvider() {
return indexProvider;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc.
* Copyright (c) 2016, 2018 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
@@ -20,7 +20,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.IComplet
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.IDocument;;
import org.springframework.ide.vscode.commons.util.text.TextDocument;;
/**
* @author Kris De Volder
@@ -46,7 +46,8 @@ public class SpringPropertiesCompletionEngine implements ICompletionEngine {
/**
* Create completions proposals in the context of a properties text editor.
*/
public Collection<ICompletionProposal> getCompletions(IDocument doc, int offset) throws BadLocationException {
@Override
public Collection<ICompletionProposal> getCompletions(TextDocument doc, int offset) throws BadLocationException {
return new PropertiesCompletionProposalsCalculator(indexProvider.getIndex(doc),
typeUtilProvider.getTypeUtil(doc), completionFactory, doc, offset, preferLowerCaseEnums).calculate();
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015, 2016 Pivotal, Inc.
* Copyright (c) 2015, 2018 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
@@ -12,13 +12,13 @@ package org.springframework.ide.vscode.commons.languageserver.completion;
import java.util.Collection;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Kris De Volder
*/
public interface ICompletionEngine {
Collection<ICompletionProposal> getCompletions(IDocument document, int offset) throws Exception;
Collection<ICompletionProposal> getCompletions(TextDocument document, int offset) throws Exception;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc.
* Copyright (c) 2016, 2018 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
@@ -31,6 +31,7 @@ import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.Unicodes;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SChildBearingNode;
@@ -79,7 +80,7 @@ public class YamlCompletionEngine implements ICompletionEngine {
}
@Override
public Collection<ICompletionProposal> getCompletions(IDocument _doc, int offset) throws Exception {
public Collection<ICompletionProposal> getCompletions(TextDocument _doc, int offset) throws Exception {
YamlDocument doc = new YamlDocument(_doc, structureProvider);
if (!doc.isCommented(offset)) {
SRootNode root = doc.getStructure();