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

Reply via email to