Unverified Commit 3a750f56 authored by Geertjan Wielenga's avatar Geertjan Wielenga Committed by GitHub
Browse files

Merge pull request #2736 from jlahoda/java-lsp-annotations

Showing completions returned by annotation Processors in VS Code.
parents ac5046d3 0f36a3f2
......@@ -24,7 +24,6 @@ import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LineMap;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.Scope;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
......@@ -61,14 +60,12 @@ import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.swing.text.BadLocationException;
......@@ -339,6 +336,7 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
private static class ItemFactoryImpl implements JavaCompletionTask.ItemFactory<CompletionItem> {
private static final int DEPRECATED = 10;
private final LanguageClient client;
private final String uri;
private final int offset;
......@@ -561,12 +559,26 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
@Override
public CompletionItem createAttributeItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean isDeprecated) {
return null; //TODO: fill
CompletionItem item = new CompletionItem(elem.getSimpleName().toString());
item.setKind(CompletionItemKind.Property);
StringBuilder insertText = new StringBuilder();
insertText.append(elem.getSimpleName());
insertText.append("=");
item.setInsertText(insertText.toString());
item.setInsertTextFormat(InsertTextFormat.PlainText);
int priority = isDeprecated ? 100 + DEPRECATED : 100;
item.setSortText(String.format("%4d%s", priority, elem.getSimpleName().toString()));
setCompletionData(item, elem);
return item;
}
@Override
public CompletionItem createAttributeValueItem(CompilationInfo info, String value, String documentation, TypeElement element, int substitutionOffset, ReferencesCount referencesCount) {
return null; //TODO: fill
CompletionItem item = new CompletionItem(value);
item.setKind(CompletionItemKind.Text);
item.setSortText(value);
item.setDocumentation(documentation);
return item;
}
private static final Object KEY_IMPORT_TEXT_EDITS = new Object();
......
......@@ -35,6 +35,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
......@@ -48,6 +49,7 @@ import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.swing.event.ChangeListener;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
......@@ -112,6 +114,8 @@ import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.LanguageServer;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.api.java.queries.AnnotationProcessingQuery.Result;
import org.netbeans.api.java.queries.AnnotationProcessingQuery.Trigger;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ui.OpenProjects;
......@@ -121,6 +125,7 @@ import org.netbeans.modules.java.source.BootClassPathUtil;
import org.netbeans.modules.parsing.impl.indexing.implspi.CacheFolderProvider;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.netbeans.spi.java.queries.AnnotationProcessingQueryImplementation;
import org.netbeans.spi.project.ProjectFactory;
import org.netbeans.spi.project.ProjectState;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
......@@ -3234,7 +3239,7 @@ public class ServerTest extends NbTestCase {
assertTrue(result.getCapabilities().getFoldingRangeProvider().isRight());
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code)));
List<FoldingRange> folds = server.getTextDocumentService().foldingRange(new FoldingRangeRequestParams(new TextDocumentIdentifier(toURI(src)))).get();
System.err.println("folds=" + folds);
assertEquals(5, folds.size());
assertEquals(0, folds.get(0).getStartLine());
......@@ -3268,6 +3273,34 @@ public class ServerTest extends NbTestCase {
assertEquals("region", folds.get(4).getKind());
}
public void testAnnotationCompletion() throws Exception {
File src = new File(getWorkDir(), "Test.java");
src.getParentFile().mkdirs();
String code = "@java.lang.Supp public class Test { }";
try (Writer w = new FileWriter(src)) {
w.write(code);
}
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new LspClient(), client.getInputStream(), client.getOutputStream());
serverLauncher.startListening();
LanguageServer server = serverLauncher.getRemoteProxy();
InitializeResult result = server.initialize(new InitializeParams()).get();
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code)));
Either<List<CompletionItem>, CompletionList> completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 15))).get();
assertTrue(completion.isRight());
List<String> actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
assertEquals(Arrays.asList("Interface:SuppressWarnings"), actualItems);
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(1);
id.setUri(toURI(src));
server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(new Range(new Position(0, 1), new Position(0, 15)), 14, "SuppressWarnings(v"))));
completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 19))).get();
actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
assertTrue(actualItems.contains("Property:value"));
server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(new Range(new Position(0, 19), new Position(0, 19)), 0, "alue=\"\""))));
completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 25))).get();
actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
assertTrue(actualItems.contains("Text:\"empty-statement\""));
}
interface Validator<T> {
public void validate(T t) throws Exception;
}
......@@ -3353,6 +3386,42 @@ public class ServerTest extends NbTestCase {
}
@ServiceProvider(service=AnnotationProcessingQueryImplementation.class, position=100)
public static final class AnnotationProcessingQueryImpl implements AnnotationProcessingQueryImplementation {
private final Result result = new Result() {
@Override
public Set<? extends Trigger> annotationProcessingEnabled() {
return EnumSet.allOf(Trigger.class);
}
@Override
public Iterable<? extends String> annotationProcessorsToRun() {
return Collections.emptyList();
}
@Override
public URL sourceOutputDirectory() {
return null;
}
@Override
public Map<? extends String, ? extends String> processorOptions() {
return Collections.emptyMap();
}
@Override
public void addChangeListener(ChangeListener l) {
}
@Override
public void removeChangeListener(ChangeListener l) {
}
};
@Override
public Result getAnnotationProcessingOptions(FileObject file) {
return result;
}
}
//tests may run as a project, so that indexing works properly:
@ServiceProvider(service=ProjectFactory.class)
public static class TestProjectFactory implements ProjectFactory {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment