Skip to content

Commit

Permalink
VSCode: Completion for annonymous inner classes improved. (#5981)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbalek authored May 24, 2023
1 parent 788ba1f commit ff991ea
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 22 deletions.
13 changes: 13 additions & 0 deletions ide/api.lsp/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@
<!-- ACTUAL CHANGES BEGIN HERE: -->

<changes>
<change id="Completion_getCommand">
<api name="LSP_API"/>
<summary>Added URL to diagnostic code description</summary>
<version major="1" minor="17"/>
<date day="23" month="5" year="2023"/>
<author login="dbalek"/>
<compatibility binary="compatible" source="compatible" addition="yes" deletion="no"/>
<description>
<a href="@TOP@/org/netbeans/api/lsp/Completion.html#getCommand">Completion.getCommand</a> to get an optional command
that is executed after inserting the completion.
</description>
<class package="org.netbeans.api.lsp" name="Completion"/>
</change>
<change id="DiagnosticURL">
<api name="LSP_API"/>
<summary>Added URL to diagnostic code description</summary>
Expand Down
2 changes: 1 addition & 1 deletion ide/api.lsp/manifest.mf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.api.lsp/1
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/lsp/Bundle.properties
OpenIDE-Module-Specification-Version: 1.16
OpenIDE-Module-Specification-Version: 1.17
AutoUpdate-Show-In-Client: false
20 changes: 16 additions & 4 deletions ide/api.lsp/src/org/netbeans/api/lsp/Completion.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public final class Completion {
CompletionAccessor.setDefault(new CompletionAccessor() {
@Override
public Completion createCompletion(String label, Kind kind, List<Tag> tags, CompletableFuture<String> detail, CompletableFuture<String> documentation,
boolean preselect, String sortText, String filterText, String insertText, TextFormat insertTextFormat, TextEdit textEdit, CompletableFuture<List<TextEdit>> additionalTextEdits,
List<Character> commitCharacters) {
return new Completion(label, kind, tags, detail, documentation, preselect, sortText, filterText, insertText, insertTextFormat, textEdit, additionalTextEdits, commitCharacters);
boolean preselect, String sortText, String filterText, String insertText, TextFormat insertTextFormat, TextEdit textEdit, Command command,
CompletableFuture<List<TextEdit>> additionalTextEdits, List<Character> commitCharacters) {
return new Completion(label, kind, tags, detail, documentation, preselect, sortText, filterText, insertText, insertTextFormat, textEdit, command, additionalTextEdits, commitCharacters);
}
});
}
Expand All @@ -62,12 +62,13 @@ public Completion createCompletion(String label, Kind kind, List<Tag> tags, Comp
private final String insertText;
private final TextFormat insertTextFormat;
private final TextEdit textEdit;
private final Command command;
private final CompletableFuture<List<TextEdit>> additionalTextEdits;
private final List<Character> commitCharacters;

private Completion(String label, Kind kind, List<Tag> tags, CompletableFuture<String> detail, CompletableFuture<String> documentation,
boolean preselect, String sortText, String filterText, String insertText, TextFormat insertTextFormat,
TextEdit textEdit, CompletableFuture<List<TextEdit>> additionalTextEdits, List<Character> commitCharacters) {
TextEdit textEdit, Command command, CompletableFuture<List<TextEdit>> additionalTextEdits, List<Character> commitCharacters) {
this.label = label;
this.kind = kind;
this.tags = tags;
Expand All @@ -79,6 +80,7 @@ private Completion(String label, Kind kind, List<Tag> tags, CompletableFuture<St
this.insertText = insertText;
this.insertTextFormat = insertTextFormat;
this.textEdit = textEdit;
this.command = command;
this.additionalTextEdits = additionalTextEdits;
this.commitCharacters = commitCharacters;
}
Expand Down Expand Up @@ -203,6 +205,16 @@ public TextEdit getTextEdit() {
return textEdit;
}

/**
* An optional command that is executed after inserting this completion.
*
* @since 1.17
*/
@CheckForNull
public Command getCommand() {
return command;
}

/**
* A list of additional text edits that are applied when selecting this
* completion. Edits must not overlap (including the same insert position)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.lsp.Command;
import org.netbeans.api.lsp.Completion;
import org.netbeans.api.lsp.TextEdit;
import org.openide.util.Exceptions;
Expand Down Expand Up @@ -56,5 +57,5 @@ public static void setDefault(@NonNull final CompletionAccessor accessor) {

public abstract Completion createCompletion(String label, Completion.Kind kind, List<Completion.Tag> tags, CompletableFuture<String> detail, CompletableFuture<String> documentation,
boolean preselect, String sortText, String filterText, String insertText, Completion.TextFormat insertTextFormat,
TextEdit textEdit, CompletableFuture<List<TextEdit>> additionalTextEdits, List<Character> commitCharacters);
TextEdit textEdit, Command command, CompletableFuture<List<TextEdit>> additionalTextEdits, List<Character> commitCharacters);
}
14 changes: 13 additions & 1 deletion ide/api.lsp/src/org/netbeans/spi/lsp/CompletionCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.swing.text.Document;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.lsp.Command;
import org.netbeans.api.lsp.Completion;
import org.netbeans.api.lsp.TextEdit;
import org.netbeans.modules.lsp.CompletionAccessor;
Expand Down Expand Up @@ -99,6 +100,7 @@ public static final class Builder {
private String insertText;
private Completion.TextFormat insertTextFormat;
private TextEdit textEdit;
private Command command;
private CompletableFuture<List<TextEdit>> additionalTextEdits;
private List<Character> commitCharacters;

Expand Down Expand Up @@ -273,6 +275,16 @@ public Builder textEdit(@NonNull TextEdit textEdit) {
return this;
}

/**
* An optional command that is executed after inserting this completion.
*
* @since 1.17
*/
@NonNull
public Builder command(@NonNull Command command) {
this.command = command;
return this;
}
/**
* A list of additional text edits that are applied when selecting this
* completion. Edits must not overlap (including the same insert position)
Expand Down Expand Up @@ -334,7 +346,7 @@ public Builder addCommitCharacter(char commitCharacter) {
public Completion build() {
return CompletionAccessor.getDefault().createCompletion(label, kind,
tags, detail, documentation, preselect, sortText, filterText,
insertText, insertTextFormat, textEdit, additionalTextEdits,
insertText, insertTextFormat, textEdit, command, additionalTextEdits,
commitCharacters);
}

Expand Down
2 changes: 1 addition & 1 deletion java/java.editor/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.9</specification-version>
<specification-version>1.17</specification-version>
</run-dependency>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import org.netbeans.api.java.source.ui.ElementHeaders;
import org.netbeans.api.java.source.ui.ElementJavadoc;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.lsp.Command;
import org.netbeans.api.lsp.Completion;
import org.netbeans.api.lsp.TextEdit;
import org.netbeans.modules.java.completion.JavaCompletionTask;
Expand Down Expand Up @@ -607,27 +608,29 @@ public Completion createGetterSetterMethodItem(CompilationInfo info, VariableEle

@Override
public Completion createDefaultConstructorItem(TypeElement elem, int substitutionOffset, boolean smartType) {
Builder builder = CompletionCollector.newBuilder(elem.getSimpleName().toString() + "()")
.kind(Completion.Kind.Constructor)
.sortText(String.format("%04d%s#0", smartType ? 650 : 1650, elem.getSimpleName().toString()));
StringBuilder insertText = new StringBuilder();
insertText.append(elem.getSimpleName());
if (substitutionOffset < offset) {
insertText.append((elem.getSimpleName()));
}
insertText.append(CodeStyle.getDefault(doc).spaceBeforeMethodCallParen() ? " ()" : "()");
boolean asTemplate = false;
if (elem.getModifiers().contains(Modifier.ABSTRACT)) {
try {
if (CodeStyle.getDefault(info.getDocument()).getClassDeclBracePlacement() == CodeStyle.BracePlacement.SAME_LINE) {
insertText.append(" {\n$0}");
} else {
insertText.append("\n{\n$0}");
}
asTemplate = true;
builder.command(new Command("Complete Abstract Methods", "java.complete.abstract.methods"));
} catch (IOException ioe) {
}
builder.insertTextFormat(Completion.TextFormat.Snippet);
} else {
builder.insertTextFormat(Completion.TextFormat.PlainText);
}
return CompletionCollector.newBuilder(elem.getSimpleName().toString() + "()")
.kind(Completion.Kind.Constructor)
.insertText(insertText.toString())
.insertTextFormat(asTemplate ? Completion.TextFormat.Snippet : Completion.TextFormat.PlainText)
.sortText(String.format("%04d%s#0", smartType ? 650 : 1650, elem.getSimpleName().toString()))
.build();
return builder.insertText(insertText.toString()).build();
}

@Override
Expand Down Expand Up @@ -1016,10 +1019,13 @@ private Completion createTypeItem(CompilationInfo info, String prefix, ElementHa
.sortText(String.format("%04d%s#%02d#%s", smartType ? 800 : 1800, elem.getSimpleName().toString(), Utilities.getImportanceLevel(name), pkgName))
.insertText(insertText.toString());
if (asTemplate) {
builder.insertTextFormat(Completion.TextFormat.Snippet);
builder.insertTextFormat(Completion.TextFormat.Snippet);
} else {
builder.insertTextFormat(Completion.TextFormat.Snippet)
.addCommitCharacter('.');
builder.insertTextFormat(Completion.TextFormat.Snippet)
.addCommitCharacter('.');
}
if (insideNew) {
builder.command(new Command("Invoke Completion", "editor.action.triggerSuggest"));
}
if (handle != null) {
builder.documentation(getDocumentation(doc, off, handle));
Expand Down Expand Up @@ -1048,6 +1054,7 @@ private Completion createExecutableItem(CompilationInfo info, ExecutableElement
sortParams.append('(');
int cnt = 0;
boolean asTemplate = false;
Command command = null;
while(it.hasNext() && tIt.hasNext()) {
TypeMirror tm = tIt.next();
if (tm == null) {
Expand Down Expand Up @@ -1094,6 +1101,7 @@ private Completion createExecutableItem(CompilationInfo info, ExecutableElement
} else {
insertText.append("\n{\n$0}");
}
command = new Command("Complete Abstract Methods", "java.complete.abstract.methods");
asTemplate = true;
} catch (IOException ioe) {
}
Expand Down Expand Up @@ -1135,7 +1143,6 @@ private Completion createExecutableItem(CompilationInfo info, ExecutableElement
} else {
builder.insertText(insertText.toString());
}

ElementHandle<ExecutableElement> handle = SUPPORTED_ELEMENT_KINDS.contains(elem.getKind().name()) ? ElementHandle.create(elem) : null;
if (handle != null) {
builder.documentation(getDocumentation(doc, offset, handle));
Expand Down
2 changes: 1 addition & 1 deletion java/java.lsp.server/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.11</specification-version>
<specification-version>1.17</specification-version>
</run-dependency>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.java.lsp.server.protocol;

import com.google.gson.Gson;
import com.google.gson.JsonPrimitive;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.swing.text.Document;
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.editor.document.LineDocument;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
import org.netbeans.modules.java.lsp.server.Utils;
import org.netbeans.modules.parsing.api.ResultIterator;
import org.openide.filesystems.FileObject;
import org.openide.util.lookup.ServiceProvider;

/**
*
* @author Dusan Balek
*/
@ServiceProvider(service = CodeActionsProvider.class, position = 200)
public final class ImplementAllAbstractMethodsAction extends CodeActionsProvider {

private static final String IMPLEMENT_ALL_ABSTRACT_METHODS = "java.implement.all.abstract.methods"; //NOI18N
private final Gson gson = new Gson();

@Override
public List<CodeAction> getCodeActions(ResultIterator resultIterator, CodeActionParams params) throws Exception {
return Collections.emptyList();
}

@Override
public Set<String> getCommands() {
return Collections.singleton(IMPLEMENT_ALL_ABSTRACT_METHODS);
}

@Override
public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
CompletableFuture<Object> future = new CompletableFuture<>();
try {
if (arguments.size() >= 2) {
String uri = ((JsonPrimitive) arguments.get(0)).getAsString();
FileObject file = Utils.fromUri(uri);
JavaSource js = JavaSource.forFileObject(file);
if (js == null) {
throw new IOException("Cannot get JavaSource for: " + uri);
}
Position position = gson.fromJson(gson.toJson(arguments.get(1)), Position.class);
List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
wc.toPhase(JavaSource.Phase.RESOLVED);
Document doc = wc.getSnapshot().getSource().getDocument(true);
if (doc instanceof LineDocument) {
int offset = Utils.getOffset((LineDocument) doc, position);
GeneratorUtils.generateAllAbstractMethodImplementations(wc, wc.getTreeUtilities().pathFor(offset));
}
});
client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
future.complete(true);
} else {
throw new IllegalArgumentException(String.format("Illegal number of arguments received for command: %s", command));
}
} catch (IOException | IllegalArgumentException ex) {
future.completeExceptionally(ex);
}
return future;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completio
if (edit != null) {
item.setTextEdit(Either.forLeft(new TextEdit(new Range(Utils.createPosition(file, edit.getStartOffset()), Utils.createPosition(file, edit.getEndOffset())), edit.getNewText())));
}
org.netbeans.api.lsp.Command command = completion.getCommand();
if (command != null) {
item.setCommand(new Command(command.getTitle(), command.getCommand(), command.getArguments()));
}
if (completion.getAdditionalTextEdits() != null && completion.getAdditionalTextEdits().isDone()) {
List<org.netbeans.api.lsp.TextEdit> additionalTextEdits = completion.getAdditionalTextEdits().getNow(null);
if (additionalTextEdits != null && !additionalTextEdits.isEmpty()) {
Expand Down
7 changes: 7 additions & 0 deletions java/java.lsp.server/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,13 @@ export function activate(context: ExtensionContext): VSNetBeansAPI {
}
}
}));
context.subscriptions.push(commands.registerCommand('java.complete.abstract.methods', async () => {
const active = vscode.window.activeTextEditor;
if (active) {
const position = new vscode.Position(active.selection.start.line, active.selection.start.character);
await commands.executeCommand('java.implement.all.abstract.methods', active.document.uri.toString(), position);
}
}));
context.subscriptions.push(commands.registerCommand('nbls.startup.condition', async () => {
return client;
}));
Expand Down

0 comments on commit ff991ea

Please sign in to comment.