You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2021/11/15 10:31:46 UTC
[netbeans] branch master updated: LSP: Organize imports action added. (#3317)
This is an automated email from the ASF dual-hosted git repository.
dbalek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 4a4528e LSP: Organize imports action added. (#3317)
4a4528e is described below
commit 4a4528e5089acd6a74157964ef1067b2f508fcae
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Mon Nov 15 11:31:20 2021 +0100
LSP: Organize imports action added. (#3317)
---
.../ChangeMethodParametersRefactoring.java | 2 +-
.../lsp/server/protocol/CodeActionsProvider.java | 35 ++-
.../lsp/server/protocol/ConstructorGenerator.java | 103 ++++++---
.../server/protocol/DelegateMethodGenerator.java | 202 +++++++++--------
.../server/protocol/EqualsHashCodeGenerator.java | 87 ++++----
.../ExtractSuperclassOrInterfaceRefactoring.java | 4 +-
.../lsp/server/protocol/GetterSetterGenerator.java | 135 ++++++-----
.../protocol/ImplementOverrideMethodGenerator.java | 118 +++++-----
.../java/lsp/server/protocol/LoggerGenerator.java | 50 +++--
.../java/lsp/server/protocol/MoveRefactoring.java | 4 +-
.../server/protocol/OrganizeImportsCodeAction.java | 87 ++++++++
.../lsp/server/protocol/PullUpRefactoring.java | 2 +-
.../lsp/server/protocol/PushDownRefactoring.java | 2 +-
.../modules/java/lsp/server/protocol/Server.java | 40 +++-
.../java/lsp/server/protocol/SurroundWithHint.java | 14 +-
.../server/protocol/TextDocumentServiceImpl.java | 45 +++-
.../lsp/server/protocol/ToStringGenerator.java | 106 ++++-----
.../lsp/server/protocol/WorkspaceServiceImpl.java | 21 +-
.../java/lsp/server/protocol/ServerTest.java | 246 +++++++++++++--------
java/java.lsp.server/vscode/package.json | 28 +++
java/java.lsp.server/vscode/src/extension.ts | 2 +-
21 files changed, 857 insertions(+), 476 deletions(-)
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ChangeMethodParametersRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ChangeMethodParametersRefactoring.java
index 849b4b6..157fdce 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ChangeMethodParametersRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ChangeMethodParametersRefactoring.java
@@ -108,7 +108,7 @@ public final class ChangeMethodParametersRefactoring extends CodeRefactoring {
}
QuickPickItem elementItem = new QuickPickItem(createLabel(info, element, true));
elementItem.setUserData(new ElementData(element));
- return Collections.singletonList(createCodeAction(Bundle.DN_ChangeMethodParams(), CHANGE_METHOD_PARAMS_REFACTORING_KIND, CHANGE_METHOD_PARAMS_REFACTORING_COMMAND, Utils.toUri(elementSource), elementItem));
+ return Collections.singletonList(createCodeAction(Bundle.DN_ChangeMethodParams(), CHANGE_METHOD_PARAMS_REFACTORING_KIND, null, CHANGE_METHOD_PARAMS_REFACTORING_COMMAND, Utils.toUri(elementSource), elementItem));
}
@Override
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider.java
index db57677..5ea0ec7 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider.java
@@ -20,7 +20,10 @@ package org.netbeans.modules.java.lsp.server.protocol;
import com.sun.source.tree.LineMap;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -47,26 +50,44 @@ import org.netbeans.modules.parsing.api.ResultIterator;
public abstract class CodeActionsProvider {
public static final String CODE_GENERATOR_KIND = "source.generate";
+ public static final String CODE_ACTIONS_PROVIDER_CLASS = "providerClass";
+ public static final String DATA = "data";
protected static final String ERROR = "<error>"; //NOI18N
public abstract List<CodeAction> getCodeActions(ResultIterator resultIterator, CodeActionParams params) throws Exception;
- public abstract Set<String> getCommands();
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ return CompletableFuture.completedFuture(codeAction);
+ }
- public abstract CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments);
+ public Set<String> getCommands() {
+ return Collections.emptySet();
+ }
- protected static int getOffset(CompilationInfo info, Position pos) {
- LineMap lm = info.getCompilationUnit().getLineMap();
- return (int) lm.getPosition(pos.getLine() + 1, pos.getCharacter() + 1);
+ public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
+ return CompletableFuture.completedFuture(false);
}
- protected static CodeAction createCodeAction(String name, String kind, String command, Object... args) {
+ protected CodeAction createCodeAction(String name, String kind, Object data, String command, Object... commandArgs) {
CodeAction action = new CodeAction(name);
action.setKind(kind);
- action.setCommand(new Command(name, command, Arrays.asList(args)));
+ if (command != null) {
+ action.setCommand(new Command(name, command, Arrays.asList(commandArgs)));
+ }
+ if (data != null) {
+ Map<String, Object> map = new HashMap<>();
+ map.put(CODE_ACTIONS_PROVIDER_CLASS, getClass().getName());
+ map.put(DATA, data);
+ action.setData(map);
+ }
return action;
}
+ protected static int getOffset(CompilationInfo info, Position pos) {
+ LineMap lm = info.getCompilationUnit().getLineMap();
+ return (int) lm.getPosition(pos.getLine() + 1, pos.getCharacter() + 1);
+ }
+
protected static String createLabel(CompilationInfo info, Element e) {
return createLabel(info, e, false);
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ConstructorGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ConstructorGenerator.java
index 7086bdd..1528927 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ConstructorGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ConstructorGenerator.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
@@ -26,8 +28,10 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@@ -43,7 +47,6 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
@@ -68,9 +71,11 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 10)
public final class ConstructorGenerator extends CodeActionsProvider {
- public static final String GENERATE_CONSTRUCTOR = "java.generate.constructor";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String CONSTRUCTORS = "constructors";
+ private static final String FIELDS = "fields";
- private final Set<String> commands = Collections.singleton(GENERATE_CONSTRUCTOR);
private final Gson gson = new Gson();
public ConstructorGenerator() {
@@ -169,62 +174,101 @@ public final class ConstructorGenerator extends CodeActionsProvider {
return Collections.emptyList();
}
String uri = Utils.toUri(info.getFileObject());
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateConstructor(), isSource ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, GENERATE_CONSTRUCTOR, uri, startOffset, constructors, fields));
- }
-
- @Override
- public Set<String> getCommands() {
- return commands;
+ Map<String, Object> data = new HashMap<>();
+ data.put(URI, uri);
+ data.put(OFFSET, startOffset);
+ data.put(CONSTRUCTORS, constructors);
+ data.put(FIELDS, fields);
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateConstructor(), isSource ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, data, null));
}
@Override
@NbBundle.Messages({
"DN_SelectSuperConstructor=Select super constructor",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 3) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- List<QuickPickItem> constructors = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(2)), QuickPickItem[].class));
- List<QuickPickItem> fields = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(3)), QuickPickItem[].class));
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ List<QuickPickItem> constructors = Arrays.asList(gson.fromJson(gson.toJson(((JsonObject) data).get(CONSTRUCTORS)), QuickPickItem[].class));
+ List<QuickPickItem> fields = Arrays.asList(gson.fromJson(((JsonObject) data).get(FIELDS), QuickPickItem[].class));
if (constructors.size() < 2 && fields.isEmpty()) {
- generate(client, uri, offset, constructors, fields);
+ WorkspaceEdit edit = generate(client, uri, offset, constructors, fields);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
} else {
if (constructors.size() > 1) {
client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectSuperConstructor(), true, constructors)).thenAccept(selected -> {
- if (selected != null) {
- selectFields(client, uri, offset, selected, fields);
+ try {
+ if (selected != null) {
+ selectFields(client, uri, offset, selected, fields).handle((edit, ex) -> {
+ if (ex != null) {
+ future.completeExceptionally(ex);
+ } else {
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
+ }
+ return null;
+ });
+ } else {
+ future.complete(codeAction);
+ }
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
} else {
- selectFields(client, uri, offset, constructors, fields);
+ selectFields(client, uri, offset, constructors, fields).handle((edit, ex) -> {
+ if (ex != null) {
+ future.completeExceptionally(ex);
+ } else {
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
+ }
+ return null;
+ });
}
}
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch (JsonSyntaxException | IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
@NbBundle.Messages({
"DN_SelectConstructorFields=Select fields to be initialized by constructor",
})
- private void selectFields(NbCodeLanguageClient client, String uri, int offset, List<QuickPickItem> constructors, List<QuickPickItem> fields) {
+ private CompletableFuture<WorkspaceEdit> selectFields(NbCodeLanguageClient client, String uri, int offset, List<QuickPickItem> constructors, List<QuickPickItem> fields) throws IOException, IllegalArgumentException {
+ CompletableFuture<WorkspaceEdit> future = new CompletableFuture<>();
if (!fields.isEmpty()) {
client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectConstructorFields(), true, fields)).thenAccept(selected -> {
- if (selected != null) {
- generate(client, uri, offset, constructors, selected);
+ try {
+ if (selected != null) {
+ future.complete(generate(client, uri, offset, constructors, selected));
+ } else {
+ future.complete(null);
+ }
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
} else {
- generate(client, uri, offset, constructors, fields);
+ future.complete(generate(client, uri, offset, constructors, fields));
}
+ return future;
}
@NbBundle.Messages({
"DN_ConstructorAlreadyExists=Given constructor already exists",
})
- private void generate(NbCodeLanguageClient client, String uri, int offset, List<QuickPickItem> constructors, List<QuickPickItem> fields) {
+ private WorkspaceEdit generate(NbCodeLanguageClient client, String uri, int offset, List<QuickPickItem> constructors, List<QuickPickItem> fields) throws IOException, IllegalArgumentException {
try {
FileObject file = Utils.fromUri(uri);
JavaSource js = JavaSource.forFileObject(file);
@@ -247,11 +291,10 @@ public final class ConstructorGenerator extends CodeActionsProvider {
GeneratorUtils.generateConstructors(wc, tp, selectedFields, selectedConstructors, -1);
}
});
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
+ return edits.isEmpty() ? null : new WorkspaceEdit(Collections.singletonMap(uri, edits));
} catch (GeneratorUtils.DuplicateMemberException dme) {
client.showMessage(new MessageParams(MessageType.Info, Bundle.DN_ConstructorAlreadyExists()));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
}
+ return null;
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DelegateMethodGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DelegateMethodGenerator.java
index 6f605b1..9673e31 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DelegateMethodGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/DelegateMethodGenerator.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.Scope;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
@@ -26,8 +28,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
@@ -41,12 +44,9 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.java.source.CompilationController;
@@ -66,14 +66,13 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 60)
public final class DelegateMethodGenerator extends CodeActionsProvider {
- public static final String GENERATE_DELEGATE_METHOD = "java.generate.delegateMethod";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String TYPE = "type";
+ private static final String FIELDS = "fields";
- private final Set<String> commands = Collections.singleton(GENERATE_DELEGATE_METHOD);
private final Gson gson = new Gson();
- public DelegateMethodGenerator() {
- }
-
@Override
@NbBundle.Messages({
"DN_GenerateDelegateMethod=Generate Delegate Method...",
@@ -122,108 +121,137 @@ public final class DelegateMethodGenerator extends CodeActionsProvider {
String uri = Utils.toUri(info.getFileObject());
QuickPickItem typeItem = new QuickPickItem(createLabel(info, typeElement));
typeItem.setUserData(new ElementData(typeElement));
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateDelegateMethod(), CODE_GENERATOR_KIND, GENERATE_DELEGATE_METHOD, uri, offset, typeItem, fields));
- }
-
- @Override
- public Set<String> getCommands() {
- return commands;
+ Map<String, Object> data = new HashMap<>();
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ data.put(TYPE, typeItem);
+ data.put(FIELDS, fields);
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateDelegateMethod(), CODE_GENERATOR_KIND, data, null));
}
@Override
@NbBundle.Messages({
"DN_SelectDelegateMethodField=Select target field to generate delegates for",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 3) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- QuickPickItem type = gson.fromJson(gson.toJson(arguments.get(2)), QuickPickItem.class);
- List<QuickPickItem> fields = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(3)), QuickPickItem[].class));
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ QuickPickItem type = gson.fromJson(gson.toJson(((JsonObject) data).get(TYPE)), QuickPickItem.class);
+ List<QuickPickItem> fields = Arrays.asList(gson.fromJson(((JsonObject) data).get(FIELDS), QuickPickItem[].class));
if (fields.size() == 1) {
- selectMethods(client, uri, offset, type, fields.get(0));
+ selectMethods(client, uri, offset, type, fields.get(0)).handle((edit, ex) -> {
+ if (ex != null) {
+ future.completeExceptionally(ex);
+ } else {
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
+ }
+ return null;
+ });
} else {
client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectDelegateMethodField(), false, fields)).thenAccept(selected -> {
- if (selected != null && !selected.isEmpty()) {
- selectMethods(client, uri, offset, type, selected.get(0));
+ try {
+ if (selected != null && !selected.isEmpty()) {
+ selectMethods(client, uri, offset, type, selected.get(0)).handle((edit, ex) -> {
+ if (ex != null) {
+ future.completeExceptionally(ex);
+ } else {
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
+ }
+ return null;
+ });
+ } else {
+ future.complete(codeAction);
+ }
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
}
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch (JsonSyntaxException | IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
@NbBundle.Messages({
"DN_SelectDelegateMethods=Select methods to generate delegates for",
})
- private void selectMethods(NbCodeLanguageClient client, String uri, int offset, QuickPickItem type, QuickPickItem selectedField) {
- try {
- FileObject file = Utils.fromUri(uri);
- JavaSource js = JavaSource.forFileObject(file);
- if (js == null) {
- throw new IOException("Cannot get JavaSource for: " + uri);
- }
- js.runUserActionTask(info -> {
- info.toPhase(JavaSource.Phase.RESOLVED);
- TypeElement origin = (TypeElement) gson.fromJson(gson.toJson(type.getUserData()), ElementData.class).resolve(info);
- VariableElement field = (VariableElement) gson.fromJson(gson.toJson(selectedField.getUserData()), ElementData.class).resolve(info);
- if (origin != null && field != null) {
- final ElementUtilities eu = info.getElementUtilities();
- final Trees trees = info.getTrees();
- final Scope scope = info.getTreeUtilities().scopeFor(offset);
- ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
- @Override
- public boolean accept(Element e, TypeMirror type) {
- if (e.getKind() == ElementKind.METHOD && trees.isAccessible(scope, e, (DeclaredType)type)) {
- Element impl = eu.getImplementationOf((ExecutableElement)e, origin);
- return impl == null || (!impl.getModifiers().contains(Modifier.FINAL) && impl.getEnclosingElement() != origin);
- }
- return false;
+ private CompletableFuture<WorkspaceEdit> selectMethods(NbCodeLanguageClient client, String uri, int offset, QuickPickItem type, QuickPickItem selectedField) throws IOException, IllegalArgumentException {
+ CompletableFuture<WorkspaceEdit> future = new CompletableFuture<>();
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
+ }
+ js.runUserActionTask(info -> {
+ info.toPhase(JavaSource.Phase.RESOLVED);
+ TypeElement origin = (TypeElement) gson.fromJson(gson.toJson(type.getUserData()), ElementData.class).resolve(info);
+ VariableElement field = (VariableElement) gson.fromJson(gson.toJson(selectedField.getUserData()), ElementData.class).resolve(info);
+ if (origin != null && field != null) {
+ final ElementUtilities eu = info.getElementUtilities();
+ final Trees trees = info.getTrees();
+ final Scope scope = info.getTreeUtilities().scopeFor(offset);
+ ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
+ @Override
+ public boolean accept(Element e, TypeMirror type) {
+ if (e.getKind() == ElementKind.METHOD && trees.isAccessible(scope, e, (DeclaredType)type)) {
+ Element impl = eu.getImplementationOf((ExecutableElement)e, origin);
+ return impl == null || (!impl.getModifiers().contains(Modifier.FINAL) && impl.getEnclosingElement() != origin);
}
- };
- List<QuickPickItem> methods = new ArrayList<>();
- for (ExecutableElement method : ElementFilter.methodsIn(eu.getMembers(field.asType(), acceptor))) {
- QuickPickItem item = new QuickPickItem(String.format("%s.%s", field.getSimpleName().toString(), createLabel(info, method)));
- item.setUserData(new ElementData(method));
- methods.add(item);
+ return false;
}
- client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectDelegateMethods(), true, methods)).thenAccept(selected -> {
+ };
+ List<QuickPickItem> methods = new ArrayList<>();
+ for (ExecutableElement method : ElementFilter.methodsIn(eu.getMembers(field.asType(), acceptor))) {
+ QuickPickItem item = new QuickPickItem(String.format("%s.%s", field.getSimpleName().toString(), createLabel(info, method)));
+ item.setUserData(new ElementData(method));
+ methods.add(item);
+ }
+ client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectDelegateMethods(), true, methods)).thenAccept(selected -> {
+ try {
if (selected != null && !selected.isEmpty()) {
- generate(client, uri, offset, selectedField, selected);
+ future.complete(generate(uri, offset, selectedField, selected));
+ } else {
+ future.complete(null);
}
- });
- }
- }, true);
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
- }
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
+ }
+ });
+ } else {
+ future.complete(null);
+ }
+ }, true);
+ return future;
}
- private void generate(NbCodeLanguageClient client, String uri, int offset, QuickPickItem selectedField, List<QuickPickItem> selectedMethods) {
- try {
- FileObject file = Utils.fromUri(uri);
- JavaSource js = JavaSource.forFileObject(file);
- if (js == null) {
- throw new IOException("Cannot get JavaSource for: " + uri);
- }
- List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
- wc.toPhase(JavaSource.Phase.RESOLVED);
- TreePath tp = wc.getTreeUtilities().pathFor(offset);
- tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
- if (tp != null) {
- VariableElement field = (VariableElement) gson.fromJson(gson.toJson(selectedField.getUserData()), ElementData.class).resolve(wc);
- List<ExecutableElement> methods = selectedMethods.stream().map(item -> {
- ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
- return (ExecutableElement)data.resolve(wc);
- }).collect(Collectors.toList());
- org.netbeans.modules.java.editor.codegen.DelegateMethodGenerator.generateDelegatingMethods(wc, tp, field, methods, -1);
- }
- });
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ private WorkspaceEdit generate(String uri, int offset, QuickPickItem selectedField, List<QuickPickItem> selectedMethods) throws IOException, IllegalArgumentException {
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
}
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ TreePath tp = wc.getTreeUtilities().pathFor(offset);
+ tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
+ if (tp != null) {
+ VariableElement field = (VariableElement) gson.fromJson(gson.toJson(selectedField.getUserData()), ElementData.class).resolve(wc);
+ List<ExecutableElement> methods = selectedMethods.stream().map(item -> {
+ ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
+ return (ExecutableElement)data.resolve(wc);
+ }).collect(Collectors.toList());
+ org.netbeans.modules.java.editor.codegen.DelegateMethodGenerator.generateDelegatingMethods(wc, tp, field, methods, -1);
+ }
+ });
+ return edits.isEmpty() ? null : new WorkspaceEdit(Collections.singletonMap(uri, edits));
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/EqualsHashCodeGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/EqualsHashCodeGenerator.java
index 67a981b..2554aa2 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/EqualsHashCodeGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/EqualsHashCodeGenerator.java
@@ -19,15 +19,17 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.lang.model.element.ElementKind;
@@ -36,12 +38,9 @@ import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.java.source.CompilationController;
@@ -59,16 +58,15 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 40)
public final class EqualsHashCodeGenerator extends CodeActionsProvider {
- public static final String GENERATE_EQUALS = "java.generate.equals";
- public static final String GENERATE_HASH_CODE = "java.generate.hashCode";
- public static final String GENERATE_EQUALS_HASH_CODE = "java.generate.equals.hashCode";
+ private static final String KIND = "kind";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String FIELDS = "fields";
+ private static final int EQUALS_ONLY = 1;
+ private static final int HASH_CODE_ONLY = 2;
- private final Set<String> commands = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(GENERATE_EQUALS_HASH_CODE, GENERATE_EQUALS, GENERATE_HASH_CODE)));
private final Gson gson = new Gson();
- public EqualsHashCodeGenerator() {
- }
-
@Override
@NbBundle.Messages({
"DN_GenerateEquals=Generate equals()...",
@@ -113,16 +111,11 @@ public final class EqualsHashCodeGenerator extends CodeActionsProvider {
String uri = Utils.toUri(info.getFileObject());
if (equalsHashCode[0] == null) {
if (equalsHashCode[1] == null) {
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateEqualsHashCode(), CODE_GENERATOR_KIND, GENERATE_EQUALS_HASH_CODE, uri, offset, fields));
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateEqualsHashCode(), CODE_GENERATOR_KIND, data(0, uri, offset, fields), null));
}
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateEquals(), CODE_GENERATOR_KIND, GENERATE_EQUALS, uri, offset, fields));
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateEquals(), CODE_GENERATOR_KIND, data(EQUALS_ONLY, uri, offset, fields), null));
}
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateHashCode(), CODE_GENERATOR_KIND, GENERATE_HASH_CODE, uri, offset, fields));
- }
-
- @Override
- public Set<String> getCommands() {
- return commands;
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateHashCode(), CODE_GENERATOR_KIND, data(HASH_CODE_ONLY, uri, offset, fields), null));
}
@Override
@@ -131,22 +124,24 @@ public final class EqualsHashCodeGenerator extends CodeActionsProvider {
"DN_SelectHashCode=Select fields to be included in hashCode()",
"DN_SelectEqualsHashCode=Select fields to be included in equals() and hashCode()",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 2) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- List<QuickPickItem> fields = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(2)), QuickPickItem[].class));
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ int kind = ((JsonObject) data).getAsJsonPrimitive(KIND).getAsInt();
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ List<QuickPickItem> fields = Arrays.asList(gson.fromJson(((JsonObject) data).get(FIELDS), QuickPickItem[].class));
String text;
- boolean generateEquals = !GENERATE_HASH_CODE.equals(command);
- boolean generateHashCode = !GENERATE_EQUALS.equals(command);
- switch (command) {
- case GENERATE_EQUALS: text = Bundle.DN_SelectEquals(); break;
- case GENERATE_HASH_CODE: text = Bundle.DN_SelectHashCode(); break;
+ boolean generateEquals = HASH_CODE_ONLY != kind;
+ boolean generateHashCode = EQUALS_ONLY != kind;
+ switch (kind) {
+ case EQUALS_ONLY: text = Bundle.DN_SelectEquals(); break;
+ case HASH_CODE_ONLY: text = Bundle.DN_SelectHashCode(); break;
default: text = Bundle.DN_SelectEqualsHashCode(); break;
}
client.showQuickPick(new ShowQuickPickParams(text, true, fields)).thenAccept(selected -> {
- if (selected != null) {
- try {
+ try {
+ if (selected != null) {
FileObject file = Utils.fromUri(uri);
JavaSource js = JavaSource.forFileObject(file);
if (js == null) {
@@ -158,21 +153,33 @@ public final class EqualsHashCodeGenerator extends CodeActionsProvider {
tp = wc.getTreeUtilities().getPathElementOfKind(Tree.Kind.CLASS, tp);
if (tp != null) {
List<VariableElement> selectedFields = selected.stream().map(item -> {
- ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
- return (VariableElement)data.resolve(wc);
+ ElementData userData = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
+ return (VariableElement) userData.resolve(wc);
}).collect(Collectors.toList());
org.netbeans.modules.java.editor.codegen.EqualsHashCodeGenerator.generateEqualsAndHashCode(wc, tp, generateEquals ? selectedFields : null, generateHashCode ? selectedFields : null, -1);
}
});
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ if (!edits.isEmpty()) {
+ codeAction.setEdit(new WorkspaceEdit(Collections.singletonMap(uri, edits)));
+ }
}
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch(JsonSyntaxException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
+ }
+
+ private static Map<String, Object> data(int kind, String uri, int offset, List<QuickPickItem> fields) {
+ Map<String, Object> data = new HashMap<>();
+ data.put(KIND, kind);
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ data.put(FIELDS, fields);
+ return data;
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ExtractSuperclassOrInterfaceRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ExtractSuperclassOrInterfaceRefactoring.java
index 87d4807..e1e09ec 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ExtractSuperclassOrInterfaceRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ExtractSuperclassOrInterfaceRefactoring.java
@@ -146,10 +146,10 @@ public final class ExtractSuperclassOrInterfaceRefactoring extends CodeRefactori
QuickPickItem elementItem = new QuickPickItem(createLabel(info, type));
elementItem.setUserData(new ElementData(type));
if (!type.getKind().isInterface()) {
- result.add(createCodeAction(Bundle.DN_ExtractSuperclass(), CodeActionKind.RefactorExtract, EXTRACT_SUPERCLASS_REFACTORING_COMMAND, uri, elementItem, allMembers));
+ result.add(createCodeAction(Bundle.DN_ExtractSuperclass(), CodeActionKind.RefactorExtract, null, EXTRACT_SUPERCLASS_REFACTORING_COMMAND, uri, elementItem, allMembers));
}
if (!members.isEmpty()) {
- result.add(createCodeAction(Bundle.DN_ExtractInterface(), CodeActionKind.RefactorExtract, EXTRACT_INTERFACE_REFACTORING_COMMAND, uri, elementItem, members));
+ result.add(createCodeAction(Bundle.DN_ExtractInterface(), CodeActionKind.RefactorExtract, null, EXTRACT_INTERFACE_REFACTORING_COMMAND, uri, elementItem, members));
}
}
return result;
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/GetterSetterGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/GetterSetterGenerator.java
index 9841873..c4e3928 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/GetterSetterGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/GetterSetterGenerator.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
@@ -26,9 +28,11 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@@ -36,12 +40,9 @@ import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
@@ -66,16 +67,14 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 30)
public final class GetterSetterGenerator extends CodeActionsProvider {
- public static final String GENERATE_GETTERS = "java.generate.getters";
- public static final String GENERATE_SETTERS = "java.generate.setters";
- public static final String GENERATE_GETTERS_SETTERS = "java.generate.getters.setters";
+ private static final String KIND = "kind";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String ALL = "all";
+ private static final String FIELDS = "fields";
- private final Set<String> commands = Collections.unmodifiableSet(new HashSet(Arrays.asList(GENERATE_GETTERS, GENERATE_SETTERS, GENERATE_GETTERS_SETTERS)));
private final Gson gson = new Gson();
- public GetterSetterGenerator() {
- }
-
@Override
@NbBundle.Messages({
"DN_GenerateGetters=Generate Getters...",
@@ -101,94 +100,98 @@ public final class GetterSetterGenerator extends CodeActionsProvider {
List<CodeAction> result = new ArrayList<>();
if (missingGetters) {
String name = pair.first().size() == 1 ? Bundle.DN_GenerateGetterFor(pair.first().iterator().next().getSimpleName().toString()) : Bundle.DN_GenerateGetters();
- result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, GENERATE_GETTERS, uri, offset, all, pair.first().stream().map(variableElement -> {
+ result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, data(GeneratorUtils.GETTERS_ONLY, uri, offset, all, pair.first().stream().map(variableElement -> {
QuickPickItem item = new QuickPickItem(createLabel(info, variableElement));
item.setUserData(new ElementData(variableElement));
return item;
- }).collect(Collectors.toList())));
+ }).collect(Collectors.toList())), null));
}
if (missingSetters) {
String name = pair.second().size() == 1 ? Bundle.DN_GenerateSetterFor(pair.second().iterator().next().getSimpleName().toString()) : Bundle.DN_GenerateSetters();
- result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, GENERATE_SETTERS, uri, offset, all, pair.second().stream().map(variableElement -> {
+ result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, data(GeneratorUtils.SETTERS_ONLY, uri, offset, all, pair.second().stream().map(variableElement -> {
QuickPickItem item = new QuickPickItem(createLabel(info, variableElement));
item.setUserData(new ElementData(variableElement));
return item;
- }).collect(Collectors.toList())));
+ }).collect(Collectors.toList())), null));
}
if (missingGetters && missingSetters) {
pair.first().retainAll(pair.second());
String name = pair.first().size() == 1 ? Bundle.DN_GenerateGetterSetterFor(pair.first().iterator().next().getSimpleName().toString()) : Bundle.DN_GenerateGettersSetters();
- result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, GENERATE_GETTERS_SETTERS, uri, offset, all, pair.first().stream().map(variableElement -> {
+ result.add(createCodeAction(name, all ? CODE_GENERATOR_KIND : CodeActionKind.QuickFix, data(0, uri, offset, all, pair.first().stream().map(variableElement -> {
QuickPickItem item = new QuickPickItem(createLabel(info, variableElement));
item.setUserData(new ElementData(variableElement));
return item;
- }).collect(Collectors.toList())));
+ }).collect(Collectors.toList())), null));
}
return result;
}
@Override
- public Set<String> getCommands() {
- return commands;
- }
-
- @Override
@NbBundle.Messages({
"DN_SelectGetters=Select fields to generate getters for",
"DN_SelectSetters=Select fields to generate setters for",
"DN_SelectGettersSetters=Select fields to generate getters and setters for",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 3) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- boolean all = gson.fromJson(gson.toJson(arguments.get(2)), boolean.class);
- List<QuickPickItem> fields = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(3)), QuickPickItem[].class));
- int kind;
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ int kind = ((JsonObject) data).getAsJsonPrimitive(KIND).getAsInt();
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ boolean all = ((JsonObject) data).getAsJsonPrimitive(ALL).getAsBoolean();
+ List<QuickPickItem> fields = Arrays.asList(gson.fromJson(((JsonObject) data).get(FIELDS), QuickPickItem[].class));
String text;
- switch (command) {
- case GENERATE_GETTERS: kind = GeneratorUtils.GETTERS_ONLY; text = Bundle.DN_SelectGetters(); break;
- case GENERATE_SETTERS: kind = GeneratorUtils.SETTERS_ONLY; text = Bundle.DN_SelectSetters(); break;
- default: kind = 0; text = Bundle.DN_SelectGettersSetters(); break;
+ switch (kind) {
+ case GeneratorUtils.GETTERS_ONLY: text = Bundle.DN_SelectGetters(); break;
+ case GeneratorUtils.SETTERS_ONLY: text = Bundle.DN_SelectSetters(); break;
+ default: text = Bundle.DN_SelectGettersSetters(); break;
}
if (all && fields.size() > 1) {
client.showQuickPick(new ShowQuickPickParams(text, true, fields)).thenAccept(selected -> {
- if (selected != null && !selected.isEmpty()) {
- generate(client, kind, uri, offset, selected);
+ try {
+ if (selected != null && !selected.isEmpty()) {
+ WorkspaceEdit edit = generate(kind, uri, offset, selected);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ }
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
- } else if (fields.size() == 1) {
- generate(client, kind, uri, offset, fields);
+ } else {
+ WorkspaceEdit edit = generate(kind, uri, offset, fields);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
}
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch(JsonSyntaxException | IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
- private void generate(NbCodeLanguageClient client, int kind, String uri, int offset, List<QuickPickItem> fields) throws IllegalArgumentException {
- try {
- FileObject file = Utils.fromUri(uri);
- JavaSource js = JavaSource.forFileObject(file);
- if (js == null) {
- throw new IOException("Cannot get JavaSource for: " + uri);
- }
- List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
- wc.toPhase(JavaSource.Phase.RESOLVED);
- TreePath tp = wc.getTreeUtilities().pathFor(offset);
- tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
- if (tp != null) {
- List<VariableElement> variableElements = fields.stream().map(item -> {
- ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
- return (VariableElement) data.resolve(wc);
- }).collect(Collectors.toList());
- GeneratorUtils.generateGettersAndSetters(wc, tp, variableElements, kind, -1);
- }
- });
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ private WorkspaceEdit generate(int kind, String uri, int offset, List<QuickPickItem> fields) throws IOException, IllegalArgumentException {
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
}
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ TreePath tp = wc.getTreeUtilities().pathFor(offset);
+ tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
+ if (tp != null) {
+ List<VariableElement> variableElements = fields.stream().map(item -> {
+ ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
+ return (VariableElement) data.resolve(wc);
+ }).collect(Collectors.toList());
+ GeneratorUtils.generateGettersAndSetters(wc, tp, variableElements, kind, -1);
+ }
+ });
+ return edits.isEmpty() ? null : new WorkspaceEdit(Collections.singletonMap(uri, edits));
}
private static Pair<Set<VariableElement>, Set<VariableElement>> findMissingGettersSetters(CompilationInfo info, Range range, boolean all) {
@@ -254,4 +257,14 @@ public final class GetterSetterGenerator extends CodeActionsProvider {
return Pair.of(missingGetters, missingSetters);
}
+
+ private static Map<String, Object> data(int kind, String uri, int offset, boolean all, List<QuickPickItem> fields) {
+ Map<String, Object> data = new HashMap<>();
+ data.put(KIND, kind);
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ data.put(ALL, all);
+ data.put(FIELDS, fields);
+ return data;
+ }
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ImplementOverrideMethodGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ImplementOverrideMethodGenerator.java
index 59d0c83..8a398f4 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ImplementOverrideMethodGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ImplementOverrideMethodGenerator.java
@@ -19,14 +19,16 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.util.TreePath;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.lang.model.SourceVersion;
@@ -35,12 +37,9 @@ 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 org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.java.source.CompilationController;
@@ -61,15 +60,13 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 70)
public final class ImplementOverrideMethodGenerator extends CodeActionsProvider {
- public static final String GENERATE_IMPLEMENT_METHOD = "java.generate.implementMethod";
- public static final String GENERATE_OVERRIDE_METHOD = "java.generate.overrideMethod";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String IS_IMPLEMET = "isImplement";
+ private static final String METHODS = "methods";
- private final Set<String> commands = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(GENERATE_IMPLEMENT_METHOD, GENERATE_OVERRIDE_METHOD)));
private final Gson gson = new Gson();
- public ImplementOverrideMethodGenerator() {
- }
-
@Override
@NbBundle.Messages({
"DN_GenerateImplementMethod=Generate Implement Method...",
@@ -108,7 +105,7 @@ public final class ImplementOverrideMethodGenerator extends CodeActionsProvider
implementMethods.add(new QuickPickItem(createLabel(info, method), enclosingTypeName, null, mustImplement, new ElementData(method)));
}
if (!implementMethods.isEmpty()) {
- result.add(createCodeAction(Bundle.DN_GenerateImplementMethod(), CODE_GENERATOR_KIND, GENERATE_IMPLEMENT_METHOD, uri, offset, implementMethods));
+ result.add(createCodeAction(Bundle.DN_GenerateImplementMethod(), CODE_GENERATOR_KIND, data(uri, offset, true, implementMethods), null));
}
}
if (typeElement.getKind().isClass() || typeElement.getKind().isInterface()) {
@@ -124,66 +121,75 @@ public final class ImplementOverrideMethodGenerator extends CodeActionsProvider
overrideMethods.add(item);
}
if (!overrideMethods.isEmpty()) {
- result.add(createCodeAction(Bundle.DN_GenerateOverrideMethod(), CODE_GENERATOR_KIND, GENERATE_OVERRIDE_METHOD, uri, offset, overrideMethods));
+ result.add(createCodeAction(Bundle.DN_GenerateOverrideMethod(), CODE_GENERATOR_KIND, data (uri, offset, false, overrideMethods), null));
}
}
return result;
}
@Override
- public Set<String> getCommands() {
- return commands;
- }
-
- @Override
@NbBundle.Messages({
"DN_SelectImplementMethod=Select methods to implement",
"DN_SelectOverrideMethod=Select methods to override",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 2) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- List<QuickPickItem> methods = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(2)), QuickPickItem[].class));
- String text = command == GENERATE_IMPLEMENT_METHOD ? Bundle.DN_SelectImplementMethod() : Bundle.DN_SelectOverrideMethod();
- boolean isImplement = command == GENERATE_IMPLEMENT_METHOD;
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ boolean isImplement = ((JsonObject) data).getAsJsonPrimitive(IS_IMPLEMET).getAsBoolean();
+ List<QuickPickItem> methods = Arrays.asList(gson.fromJson(((JsonObject) data).get(METHODS), QuickPickItem[].class));
+ String text = isImplement ? Bundle.DN_SelectImplementMethod() : Bundle.DN_SelectOverrideMethod();
client.showQuickPick(new ShowQuickPickParams(text, true, methods)).thenAccept(selected -> {
- if (selected != null && !selected.isEmpty()) {
- generate(client, uri, offset, isImplement, selected);
+ try {
+ if (selected != null && !selected.isEmpty()) {
+ WorkspaceEdit edit = generate(uri, offset, isImplement, selected);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ }
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch(JsonSyntaxException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
- private void generate(NbCodeLanguageClient client, String uri, int offset, boolean isImplement, List<QuickPickItem> methods) {
- try {
- FileObject file = Utils.fromUri(uri);
- JavaSource js = JavaSource.forFileObject(file);
- if (js == null) {
- throw new IOException("Cannot get JavaSource for: " + uri);
- }
- List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
- wc.toPhase(JavaSource.Phase.RESOLVED);
- TreePath tp = wc.getTreeUtilities().pathFor(offset);
- tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
- if (tp != null) {
- List<ExecutableElement> selectedMethods = methods.stream().map(item -> {
- ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
- return (ExecutableElement)data.resolve(wc);
- }).collect(Collectors.toList());
- if (isImplement) {
- GeneratorUtils.generateAbstractMethodImplementations(wc, tp, selectedMethods, -1);
- } else {
- GeneratorUtils.generateMethodOverrides(wc, tp, selectedMethods, -1);
- }
- }
- });
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ private WorkspaceEdit generate(String uri, int offset, boolean isImplement, List<QuickPickItem> methods) throws IOException, IllegalArgumentException {
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
}
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ TreePath tp = wc.getTreeUtilities().pathFor(offset);
+ tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
+ if (tp != null) {
+ List<ExecutableElement> selectedMethods = methods.stream().map(item -> {
+ ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
+ return (ExecutableElement)data.resolve(wc);
+ }).collect(Collectors.toList());
+ if (isImplement) {
+ GeneratorUtils.generateAbstractMethodImplementations(wc, tp, selectedMethods, -1);
+ } else {
+ GeneratorUtils.generateMethodOverrides(wc, tp, selectedMethods, -1);
+ }
+ }
+ });
+ return edits == null ? null : new WorkspaceEdit(Collections.singletonMap(uri, edits));
+ }
+
+ private static Map<String, Object> data(String uri, int offset, boolean isImplement, List<QuickPickItem> methods) {
+ Map<String, Object> data = new HashMap<>();
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ data.put(IS_IMPLEMET, isImplement);
+ data.put(METHODS, methods);
+ return data;
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LoggerGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LoggerGenerator.java
index 824838d..14220ac 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LoggerGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LoggerGenerator.java
@@ -19,14 +19,17 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import javax.lang.model.element.Modifier;
@@ -36,12 +39,9 @@ import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.java.source.CompilationController;
@@ -62,9 +62,9 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 20)
public final class LoggerGenerator extends CodeActionsProvider {
- public static final String GENERATE_LOGGER = "java.generate.logger";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
- private final Set<String> commands = Collections.singleton(GENERATE_LOGGER);
private final Gson gson = new Gson();
public LoggerGenerator() {
@@ -102,25 +102,24 @@ public final class LoggerGenerator extends CodeActionsProvider {
}
}
String uri = Utils.toUri(info.getFileObject());
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateLogger(), CODE_GENERATOR_KIND, GENERATE_LOGGER, uri, offset));
- }
-
- @Override
- public Set<String> getCommands() {
- return commands;
+ Map<String, Object> data = new HashMap<>();
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateLogger(), CODE_GENERATOR_KIND, data, null));
}
@Override
@NbBundle.Messages({
"DN_SelectLoggerName=Logger field name",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 1) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
client.showInputBox(new ShowInputBoxParams(Bundle.DN_SelectLoggerName(), "LOG")).thenAccept(value -> {
- if (value != null && BaseUtilities.isJavaIdentifier(value)) {
- try {
+ try {
+ if (value != null && BaseUtilities.isJavaIdentifier(value)) {
FileObject file = Utils.fromUri(uri);
JavaSource js = JavaSource.forFileObject(file);
if (js == null) {
@@ -136,15 +135,18 @@ public final class LoggerGenerator extends CodeActionsProvider {
wc.rewrite(cls, GeneratorUtilities.get(wc).insertClassMember(cls, field));
}
});
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ if (!edits.isEmpty()) {
+ codeAction.setEdit(new WorkspaceEdit(Collections.singletonMap(uri, edits)));
+ }
}
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch (JsonSyntaxException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/MoveRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/MoveRefactoring.java
index 9aa18d7..51475e6 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/MoveRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/MoveRefactoring.java
@@ -98,9 +98,9 @@ public final class MoveRefactoring extends CodeRefactoring {
if (element != null) {
QuickPickItem elementItem = new QuickPickItem(createLabel(info, element));
elementItem.setUserData(new ElementData(element));
- return Collections.singletonList(createCodeAction(Bundle.DN_Move(), MOVE_REFACTORING_KIND, MOVE_REFACTORING_COMMAND, uri, elementItem));
+ return Collections.singletonList(createCodeAction(Bundle.DN_Move(), MOVE_REFACTORING_KIND, null, MOVE_REFACTORING_COMMAND, uri, elementItem));
} else {
- return Collections.singletonList(createCodeAction(Bundle.DN_Move(), MOVE_REFACTORING_KIND, MOVE_REFACTORING_COMMAND, uri));
+ return Collections.singletonList(createCodeAction(Bundle.DN_Move(), MOVE_REFACTORING_KIND, null, MOVE_REFACTORING_COMMAND, uri));
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/OrganizeImportsCodeAction.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/OrganizeImportsCodeAction.java
new file mode 100644
index 0000000..c16187c
--- /dev/null
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/OrganizeImportsCodeAction.java
@@ -0,0 +1,87 @@
+/*
+ * 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.JsonPrimitive;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import org.eclipse.lsp4j.CodeAction;
+import org.eclipse.lsp4j.CodeActionKind;
+import org.eclipse.lsp4j.CodeActionParams;
+import org.eclipse.lsp4j.TextEdit;
+import org.eclipse.lsp4j.WorkspaceEdit;
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.modules.java.hints.OrganizeImports;
+import org.netbeans.modules.java.lsp.server.Utils;
+import org.netbeans.modules.parsing.api.ResultIterator;
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author Dusan Balek
+ */
+@ServiceProvider(service = CodeActionsProvider.class, position = 90)
+public final class OrganizeImportsCodeAction extends CodeActionsProvider {
+
+ @Override
+ @NbBundle.Messages({
+ "DN_OrganizeImports=Organize Imports",
+ })
+ public List<CodeAction> getCodeActions(ResultIterator resultIterator, CodeActionParams params) throws Exception {
+ List<String> only = params.getContext().getOnly();
+ if (only == null || !only.contains(CodeActionKind.Source) && !only.contains(CodeActionKind.SourceOrganizeImports)) {
+ return Collections.emptyList();
+ }
+ CompilationController info = CompilationController.get(resultIterator.getParserResult());
+ if (info == null) {
+ return Collections.emptyList();
+ }
+ String uri = Utils.toUri(info.getFileObject());
+ return Collections.singletonList(createCodeAction(Bundle.DN_OrganizeImports(), CodeActionKind.SourceOrganizeImports, uri, null));
+ }
+
+ @Override
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonPrimitive) data).getAsString();
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
+ }
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ OrganizeImports.doOrganizeImports(wc, null, false);
+ });
+ if (!edits.isEmpty()) {
+ codeAction.setEdit(new WorkspaceEdit(Collections.singletonMap(uri, edits)));
+ }
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
+ }
+ return future;
+ }
+}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PullUpRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PullUpRefactoring.java
index b146688..dea79b2 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PullUpRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PullUpRefactoring.java
@@ -115,7 +115,7 @@ public final class PullUpRefactoring extends CodeRefactoring {
}
QuickPickItem elementItem = new QuickPickItem(createLabel(info, element));
elementItem.setUserData(new ElementData(element));
- return Collections.singletonList(createCodeAction(Bundle.DN_PullUp(), PULL_UP_REFACTORING_KIND, PULL_UP_REFACTORING_COMMAND, uri, offset, elementItem, supertypeItems));
+ return Collections.singletonList(createCodeAction(Bundle.DN_PullUp(), PULL_UP_REFACTORING_KIND, null, PULL_UP_REFACTORING_COMMAND, uri, offset, elementItem, supertypeItems));
}
@Override
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PushDownRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PushDownRefactoring.java
index 591f071..65cc6fd 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PushDownRefactoring.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/PushDownRefactoring.java
@@ -126,7 +126,7 @@ public final class PushDownRefactoring extends CodeRefactoring {
}
QuickPickItem elementItem = new QuickPickItem(createLabel(info, element));
elementItem.setUserData(new ElementData(element));
- return Collections.singletonList(createCodeAction(Bundle.DN_PushDown(), PUSH_DOWN_REFACTORING_KIND, PUSH_DOWN_REFACTORING_COMMAND, uri, elementItem, members));
+ return Collections.singletonList(createCodeAction(Bundle.DN_PushDown(), PUSH_DOWN_REFACTORING_KIND, null, PUSH_DOWN_REFACTORING_COMMAND, uri, elementItem, members));
}
@Override
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
index f406c47..386ee69 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
@@ -43,10 +43,13 @@ import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gson.InstanceCreator;
+import com.google.gson.JsonObject;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionOptions;
import org.eclipse.lsp4j.CodeLensOptions;
import org.eclipse.lsp4j.CompletionOptions;
+import org.eclipse.lsp4j.ConfigurationItem;
+import org.eclipse.lsp4j.ConfigurationParams;
import org.eclipse.lsp4j.ExecuteCommandOptions;
import org.eclipse.lsp4j.FoldingRangeProviderOptions;
import org.eclipse.lsp4j.InitializeParams;
@@ -60,6 +63,7 @@ import org.eclipse.lsp4j.SemanticTokensCapabilities;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.lsp4j.TextDocumentSyncKind;
+import org.eclipse.lsp4j.TextDocumentSyncOptions;
import org.eclipse.lsp4j.WorkDoneProgressCancelParams;
import org.eclipse.lsp4j.WorkDoneProgressParams;
import org.eclipse.lsp4j.WorkspaceFolder;
@@ -280,13 +284,15 @@ public final class Server {
static class LanguageServerImpl implements LanguageServer, LanguageClientAware, LspServerState {
+ private static final String NETBEANS_JAVA_IMPORTS = "netbeans.java.imports";
+
// change to a greater throughput if the initialization waits on more processes than just (serialized) project open.
private static final RequestProcessor SERVER_INIT_RP = new RequestProcessor(LanguageServerImpl.class.getName());
private static final Logger LOG = Logger.getLogger(LanguageServerImpl.class.getName());
private NbCodeClientWrapper client;
- private final TextDocumentService textDocumentService = new TextDocumentServiceImpl(this);
- private final WorkspaceService workspaceService = new WorkspaceServiceImpl(this);
+ private final TextDocumentServiceImpl textDocumentService = new TextDocumentServiceImpl(this);
+ private final WorkspaceServiceImpl workspaceService = new WorkspaceServiceImpl(this);
private final InstanceContent sessionServices = new InstanceContent();
private final Lookup sessionLookup = new ProxyLookup(
new AbstractLookup(sessionServices),
@@ -610,13 +616,19 @@ public final class Server {
private InitializeResult constructInitResponse(JavaSource src) {
ServerCapabilities capabilities = new ServerCapabilities();
if (src != null) {
- capabilities.setTextDocumentSync(TextDocumentSyncKind.Incremental);
+ TextDocumentSyncOptions textDocumentSyncOptions = new TextDocumentSyncOptions();
+ textDocumentSyncOptions.setChange(TextDocumentSyncKind.Incremental);
+ textDocumentSyncOptions.setOpenClose(true);
+ textDocumentSyncOptions.setWillSaveWaitUntil(true);
+ capabilities.setTextDocumentSync(textDocumentSyncOptions);
CompletionOptions completionOptions = new CompletionOptions();
completionOptions.setResolveProvider(true);
completionOptions.setTriggerCharacters(Collections.singletonList("."));
capabilities.setCompletionProvider(completionOptions);
capabilities.setHoverProvider(true);
- capabilities.setCodeActionProvider(new CodeActionOptions(Arrays.asList(CodeActionKind.QuickFix, CodeActionKind.Source, CodeActionKind.Refactor)));
+ CodeActionOptions codeActionOptions = new CodeActionOptions(Arrays.asList(CodeActionKind.QuickFix, CodeActionKind.Source, CodeActionKind.SourceOrganizeImports, CodeActionKind.Refactor));
+ codeActionOptions.setResolveProvider(true);
+ capabilities.setCodeActionProvider(codeActionOptions);
capabilities.setDocumentSymbolProvider(true);
capabilities.setDefinitionProvider(true);
capabilities.setTypeDefinitionProvider(true);
@@ -687,7 +699,9 @@ public final class Server {
// chain showIndexingComplete message after initial project open.
prjs.
thenApply(this::showIndexingCompleted);
-
+
+ initializeOptions();
+
// but complete the InitializationRequest independently of the project initialization.
return CompletableFuture.completedFuture(
finishInitialization(
@@ -696,6 +710,22 @@ public final class Server {
);
}
+ private void initializeOptions() {
+ getWorkspaceProjects().thenAccept(projects -> {
+ if (projects != null && projects.length > 0) {
+ ConfigurationItem item = new ConfigurationItem();
+ FileObject fo = projects[0].getProjectDirectory();
+ item.setScopeUri(Utils.toUri(fo));
+ item.setSection(NETBEANS_JAVA_IMPORTS);
+ client.configuration(new ConfigurationParams(Collections.singletonList(item))).thenAccept(c -> {
+ if (c != null && !c.isEmpty() && c.get(0) instanceof JsonObject) {
+ workspaceService.updateJavaImportPreferences(fo, (JsonObject) c.get(0));
+ }
+ });
+ }
+ });
+ }
+
public CompletableFuture<Project[]> getWorkspaceProjects() {
return workspaceProjects;
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
index 5aad8d4..5424309 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/SurroundWithHint.java
@@ -134,7 +134,7 @@ public final class SurroundWithHint extends CodeActionsProvider {
snippet = sb.append(snippet).toString();
}
int idx = label.indexOf(' ');
- CodeAction codeAction = createCodeAction(Bundle.DN_SurroundWith(idx < 0 ? label : label.substring(0, idx)), CodeActionKind.RefactorRewrite, COMMAND_INSERT_SNIPPET, Collections.singletonMap(SNIPPET, snippet));
+ CodeAction codeAction = createCodeAction(Bundle.DN_SurroundWith(idx < 0 ? label : label.substring(0, idx)), CodeActionKind.RefactorRewrite, null, COMMAND_INSERT_SNIPPET, Collections.singletonMap(SNIPPET, snippet));
if (!edits.isEmpty()) {
codeAction.setEdit(new WorkspaceEdit(Collections.singletonMap(params.getTextDocument().getUri(), edits)));
}
@@ -146,21 +146,11 @@ public final class SurroundWithHint extends CodeActionsProvider {
}
}
if (items.size() > codeActions.size()) {
- codeActions.add(createCodeAction(Bundle.DN_SurroundWithAll(), CodeActionKind.RefactorRewrite, COMMAND_SURROUND_WITH, items));
+ codeActions.add(createCodeAction(Bundle.DN_SurroundWithAll(), CodeActionKind.RefactorRewrite, null, COMMAND_SURROUND_WITH, items));
}
return codeActions;
}
- @Override
- public Set<String> getCommands() {
- return Collections.emptySet();
- }
-
- @Override
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- return CompletableFuture.completedFuture(false);
- }
-
private static Collection<? extends CodeTemplateFilter> getTemplateFilters(Document doc, int startOffset, int endOffset) {
String mimeType = DocumentUtilities.getMimeType(doc);
Collection<? extends CodeTemplateFilter.Factory> filterFactories = MimeLookup.getLookup(mimeType).lookupAll(CodeTemplateFilter.Factory.class);
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
index faa927d..a8ba7bf 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
@@ -132,6 +132,7 @@ import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.TypeDefinitionParams;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
+import org.eclipse.lsp4j.WillSaveTextDocumentParams;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
@@ -175,6 +176,7 @@ import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
import org.netbeans.modules.java.editor.options.MarkOccurencesSettings;
import org.netbeans.modules.java.editor.overridden.ComputeOverriding;
import org.netbeans.modules.java.editor.overridden.ElementDescription;
+import org.netbeans.modules.java.hints.OrganizeImports;
import org.netbeans.modules.java.hints.introduce.IntroduceFixBase;
import org.netbeans.modules.java.hints.introduce.IntroduceHint;
import org.netbeans.modules.java.hints.introduce.IntroduceKind;
@@ -233,6 +235,7 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
private static final String COMMAND_RUN_SINGLE = "java.run.single"; // NOI18N
private static final String COMMAND_DEBUG_SINGLE = "java.debug.single"; // NOI18N
private static final String NETBEANS_JAVADOC_LOAD_TIMEOUT = "netbeans.javadoc.load.timeout";// NOI18N
+ private static final String NETBEANS_JAVA_ON_SAVE_ORGANIZE_IMPORTS = "netbeans.java.onSave.organizeImports";// NOI18N
private static final RequestProcessor BACKGROUND_TASKS = new RequestProcessor(TextDocumentServiceImpl.class.getName(), 1, false, false);
private static final RequestProcessor WORKER = new RequestProcessor(TextDocumentServiceImpl.class.getName(), 1, false, false);
@@ -1001,7 +1004,23 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
});
return resultFuture;
}
-
+
+ @Override
+ public CompletableFuture<CodeAction> resolveCodeAction(CodeAction unresolved) {
+ JsonObject data = (JsonObject) unresolved.getData();
+ if (data != null) {
+ String providerClass = data.getAsJsonPrimitive(CodeActionsProvider.CODE_ACTIONS_PROVIDER_CLASS).getAsString();
+ for (CodeActionsProvider codeGenerator : Lookup.getDefault().lookupAll(CodeActionsProvider.class)) {
+ try {
+ if (codeGenerator.getClass().getName().equals(providerClass)) {
+ return codeGenerator.resolve(client, unresolved, data.get(CodeActionsProvider.DATA));
+ }
+ } catch (Exception ex) {
+ }
+ }
+ }
+ return CompletableFuture.completedFuture(unresolved);
+ }
@NbBundle.Messages({"# {0} - method name", "LBL_Run=Run {0}",
"# {0} - method name", "LBL_Debug=Debug {0}",
@@ -1443,6 +1462,30 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
}
@Override
+ public CompletableFuture<List<TextEdit>> willSaveWaitUntil(WillSaveTextDocumentParams params) {
+ String uri = params.getTextDocument().getUri();
+ JavaSource js = getJavaSource(uri);
+ if (js == null) {
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+ ConfigurationItem conf = new ConfigurationItem();
+ conf.setScopeUri(uri);
+ conf.setSection(NETBEANS_JAVA_ON_SAVE_ORGANIZE_IMPORTS);
+ return client.configuration(new ConfigurationParams(Collections.singletonList(conf))).thenApply(c -> {
+ if (c != null && !c.isEmpty() && ((JsonPrimitive) c.get(0)).getAsBoolean()) {
+ try {
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ OrganizeImports.doOrganizeImports(wc, null, false);
+ });
+ return edits;
+ } catch (IOException ex) {}
+ }
+ return Collections.emptyList();
+ });
+ }
+
+ @Override
public void didSave(DidSaveTextDocumentParams arg0) {
//TODO: nothing for now?
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ToStringGenerator.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ToStringGenerator.java
index 70dc949..f862f38 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ToStringGenerator.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/ToStringGenerator.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.java.lsp.server.protocol;
import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.TreePath;
@@ -26,8 +28,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
@@ -35,12 +38,9 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
-import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionParams;
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.netbeans.api.java.source.CompilationController;
@@ -60,14 +60,12 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = CodeActionsProvider.class, position = 50)
public final class ToStringGenerator extends CodeActionsProvider {
- public static final String GENERATE_TO_STRING = "java.generate.toString";
+ private static final String URI = "uri";
+ private static final String OFFSET = "offset";
+ private static final String FIELDS = "fields";
- private final Set<String> commands = Collections.singleton(GENERATE_TO_STRING);
private final Gson gson = new Gson();
- public ToStringGenerator() {
- }
-
@Override
@NbBundle.Messages({
"DN_GenerateToString=Generate toString()...",
@@ -110,62 +108,70 @@ public final class ToStringGenerator extends CodeActionsProvider {
}
}
String uri = Utils.toUri(info.getFileObject());
- return Collections.singletonList(createCodeAction(Bundle.DN_GenerateToString(), CODE_GENERATOR_KIND, GENERATE_TO_STRING, uri, offset, fields));
- }
-
- @Override
- public Set<String> getCommands() {
- return commands;
+ Map<String, Object> data = new HashMap<>();
+ data.put(URI, uri);
+ data.put(OFFSET, offset);
+ data.put(FIELDS, fields);
+ return Collections.singletonList(createCodeAction(Bundle.DN_GenerateToString(), CODE_GENERATOR_KIND, data, null));
}
@Override
@NbBundle.Messages({
"DN_SelectToString=Select fields to be included in toString()",
})
- public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
- if (arguments.size() > 2) {
- String uri = gson.fromJson(gson.toJson(arguments.get(0)), String.class);
- int offset = gson.fromJson(gson.toJson(arguments.get(1)), Integer.class);
- List<QuickPickItem> fields = Arrays.asList(gson.fromJson(gson.toJson(arguments.get(2)), QuickPickItem[].class));
+ public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) {
+ CompletableFuture<CodeAction> future = new CompletableFuture<>();
+ try {
+ String uri = ((JsonObject) data).getAsJsonPrimitive(URI).getAsString();
+ int offset = ((JsonObject) data).getAsJsonPrimitive(OFFSET).getAsInt();
+ List<QuickPickItem> fields = Arrays.asList(gson.fromJson(((JsonObject) data).get(FIELDS), QuickPickItem[].class));
if (fields.isEmpty()) {
- generate(client, uri, offset, fields);
+ WorkspaceEdit edit = generate(uri, offset, fields);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ future.complete(codeAction);
} else {
client.showQuickPick(new ShowQuickPickParams(Bundle.DN_SelectToString(), true, fields)).thenAccept(selected -> {
- if (selected != null) {
- generate(client, uri, offset, selected);
+ try {
+ if (selected != null) {
+ WorkspaceEdit edit = generate(uri, offset, fields);
+ if (edit != null) {
+ codeAction.setEdit(edit);
+ }
+ }
+ future.complete(codeAction);
+ } catch (IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
});
}
- } else {
- client.logMessage(new MessageParams(MessageType.Error, String.format("Illegal number of arguments received for command: %s", command)));
+ } catch (JsonSyntaxException | IOException | IllegalArgumentException ex) {
+ future.completeExceptionally(ex);
}
- return CompletableFuture.completedFuture(true);
+ return future;
}
- private void generate(NbCodeLanguageClient client, String uri, int offset, List<QuickPickItem> fields) {
- try {
- FileObject file = Utils.fromUri(uri);
- JavaSource js = JavaSource.forFileObject(file);
- if (js == null) {
- throw new IOException("Cannot get JavaSource for: " + uri);
- }
- List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
- wc.toPhase(JavaSource.Phase.RESOLVED);
- TreePath tp = wc.getTreeUtilities().pathFor(offset);
- tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
- if (tp != null) {
- ClassTree cls = (ClassTree) tp.getLeaf();
- List<VariableElement> selectedFields = fields.stream().map(item -> {
- ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
- return (VariableElement)data.resolve(wc);
- }).collect(Collectors.toList());
- MethodTree method = org.netbeans.modules.java.editor.codegen.ToStringGenerator.createToStringMethod(wc, selectedFields, cls.getSimpleName().toString(), true);
- wc.rewrite(cls, GeneratorUtilities.get(wc).insertClassMember(cls, method));
- }
- });
- client.applyEdit(new ApplyWorkspaceEditParams(new WorkspaceEdit(Collections.singletonMap(uri, edits))));
- } catch (IOException | IllegalArgumentException ex) {
- client.logMessage(new MessageParams(MessageType.Error, ex.getLocalizedMessage()));
+ private WorkspaceEdit generate(String uri, int offset, List<QuickPickItem> fields) throws IOException, IllegalArgumentException {
+ FileObject file = Utils.fromUri(uri);
+ JavaSource js = JavaSource.forFileObject(file);
+ if (js == null) {
+ throw new IOException("Cannot get JavaSource for: " + uri);
}
+ List<TextEdit> edits = TextDocumentServiceImpl.modify2TextEdits(js, wc -> {
+ wc.toPhase(JavaSource.Phase.RESOLVED);
+ TreePath tp = wc.getTreeUtilities().pathFor(offset);
+ tp = wc.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, tp);
+ if (tp != null) {
+ ClassTree cls = (ClassTree) tp.getLeaf();
+ List<VariableElement> selectedFields = fields.stream().map(item -> {
+ ElementData data = gson.fromJson(gson.toJson(item.getUserData()), ElementData.class);
+ return (VariableElement)data.resolve(wc);
+ }).collect(Collectors.toList());
+ MethodTree method = org.netbeans.modules.java.editor.codegen.ToStringGenerator.createToStringMethod(wc, selectedFields, cls.getSimpleName().toString(), true);
+ wc.rewrite(cls, GeneratorUtilities.get(wc).insertClassMember(cls, method));
+ }
+ });
+ return edits.isEmpty() ? null : new WorkspaceEdit(Collections.singletonMap(uri, edits));
}
}
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
index eb55741..8928119 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
@@ -44,6 +44,7 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.logging.Logger;
+import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
@@ -80,6 +81,7 @@ import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.ui.OpenProjects;
+import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodController;
import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodFinder;
import org.netbeans.modules.java.lsp.server.LspServerState;
@@ -660,8 +662,23 @@ public final class WorkspaceServiceImpl implements WorkspaceService, LanguageCli
}
@Override
- public void didChangeConfiguration(DidChangeConfigurationParams arg0) {
- //TODO: no real configuration right now
+ public void didChangeConfiguration(DidChangeConfigurationParams params) {
+ server.openedProjects().thenAccept(projects -> {
+ if (projects != null && projects.length > 0) {
+ updateJavaImportPreferences(projects[0].getProjectDirectory(), ((JsonObject) params.getSettings()).getAsJsonObject("netbeans").getAsJsonObject("java").getAsJsonObject("imports"));
+ }
+ });
+ }
+
+ void updateJavaImportPreferences(FileObject fo, JsonObject configuration) {
+ Preferences prefs = CodeStylePreferences.get(fo, "text/x-java").getPreferences();
+ if (prefs != null) {
+ prefs.put("importGroupsOrder", String.join(";", gson.fromJson(configuration.get("groups"), String[].class)));
+ prefs.putBoolean("allowConvertToStarImport", true);
+ prefs.putInt("countForUsingStarImport", configuration.getAsJsonPrimitive("countForUsingStarImport").getAsInt());
+ prefs.putBoolean("allowConvertToStaticStarImport", true);
+ prefs.putInt("countForUsingStaticStarImport", configuration.getAsJsonPrimitive("countForUsingStaticStarImport").getAsInt());
+ }
}
@Override
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
index 6dd3fbe..bb18841 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
@@ -2818,7 +2818,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new LspClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -2845,8 +2844,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
}, client.getInputStream(), client.getOutputStream());
@@ -2865,9 +2863,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateGetterSetterFor("f2").equals(a.getTitle()))
.findAny();
assertTrue(generateGetterSetter.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateGetterSetter.get().getCommand().getCommand(), generateGetterSetter.get().getCommand().getArguments())).get();
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateGetterSetter.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(6, 0),
@@ -2894,7 +2895,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -2921,8 +2921,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -2981,13 +2980,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateConstructor().equals(a.getTitle()))
.findAny();
assertTrue(generateConstructor.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateConstructor.get().getCommand().getCommand(), generateConstructor.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateConstructor.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(3, 0),
@@ -3010,7 +3008,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new LspClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3037,8 +3034,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
}, client.getInputStream(), client.getOutputStream());
@@ -3049,7 +3045,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(3, 0), new Position(3, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(9, codeActions.size());
+ assertEquals(10, codeActions.size());
Optional<CodeAction> generateGetterSetter =
codeActions.stream()
.filter(Either::isRight)
@@ -3057,9 +3053,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateGetterSetterFor("f2").equals(a.getTitle()))
.findAny();
assertTrue(generateGetterSetter.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateGetterSetter.get().getCommand().getCommand(), generateGetterSetter.get().getCommand().getArguments())).get();
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateGetterSetter.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(3, 0),
@@ -3076,7 +3075,7 @@ public class ServerTest extends NbTestCase {
fileChanges.get(0).getNewText());
server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(fileChanges.get(0).getRange(), 0, fileChanges.get(0).getNewText()))));
codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(3, 0), new Position(3, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateGetter =
codeActions.stream()
.filter(Either::isRight)
@@ -3084,9 +3083,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateGetterFor("f1").equals(a.getTitle()))
.findAny();
assertTrue(generateGetter.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateGetter.get().getCommand().getCommand(), generateGetter.get().getCommand().getArguments())).get();
- assertEquals(1, edit[0].getChanges().size());
- fileChanges = edit[0].getChanges().get(uri);
+ resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateGetter.get()).get();
+ assertNotNull(resolvedCodeAction);
+ edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(11, 0),
@@ -3108,7 +3110,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3135,8 +3136,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3187,7 +3187,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(2, 0), new Position(2, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateConstructor =
codeActions.stream()
.filter(Either::isRight)
@@ -3195,13 +3195,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateConstructor().equals(a.getTitle()))
.findAny();
assertTrue(generateConstructor.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateConstructor.get().getCommand().getCommand(), generateConstructor.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateConstructor.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(2, 0),
@@ -3239,7 +3238,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3266,8 +3264,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3318,7 +3315,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(5, 0), new Position(5, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(9, codeActions.size());
+ assertEquals(10, codeActions.size());
Optional<CodeAction> generateEquals =
codeActions.stream()
.filter(Either::isRight)
@@ -3326,13 +3323,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateEquals().equals(a.getTitle()))
.findAny();
assertTrue(generateEquals.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateEquals.get().getCommand().getCommand(), generateEquals.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateEquals.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(13, 0),
@@ -3368,7 +3364,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3395,8 +3390,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3447,7 +3441,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(2, 0), new Position(2, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateToString =
codeActions.stream()
.filter(Either::isRight)
@@ -3455,13 +3449,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateToString().equals(a.getTitle()))
.findAny();
assertTrue(generateToString.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateToString.get().getCommand().getCommand(), generateToString.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateToString.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(2, 0),
@@ -3488,7 +3481,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3515,8 +3507,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3567,7 +3558,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(2, 0), new Position(2, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateDelegateMethod =
codeActions.stream()
.filter(Either::isRight)
@@ -3575,13 +3566,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateDelegateMethod().equals(a.getTitle()))
.findAny();
assertTrue(generateDelegateMethod.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateDelegateMethod.get().getCommand().getCommand(), generateDelegateMethod.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateDelegateMethod.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(2, fileChanges.size());
assertEquals(new Range(new Position(0, 0),
@@ -3612,7 +3602,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3639,8 +3628,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3691,7 +3679,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(2, 0), new Position(2, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateOverrideMethod =
codeActions.stream()
.filter(Either::isRight)
@@ -3699,13 +3687,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateOverrideMethod().equals(a.getTitle()))
.findAny();
assertTrue(generateOverrideMethod.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateOverrideMethod.get().getCommand().getCommand(), generateOverrideMethod.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateOverrideMethod.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(1, fileChanges.size());
assertEquals(new Range(new Position(2, 0),
@@ -3733,7 +3720,6 @@ public class ServerTest extends NbTestCase {
try (Writer w = new FileWriter(src)) {
w.write(code);
}
- WorkspaceEdit[] edit = new WorkspaceEdit[1];
Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new NbCodeLanguageClient() {
@Override
public void telemetryEvent(Object arg0) {
@@ -3760,8 +3746,7 @@ public class ServerTest extends NbTestCase {
@Override
public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
- edit[0] = params.getEdit();
- return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
+ throw new UnsupportedOperationException("Not supported yet.");
}
@Override
@@ -3812,7 +3797,7 @@ public class ServerTest extends NbTestCase {
server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(2, 0), new Position(2, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
- assertEquals(7, codeActions.size());
+ assertEquals(8, codeActions.size());
Optional<CodeAction> generateLogger =
codeActions.stream()
.filter(Either::isRight)
@@ -3820,13 +3805,12 @@ public class ServerTest extends NbTestCase {
.filter(a -> Bundle.DN_GenerateLogger().equals(a.getTitle()))
.findAny();
assertTrue(generateLogger.isPresent());
- server.getWorkspaceService().executeCommand(new ExecuteCommandParams(generateLogger.get().getCommand().getCommand(), generateLogger.get().getCommand().getArguments())).get();
- int cnt = 0;
- while(edit[0] == null && cnt++ < 10) {
- Thread.sleep(1000);
- }
- assertEquals(1, edit[0].getChanges().size());
- List<TextEdit> fileChanges = edit[0].getChanges().get(uri);
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(generateLogger.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
assertNotNull(fileChanges);
assertEquals(2, fileChanges.size());
assertEquals(new Range(new Position(0, 0),
@@ -3842,6 +3826,82 @@ public class ServerTest extends NbTestCase {
fileChanges.get(1).getNewText());
}
+ public void testSourceActionOrganizeImports() throws Exception {
+ File src = new File(getWorkDir(), "Test.java");
+ src.getParentFile().mkdirs();
+ String code = "import java.util.List;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.Collection;\n" +
+ "\n" +
+ "public class Test {\n" +
+ " private final List<String> names = new ArrayList<>();\n" +
+ "}\n";
+ try (Writer w = new FileWriter(src)) {
+ w.write(code);
+ }
+ Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new LspClient() {
+ @Override
+ public void telemetryEvent(Object arg0) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void publishDiagnostics(PublishDiagnosticsParams params) {
+ }
+
+ @Override
+ public void showMessage(MessageParams arg0) {
+ }
+
+ @Override
+ public CompletableFuture<MessageActionItem> showMessageRequest(ShowMessageRequestParams arg0) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void logMessage(MessageParams arg0) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CompletableFuture<ApplyWorkspaceEditResponse> applyEdit(ApplyWorkspaceEditParams params) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ }, client.getInputStream(), client.getOutputStream());
+ serverLauncher.startListening();
+ LanguageServer server = serverLauncher.getRemoteProxy();
+ server.initialize(new InitializeParams()).get();
+ String uri = src.toURI().toString();
+ server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, code)));
+ VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(src.toURI().toString(), 1);
+ List<Either<Command, CodeAction>> codeActions = server.getTextDocumentService().codeAction(new CodeActionParams(id, new Range(new Position(6, 0), new Position(6, 0)), new CodeActionContext(Arrays.asList(), Arrays.asList(CodeActionKind.Source)))).get();
+ assertEquals(8, codeActions.size());
+ Optional<CodeAction> organizeImports =
+ codeActions.stream()
+ .filter(Either::isRight)
+ .map(Either::getRight)
+ .filter(a -> Bundle.DN_OrganizeImports().equals(a.getTitle()))
+ .findAny();
+ assertTrue(organizeImports.isPresent());
+ CodeAction resolvedCodeAction = server.getTextDocumentService().resolveCodeAction(organizeImports.get()).get();
+ assertNotNull(resolvedCodeAction);
+ WorkspaceEdit edit = resolvedCodeAction.getEdit();
+ assertNotNull(edit);
+ assertEquals(1, edit.getChanges().size());
+ List<TextEdit> fileChanges = edit.getChanges().get(uri);
+ assertNotNull(fileChanges);
+ assertEquals(2, fileChanges.size());
+ assertEquals(new Range(new Position(0, 0),
+ new Position(1, 0)),
+ fileChanges.get(0).getRange());
+ assertEquals("", fileChanges.get(0).getNewText());
+ assertEquals(new Range(new Position(2, 17),
+ new Position(2, 27)),
+ fileChanges.get(1).getRange());
+ assertEquals("List", fileChanges.get(1).getNewText());
+ }
+
public void testRenameDocumentChangesCapabilitiesRenameOp() throws Exception {
doTestRename(init -> {
WorkspaceEditCapabilities wec = new WorkspaceEditCapabilities();
diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json
index d2cdd7f..94f9793 100644
--- a/java/java.lsp.server/vscode/package.json
+++ b/java/java.lsp.server/vscode/package.json
@@ -108,6 +108,34 @@
"type": "integer",
"default": 100,
"description": "Timeout (in milliseconds) for loading Javadoc in code completion (-1 for unlimited)"
+ },
+ "netbeans.java.onSave.organizeImports": {
+ "type": "boolean",
+ "default": true,
+ "description": "Enable organize imports action on a document save"
+ },
+ "netbeans.java.imports.groups": {
+ "type": "array",
+ "description": "Groups of import statements (specified by their package prefixes) and their sorting order. Import statements within a group are ordered alphabetically",
+ "default": [
+ "java",
+ "javax",
+ "org",
+ "com",
+ ""
+ ]
+ },
+ "netbeans.java.imports.countForUsingStarImport": {
+ "type": "integer",
+ "description": "Class count to use a star-import",
+ "default": 999,
+ "minimum": 1
+ },
+ "netbeans.java.imports.countForUsingStaticStarImport": {
+ "type": "integer",
+ "description": "Members count to use a static star-import",
+ "default": 999,
+ "minimum": 1
}
}
},
diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts
index 2263916..008d5d8 100644
--- a/java/java.lsp.server/vscode/src/extension.ts
+++ b/java/java.lsp.server/vscode/src/extension.ts
@@ -568,7 +568,7 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex
// Register the server for java documents
documentSelector: documentSelectors,
synchronize: {
- configurationSection: 'java',
+ configurationSection: 'netbeans.java.imports',
fileEvents: [
workspace.createFileSystemWatcher('**/*.java')
]
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists