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 71f69f99f9 LSP: Adding CodaActionProvider API. new 82603029ef Merge pull request #6770 from dbalek/dbalek/lsp-code-action-provider 71f69f99f9 is described below commit 71f69f99f9745dc8b39397c62d321f18e1215ca4 Author: Dusan Balek <dusan.ba...@oracle.com> AuthorDate: Thu Nov 30 13:05:12 2023 +0100 LSP: Adding CodaActionProvider API. --- ide/api.lsp/apichanges.xml | 15 +++ ide/api.lsp/manifest.mf | 2 +- .../src/org/netbeans/api/lsp/CodeAction.java | 27 ++++- .../src/org/netbeans/api/lsp/LazyCodeAction.java | 14 +++ .../org/netbeans/spi/lsp/CodeActionProvider.java | 45 ++++++++ java/java.lsp.server/nbproject/project.xml | 2 +- .../java/lsp/server/db/DBConnectionProvider.java | 17 +-- .../server/explorer/NodePropertiesProvider.java | 18 +-- .../CodeActionsProvider2CommandProviderBridge.java | 63 ----------- .../protocol/CodeActionsProvider2LspApiBridge.java | 124 ++++++++++++++++++++ .../server/protocol/TextDocumentServiceImpl.java | 126 ++++++++++----------- 11 files changed, 291 insertions(+), 162 deletions(-) diff --git a/ide/api.lsp/apichanges.xml b/ide/api.lsp/apichanges.xml index 59a1778b63..ec98400315 100644 --- a/ide/api.lsp/apichanges.xml +++ b/ide/api.lsp/apichanges.xml @@ -51,6 +51,21 @@ <!-- ACTUAL CHANGES BEGIN HERE: --> <changes> + <change id="CodeActionProvider"> + <api name="LSP_API"/> + <summary>Added CodeActionProvider interface</summary> + <version major="1" minor="23"/> + <date day="1" month="12" year="2023"/> + <author login="dbalek"/> + <compatibility binary="compatible" source="compatible" addition="yes" deletion="no"/> + <description> + <a href="@TOP@/org/netbeans/spi/lsp/CodeActionProvider.html">CodeActionProvider</a> + has been added to allow server provide arbitrary code actions for a given document and range. + </description> + <class package="org.netbeans.api.lsp" name="CodeAction"/> + <class package="org.netbeans.api.lsp" name="LazyCodeAction"/> + <class package="org.netbeans.spi.lsp" name="CodeActionProvider"/> + </change> <change id="CommandProvider"> <api name="LSP_API"/> <summary>Added CommandProvider interface</summary> diff --git a/ide/api.lsp/manifest.mf b/ide/api.lsp/manifest.mf index b9e46648cf..2eaadac4f9 100644 --- a/ide/api.lsp/manifest.mf +++ b/ide/api.lsp/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.lsp/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/api/lsp/Bundle.properties -OpenIDE-Module-Specification-Version: 1.22 +OpenIDE-Module-Specification-Version: 1.23 AutoUpdate-Show-In-Client: false diff --git a/ide/api.lsp/src/org/netbeans/api/lsp/CodeAction.java b/ide/api.lsp/src/org/netbeans/api/lsp/CodeAction.java index a9493f5277..48c8dc481a 100644 --- a/ide/api.lsp/src/org/netbeans/api/lsp/CodeAction.java +++ b/ide/api.lsp/src/org/netbeans/api/lsp/CodeAction.java @@ -19,13 +19,14 @@ package org.netbeans.api.lsp; /** - *An action over the code. + * An action over the code. * * @since 1.3 */ public class CodeAction { private final String title; + private final String kind; private final Command command; private final WorkspaceEdit edit; @@ -57,7 +58,21 @@ public class CodeAction { * @param edit the {@code WorkspaceEdit} that should be performed */ public CodeAction(String title, Command command, WorkspaceEdit edit) { + this(title, null, command, edit); + } + + /** + * Construct the {@code CodeAction}. + * + * @param title the name of the action + * @param kind optional kind of the action + * @param command the command that should be invoked + * @param edit the {@code WorkspaceEdit} that should be performed + * @since 1.23 + */ + public CodeAction(String title, String kind, Command command, WorkspaceEdit edit) { this.title = title; + this.kind = kind; this.command = command; this.edit = edit; } @@ -71,6 +86,16 @@ public class CodeAction { return title; } + /** + * Return the kind of the action. + * + * @return the kind of the action + * @since 1.23 + */ + public String getKind() { + return kind; + } + /** * Return the command of the action. * diff --git a/ide/api.lsp/src/org/netbeans/api/lsp/LazyCodeAction.java b/ide/api.lsp/src/org/netbeans/api/lsp/LazyCodeAction.java index 25df864d9a..327c9dafd1 100644 --- a/ide/api.lsp/src/org/netbeans/api/lsp/LazyCodeAction.java +++ b/ide/api.lsp/src/org/netbeans/api/lsp/LazyCodeAction.java @@ -52,6 +52,20 @@ public final class LazyCodeAction extends CodeAction { this.lazyEdit = lazyEdit; } + /** + * Constructs the {@code LazyCodeAction}. + * + * @param title the name of the action + * @param kind optional kind of the action + * @param command the command that should be invoked + * @param lazyEdit the lazily computed {@code WorkspaceEdit} that should be performed + * @since 1.23 + */ + public LazyCodeAction(String title, String kind, Command command, Supplier<WorkspaceEdit> lazyEdit) { + super(title, kind, command, null); + this.lazyEdit = lazyEdit; + } + @Override public WorkspaceEdit getEdit() { try { diff --git a/ide/api.lsp/src/org/netbeans/spi/lsp/CodeActionProvider.java b/ide/api.lsp/src/org/netbeans/spi/lsp/CodeActionProvider.java new file mode 100644 index 0000000000..b234018a0d --- /dev/null +++ b/ide/api.lsp/src/org/netbeans/spi/lsp/CodeActionProvider.java @@ -0,0 +1,45 @@ +/* + * 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.spi.lsp; + +import java.util.List; +import javax.swing.text.Document; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.lsp.CodeAction; +import org.netbeans.api.lsp.Range; +import org.openide.util.Lookup; + +/** + * A provider for code actions for a given document and range. + * + * @author Dusan Balek + * @since 1.23 + */ +public interface CodeActionProvider { + + /** + * Computes code actions for a given document and range + * @param doc a text document + * @param range a range inside the text document + * @param context a context carrying additional information. + * @return a list of {@link CodeAction} instances + * @since 1.23 + */ + public List<CodeAction> getCodeActions(@NonNull Document doc, @NonNull Range range, @NonNull Lookup context); +} diff --git a/java/java.lsp.server/nbproject/project.xml b/java/java.lsp.server/nbproject/project.xml index 8fcbf4da7a..24a039f7f8 100644 --- a/java/java.lsp.server/nbproject/project.xml +++ b/java/java.lsp.server/nbproject/project.xml @@ -136,7 +136,7 @@ <compile-dependency/> <run-dependency> <release-version>1</release-version> - <specification-version>1.18</specification-version> + <specification-version>1.23</specification-version> </run-dependency> </dependency> <dependency> diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/db/DBConnectionProvider.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/db/DBConnectionProvider.java index 239890a9e8..9da0614d30 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/db/DBConnectionProvider.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/db/DBConnectionProvider.java @@ -47,21 +47,17 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.logging.Logger; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.CodeActionParams; import org.netbeans.api.db.explorer.ConnectionManager; import org.netbeans.api.db.explorer.DatabaseConnection; -import org.netbeans.modules.java.lsp.server.protocol.CodeActionsProvider; -import org.netbeans.modules.java.lsp.server.protocol.NbCodeLanguageClient; -import org.netbeans.modules.parsing.api.ResultIterator; +import org.netbeans.spi.lsp.CommandProvider; import org.openide.util.lookup.ServiceProvider; /** * * @author Jan Horvath */ -@ServiceProvider(service = CodeActionsProvider.class) -public class DBConnectionProvider extends CodeActionsProvider{ +@ServiceProvider(service = CommandProvider.class) +public class DBConnectionProvider implements CommandProvider { private static final Logger LOG = Logger.getLogger(DBConnectionProvider.class.getName()); private static final String GET_DB_CONNECTION = "nbls.db.connection"; //NOI18N @@ -81,12 +77,7 @@ public class DBConnectionProvider extends CodeActionsProvider{ } @Override - public List<CodeAction> getCodeActions(NbCodeLanguageClient client, ResultIterator resultIterator, CodeActionParams params) throws Exception { - return Collections.emptyList(); - } - - @Override - public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) { + public CompletableFuture<Object> runCommand(String command, List<Object> arguments) { Map<String, String> result = new HashMap<> (); CompletableFuture ret = new CompletableFuture(); Properties dbProps = new Properties(); diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/explorer/NodePropertiesProvider.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/explorer/NodePropertiesProvider.java index f20e40acc9..10e779fb77 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/explorer/NodePropertiesProvider.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/explorer/NodePropertiesProvider.java @@ -25,7 +25,6 @@ import com.google.gson.JsonNull; import com.google.gson.JsonPrimitive; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,11 +34,7 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.logging.Logger; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.CodeActionParams; -import org.netbeans.modules.java.lsp.server.protocol.CodeActionsProvider; -import org.netbeans.modules.java.lsp.server.protocol.NbCodeLanguageClient; -import org.netbeans.modules.parsing.api.ResultIterator; +import org.netbeans.spi.lsp.CommandProvider; import org.openide.nodes.Node; import org.openide.util.Lookup; import org.openide.util.lookup.ServiceProvider; @@ -48,8 +43,8 @@ import org.openide.util.lookup.ServiceProvider; * * @author Tomas Hurka */ -@ServiceProvider(service = CodeActionsProvider.class) -public class NodePropertiesProvider extends CodeActionsProvider { +@ServiceProvider(service = CommandProvider.class) +public class NodePropertiesProvider implements CommandProvider { private static final Logger LOG = Logger.getLogger(NodePropertiesProvider.class.getName()); private static final String COMMAND_PREFIX = "nbls."; @@ -76,12 +71,7 @@ public class NodePropertiesProvider extends CodeActionsProvider { private final Gson gson = new Gson(); @Override - public List<CodeAction> getCodeActions(NbCodeLanguageClient client, ResultIterator resultIterator, CodeActionParams params) throws Exception { - return Collections.emptyList(); - } - - @Override - public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) { + public CompletableFuture<Object> runCommand(String command, List<Object> arguments) { if (arguments == null || arguments.isEmpty()) { return CompletableFuture.completedFuture(null); } diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2CommandProviderBridge.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2CommandProviderBridge.java deleted file mode 100644 index fc2410338f..0000000000 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2CommandProviderBridge.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.CodeActionParams; -import org.netbeans.modules.parsing.api.ResultIterator; -import org.netbeans.spi.lsp.CommandProvider; -import org.openide.util.Lookup; -import org.openide.util.lookup.ServiceProvider; - -@ServiceProvider(service=CodeActionsProvider.class) -public class CodeActionsProvider2CommandProviderBridge extends CodeActionsProvider { - - @Override - public Set<String> getCommands() { - Set<String> allCommands = new HashSet<>(); - - for (CommandProvider cmdProvider : Lookup.getDefault().lookupAll(CommandProvider.class)) { - allCommands.addAll(cmdProvider.getCommands()); - } - - return allCommands; - } - - @Override - public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) { - for (CommandProvider cmdProvider : Lookup.getDefault().lookupAll(CommandProvider.class)) { - if (cmdProvider.getCommands().contains(command)) { - return cmdProvider.runCommand(command, arguments); - } - } - - return CompletableFuture.completedFuture(null); - } - - @Override - public List<CodeAction> getCodeActions(NbCodeLanguageClient client, ResultIterator resultIterator, CodeActionParams params) throws Exception { - return Collections.emptyList(); - } - -} diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2LspApiBridge.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2LspApiBridge.java new file mode 100644 index 0000000000..a901cf1a5d --- /dev/null +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/CodeActionsProvider2LspApiBridge.java @@ -0,0 +1,124 @@ +/* + * 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.JsonObject; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import javax.swing.text.Document; +import javax.swing.text.StyledDocument; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionParams; +import org.eclipse.lsp4j.MessageParams; +import org.eclipse.lsp4j.MessageType; +import org.netbeans.api.lsp.LazyCodeAction; +import org.netbeans.api.lsp.WorkspaceEdit; +import org.netbeans.modules.java.lsp.server.Utils; +import org.netbeans.modules.parsing.api.ResultIterator; +import org.netbeans.spi.lsp.CodeActionProvider; +import org.netbeans.spi.lsp.CommandProvider; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ServiceProvider; + +@ServiceProvider(service=CodeActionsProvider.class, position = 5) +public class CodeActionsProvider2LspApiBridge extends CodeActionsProvider { + + private static final String URL = "url";// NOI18N + private static final String INDEX = "index";// NOI18N + private List<LazyCodeAction> lastCodeActions = null; + + @Override + public Set<String> getCommands() { + Set<String> allCommands = new HashSet<>(); + for (CommandProvider cmdProvider : Lookup.getDefault().lookupAll(CommandProvider.class)) { + allCommands.addAll(cmdProvider.getCommands()); + } + return allCommands; + } + + @Override + public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) { + for (CommandProvider cmdProvider : Lookup.getDefault().lookupAll(CommandProvider.class)) { + if (cmdProvider.getCommands().contains(command)) { + return cmdProvider.runCommand(command, arguments); + } + } + return CompletableFuture.completedFuture(false); + } + + @Override + public List<CodeAction> getCodeActions(NbCodeLanguageClient client, ResultIterator resultIterator, CodeActionParams params) throws Exception { + lastCodeActions = new ArrayList<>(); + List<CodeAction> allActions = new ArrayList<>(); + Document doc = resultIterator.getSnapshot().getSource().getDocument(false); + if (doc instanceof StyledDocument) { + String uri = params.getTextDocument().getUri(); + int startOffset = Utils.getOffset((StyledDocument) doc, params.getRange().getStart()); + int endOffset = Utils.getOffset((StyledDocument) doc, params.getRange().getEnd()); + org.netbeans.api.lsp.Range r = new org.netbeans.api.lsp.Range(startOffset, endOffset); + List<String> only = params.getContext().getOnly(); + Lookup l = only != null ? Lookups.fixed(client, resultIterator, only) : Lookups.fixed(client, resultIterator); + for (CodeActionProvider caProvider : Lookup.getDefault().lookupAll(CodeActionProvider.class)) { + try { + for (org.netbeans.api.lsp.CodeAction ca : caProvider.getCodeActions(doc, r, l)) { + Object data = null; + String command = ca.getCommand() != null ? ca.getCommand().getCommand() : null; + WorkspaceEdit edit = null; + if (ca instanceof LazyCodeAction && ((LazyCodeAction) ca).getLazyEdit() != null) { + HashMap<String, Object> map = new HashMap<>(); + map.put(URL, uri); + map.put(INDEX, lastCodeActions.size()); + lastCodeActions.add((LazyCodeAction) ca); + data = map; + } else if (ca.getEdit() != null) { + edit = ca.getEdit(); + } + CodeAction codeAction = createCodeAction(client, ca.getTitle(), ca.getKind(), data, command, command != null ? ca.getCommand().getArguments() : null); + if (edit != null) { + codeAction.setEdit(TextDocumentServiceImpl.fromAPI(edit, uri, client)); + } + allActions.add(codeAction); + } + } catch (Exception ex) { + client.logMessage(new MessageParams(MessageType.Error, ex.getMessage())); + } + } + } + return allActions; + } + + @Override + public CompletableFuture<CodeAction> resolve(NbCodeLanguageClient client, CodeAction codeAction, Object data) { + if (data instanceof JsonObject) { + JsonObject obj = (JsonObject) data; + if (obj.has(URL) && obj.has(INDEX)) { + LazyCodeAction inputAction = lastCodeActions.get(obj.getAsJsonPrimitive(INDEX).getAsInt()); + if (inputAction != null) { + codeAction.setEdit(TextDocumentServiceImpl.fromAPI(inputAction.getLazyEdit().get(), obj.getAsJsonPrimitive(URL).getAsString(), client)); + } + } + } + return CompletableFuture.completedFuture(codeAction); + } +} 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 d3066f1a24..a21dd42572 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 @@ -1017,35 +1017,7 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli data.put(INDEX, index.getAndIncrement()); action.setData(data); } else if (inputAction.getEdit() != null) { - org.netbeans.api.lsp.WorkspaceEdit edit = inputAction.getEdit(); - List<Either<TextDocumentEdit, ResourceOperation>> documentChanges = new ArrayList<>(); - for (Union2<org.netbeans.api.lsp.TextDocumentEdit, org.netbeans.api.lsp.ResourceOperation> parts : edit.getDocumentChanges()) { - if (parts.hasFirst()) { - String docUri = parts.first().getDocument(); - try { - FileObject file = Utils.fromUri(docUri); - if (file == null) { - file = Utils.fromUri(params.getTextDocument().getUri()); - } - FileObject fo = file; - if (fo != null) { - List<TextEdit> edits = parts.first().getEdits().stream().map(te -> new TextEdit(new Range(Utils.createPosition(fo, te.getStartOffset()), Utils.createPosition(fo, te.getEndOffset())), te.getNewText())).collect(Collectors.toList()); - TextDocumentEdit tde = new TextDocumentEdit(new VersionedTextDocumentIdentifier(docUri, -1), edits); - documentChanges.add(Either.forLeft(tde)); - } - } catch (Exception ex) { - client.logMessage(new MessageParams(MessageType.Error, ex.getMessage())); - } - } else { - if (parts.second() instanceof org.netbeans.api.lsp.ResourceOperation.CreateFile) { - documentChanges.add(Either.forRight(new CreateFile(((org.netbeans.api.lsp.ResourceOperation.CreateFile) parts.second()).getNewFile()))); - } else { - throw new IllegalStateException(String.valueOf(parts.second())); - } - } - } - - action.setEdit(new WorkspaceEdit(documentChanges)); + action.setEdit(fromAPI(inputAction.getEdit(), uri, client)); } result.add(Either.forRight(action)); } @@ -1133,51 +1105,37 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli @Override public CompletableFuture<CodeAction> resolveCodeAction(CodeAction unresolved) { - JsonObject data = (JsonObject) unresolved.getData(); - if (data.has(CodeActionsProvider.CODE_ACTIONS_PROVIDER_CLASS)) { - String providerClass = ((JsonObject) data).getAsJsonPrimitive(CodeActionsProvider.CODE_ACTIONS_PROVIDER_CLASS).getAsString(); - for (CodeActionsProvider codeGenerator : Lookup.getDefault().lookupAll(CodeActionsProvider.class)) { - try { + CompletableFuture<CodeAction> future = new CompletableFuture<>(); + BACKGROUND_TASKS.post(() -> { + JsonObject data = (JsonObject) unresolved.getData(); + if (data.has(CodeActionsProvider.CODE_ACTIONS_PROVIDER_CLASS)) { + String providerClass = data.getAsJsonPrimitive(CodeActionsProvider.CODE_ACTIONS_PROVIDER_CLASS).getAsString(); + for (CodeActionsProvider codeGenerator : Lookup.getDefault().lookupAll(CodeActionsProvider.class)) { if (codeGenerator.getClass().getName().equals(providerClass)) { - return codeGenerator.resolve(client, unresolved, ((JsonObject) data).get(CodeActionsProvider.DATA)); - } - } catch (Exception ex) { - } - } - } else if (data.has(URL) && data.has(INDEX)) { - LazyCodeAction inputAction = lastCodeActions.get(data.getAsJsonPrimitive(INDEX).getAsInt()); - if (inputAction != null) { - org.netbeans.api.lsp.WorkspaceEdit edit = inputAction.getLazyEdit().get(); - List<Either<TextDocumentEdit, ResourceOperation>> documentChanges = new ArrayList<>(); - for (Union2<org.netbeans.api.lsp.TextDocumentEdit, org.netbeans.api.lsp.ResourceOperation> parts : edit.getDocumentChanges()) { - if (parts.hasFirst()) { - String docUri = parts.first().getDocument(); try { - FileObject file = Utils.fromUri(docUri); - if (file == null) { - file = Utils.fromUri(data.getAsJsonPrimitive(URL).getAsString()); - } - FileObject fo = file; - if (fo != null) { - List<TextEdit> edits = parts.first().getEdits().stream().map(te -> new TextEdit(new Range(Utils.createPosition(fo, te.getStartOffset()), Utils.createPosition(fo, te.getEndOffset())), te.getNewText())).collect(Collectors.toList()); - TextDocumentEdit tde = new TextDocumentEdit(new VersionedTextDocumentIdentifier(docUri, -1), edits); - documentChanges.add(Either.forLeft(tde)); - } - } catch (Exception ex) { - client.logMessage(new MessageParams(MessageType.Error, ex.getMessage())); - } - } else { - if (parts.second() instanceof org.netbeans.api.lsp.ResourceOperation.CreateFile) { - documentChanges.add(Either.forRight(new CreateFile(((org.netbeans.api.lsp.ResourceOperation.CreateFile) parts.second()).getNewFile()))); - } else { - throw new IllegalStateException(String.valueOf(parts.second())); + codeGenerator.resolve(client, unresolved, data.get(CodeActionsProvider.DATA)).thenAccept(action -> { + future.complete(action); + }); + } catch (Exception e) { + future.completeExceptionally(e); } + return; + } + } + } else if (data.has(URL) && data.has(INDEX)) { + LazyCodeAction inputAction = lastCodeActions.get(data.getAsJsonPrimitive(INDEX).getAsInt()); + if (inputAction != null) { + try { + unresolved.setEdit(fromAPI(inputAction.getLazyEdit().get(), data.getAsJsonPrimitive(URL).getAsString(), client)); + } catch (Exception e) { + future.completeExceptionally(e); + return; } } - unresolved.setEdit(new WorkspaceEdit(documentChanges)); } - } - return CompletableFuture.completedFuture(unresolved); + future.complete(unresolved); + }); + return future; } @NbBundle.Messages({"# {0} - method name", "LBL_Run=Run {0}", @@ -2204,7 +2162,37 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli } } - public static List<TextEdit> modify2TextEdits(JavaSource js, Task<WorkingCopy> task) throws IOException {//TODO: is this still used? + static WorkspaceEdit fromAPI(org.netbeans.api.lsp.WorkspaceEdit edit, String uri, NbCodeLanguageClient client) { + List<Either<TextDocumentEdit, ResourceOperation>> documentChanges = new ArrayList<>(); + for (Union2<org.netbeans.api.lsp.TextDocumentEdit, org.netbeans.api.lsp.ResourceOperation> parts : edit.getDocumentChanges()) { + if (parts.hasFirst()) { + String docUri = parts.first().getDocument(); + try { + FileObject file = Utils.fromUri(docUri); + if (file == null) { + file = Utils.fromUri(uri); + } + FileObject fo = file; + if (fo != null) { + List<TextEdit> edits = parts.first().getEdits().stream().map(te -> new TextEdit(new Range(Utils.createPosition(fo, te.getStartOffset()), Utils.createPosition(fo, te.getEndOffset())), te.getNewText())).collect(Collectors.toList()); + TextDocumentEdit tde = new TextDocumentEdit(new VersionedTextDocumentIdentifier(docUri, -1), edits); + documentChanges.add(Either.forLeft(tde)); + } + } catch (Exception ex) { + client.logMessage(new MessageParams(MessageType.Error, ex.getMessage())); + } + } else { + if (parts.second() instanceof org.netbeans.api.lsp.ResourceOperation.CreateFile) { + documentChanges.add(Either.forRight(new CreateFile(((org.netbeans.api.lsp.ResourceOperation.CreateFile) parts.second()).getNewFile()))); + } else { + throw new IllegalStateException(String.valueOf(parts.second())); + } + } + } + return new WorkspaceEdit(documentChanges); + } + + static List<TextEdit> modify2TextEdits(JavaSource js, Task<WorkingCopy> task) throws IOException {//TODO: is this still used? FileObject[] file = new FileObject[1]; LineMap[] lm = new LineMap[1]; ModificationResult changes = js.runModificationTask(wc -> { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists