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 fa4b0f7  LSP: attempt to speed up open type action. (#3354)
fa4b0f7 is described below

commit fa4b0f70def0573f9675fc06108e13b8b6c49c0e
Author: Dusan Balek <[email protected]>
AuthorDate: Mon Dec 6 21:25:10 2021 +0100

    LSP: attempt to speed up open type action. (#3354)
---
 .../modules/java/lsp/server/protocol/Server.java   |   2 +
 .../lsp/server/protocol/WorkspaceServiceImpl.java  | 107 ++++++++++++++-------
 .../java/lsp/server/protocol/ServerTest.java       |   8 +-
 java/java.lsp.server/vscode/src/extension.ts       |  19 +++-
 .../netbeans/api/java/source/ui/ElementOpen.java   |  42 +++++---
 .../maven/queries/MavenSourceJavadocAttacher.java  |   2 +-
 6 files changed, 128 insertions(+), 52 deletions(-)

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 8d19542..ccaf4c5 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
@@ -709,6 +709,7 @@ public final class Server {
                         JAVA_NEW_PROJECT,
                         JAVA_PROJECT_CONFIGURATION_COMPLETION,
                         JAVA_SUPER_IMPLEMENTATION,
+                        JAVA_SOURCE_FOR,
                         JAVA_CLEAR_PROJECT_CACHES,
                         NATIVE_IMAGE_FIND_DEBUG_PROCESS_TO_ATTACH));
                 for (CodeActionsProvider codeActionsProvider : 
Lookup.getDefault().lookupAll(CodeActionsProvider.class)) {
@@ -854,6 +855,7 @@ public final class Server {
     public static final String JAVA_GET_PROJECT_PACKAGES = 
"java.get.project.packages";
     public static final String JAVA_LOAD_WORKSPACE_TESTS =  
"java.load.workspace.tests";
     public static final String JAVA_SUPER_IMPLEMENTATION =  
"java.super.implementation";
+    public static final String JAVA_SOURCE_FOR =  "java.source.for";
     public static final String GRAALVM_PAUSE_SCRIPT =  "graalvm.pause.script";
 
     /**
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 19f1fff..e1bfe88 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
@@ -26,7 +26,11 @@ import com.sun.source.util.TreePath;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -57,6 +61,7 @@ import org.eclipse.lsp4j.ExecuteCommandParams;
 import org.eclipse.lsp4j.Location;
 import org.eclipse.lsp4j.Position;
 import org.eclipse.lsp4j.Range;
+import org.eclipse.lsp4j.ShowDocumentParams;
 import org.eclipse.lsp4j.SymbolInformation;
 import org.eclipse.lsp4j.WorkspaceSymbolParams;
 import org.eclipse.lsp4j.services.LanguageClient;
@@ -90,6 +95,7 @@ import org.netbeans.modules.java.lsp.server.LspServerState;
 import org.netbeans.modules.java.lsp.server.Utils;
 import 
org.netbeans.modules.java.lsp.server.debugging.attach.AttachConfigurations;
 import 
org.netbeans.modules.java.lsp.server.debugging.attach.AttachNativeConfigurations;
+import org.netbeans.modules.java.source.ElementHandleAccessor;
 import org.netbeans.modules.java.source.ui.JavaSymbolProvider;
 import org.netbeans.modules.java.source.ui.JavaTypeProvider;
 import org.netbeans.modules.java.source.usages.ClassIndexImpl;
@@ -261,7 +267,50 @@ public final class WorkspaceServiceImpl implements 
WorkspaceService, LanguageCli
                 String uri = ((JsonPrimitive) 
params.getArguments().get(0)).getAsString();
                 Position pos = 
gson.fromJson(gson.toJson(params.getArguments().get(1)), Position.class);
                 return 
(CompletableFuture)((TextDocumentServiceImpl)server.getTextDocumentService()).superImplementations(uri,
 pos);
-                
+            case Server.JAVA_SOURCE_FOR: {
+                CompletableFuture<Object> result = new CompletableFuture<>();
+                try {
+                    String sourceUri = ((JsonPrimitive) 
params.getArguments().get(0)).getAsString();
+                    if (sourceUri == null || 
!sourceUri.startsWith(SOURCE_FOR)) {
+                        throw new IllegalArgumentException("Invalid uri: " + 
sourceUri);
+                    }
+                    sourceUri = 
URLDecoder.decode(sourceUri.substring(SOURCE_FOR.length()), 
StandardCharsets.UTF_8.toString());
+                    int qIdx = sourceUri.lastIndexOf('?');
+                    int hIdx = sourceUri.lastIndexOf('#');
+                    if (qIdx < 0 || hIdx < 0 || hIdx <= qIdx) {
+                        throw new IllegalArgumentException("Invalid uri: " + 
sourceUri);
+                    }
+                    String rootUri = sourceUri.substring(0, qIdx);
+                    FileObject root = 
URLMapper.findFileObject(URI.create(rootUri).toURL());
+                    if (root == null) {
+                        throw new IllegalStateException("Unable to find root: 
" + rootUri);
+                    }
+                    ElementHandle typeHandle = 
ElementHandleAccessor.getInstance().create(ElementKind.valueOf(sourceUri.substring(qIdx
 + 1, hIdx)), sourceUri.substring(hIdx + 1));
+                    CompletableFuture<ElementOpen.Location> location = 
ElementOpen.getLocation(ClasspathInfo.create(root), typeHandle, 
typeHandle.getQualifiedName().replace('.', '/') + ".class");
+                    location.exceptionally(ex -> {
+                        result.completeExceptionally(ex);
+                        return null;
+                    }).thenAccept(loc -> {
+                        if (loc != null) {
+                            ShowDocumentParams sdp = new 
ShowDocumentParams(Utils.toUri(loc.getFileObject()));
+                            Position position = 
Utils.createPosition(loc.getFileObject(), loc.getStartOffset());
+                            sdp.setSelection(new Range(position, position));
+                            client.showDocument(sdp).thenAccept(res -> {
+                                if (res.isSuccess()) {
+                                    result.complete(null);
+                                } else {
+                                    result.completeExceptionally(new 
IllegalStateException("Cannot open source for: " + 
typeHandle.getQualifiedName()));
+                                }
+                            });
+                        } else if (!result.isCompletedExceptionally()) {
+                            result.completeExceptionally(new 
IllegalStateException("Cannot find source for: " + 
typeHandle.getQualifiedName()));
+                        }
+                    });
+                } catch (Throwable t) {
+                    result.completeExceptionally(t);
+                }
+                return result;
+            }
             case Server.JAVA_FIND_PROJECT_CONFIGURATIONS: {
                 String fileUri = ((JsonPrimitive) 
params.getArguments().get(0)).getAsString();
                 
@@ -449,6 +498,10 @@ public final class WorkspaceServiceImpl implements 
WorkspaceService, LanguageCli
         return UnitTestForSourceQuery.findSources(sg.getRootFolder()).length > 
0;
     }
 
+    private static final Position NO_POS = new Position(0, 0);
+    private static final Range NO_RANGE = new Range(NO_POS, NO_POS);
+    private static final String SOURCE_FOR = "sourceFor:";
+
     @Override
     public CompletableFuture<List<? extends SymbolInformation>> 
symbol(WorkspaceSymbolParams params) {
         // shortcut: if the projects are not yet initialized, return empty:
@@ -557,9 +610,9 @@ public final class WorkspaceServiceImpl implements 
WorkspaceService, LanguageCli
                     }
                 };
                 JavaSymbolProvider.doComputeSymbols(searchType, queryFin, 
symbolHandler, true, cancel);
-                List<Pair<ElementHandle<TypeElement>, ClasspathInfo>> pairs = 
new ArrayList<>();
-                
JavaTypeProvider.ResultHandler<Pair<ElementHandle<TypeElement>, ClasspathInfo>> 
typeHandler = new 
JavaTypeProvider.ResultHandler<Pair<ElementHandle<TypeElement>, 
ClasspathInfo>>() {
-                    private ClasspathInfo cpInfo;
+                List<Pair<ElementHandle<TypeElement>, FileObject>> pairs = new 
ArrayList<>();
+                
JavaTypeProvider.ResultHandler<Pair<ElementHandle<TypeElement>, FileObject>> 
typeHandler = new 
JavaTypeProvider.ResultHandler<Pair<ElementHandle<TypeElement>, FileObject>>() {
+                    private FileObject root;
 
                     @Override
                     public void setMessage(String msg) {
@@ -575,49 +628,37 @@ public final class WorkspaceServiceImpl implements 
WorkspaceService, LanguageCli
 
                     @Override
                     public void runRoot(FileObject root, 
JavaTypeProvider.ResultHandler.Exec exec) throws IOException, 
InterruptedException {
-                        cpInfo = ClasspathInfo.create(root);
+                        this.root = root;
                         try {
                             exec.run();
                         } finally {
-                            cpInfo = null;
+                            this.root = null;
                         }
                     }
 
                     @Override
-                    public Pair<ElementHandle<TypeElement>, ClasspathInfo> 
create(JavaTypeProvider.CacheItem cacheItem, ElementHandle<TypeElement> handle, 
String simpleName, String relativePath) {
-                        return Pair.of(handle, cpInfo);
+                    public Pair<ElementHandle<TypeElement>, FileObject> 
create(JavaTypeProvider.CacheItem cacheItem, ElementHandle<TypeElement> handle, 
String simpleName, String relativePath) {
+                        return Pair.of(handle, this.root);
                     }
 
                     @Override
-                    public void addResult(List<? extends 
Pair<ElementHandle<TypeElement>, ClasspathInfo>> types) {
+                    public void addResult(List<? extends 
Pair<ElementHandle<TypeElement>, FileObject>> types) {
                         pairs.addAll(types);
                     }
                 };
                 JavaTypeProvider.doComputeTypes(searchType, queryFin, 
typeHandler, cancel);
-                Map<CompletableFuture<ElementOpen.Location>, 
ElementHandle<TypeElement>> location2Handles = new HashMap<>();
-                CompletableFuture<ElementOpen.Location>[] futures = 
pairs.stream().map(pair -> {
-                    CompletableFuture<ElementOpen.Location> future = 
ElementOpen.getLocation(pair.second(), pair.first(), 
pair.first().getQualifiedName().replace('.', '/') + ".class");
-                    location2Handles.put(future, pair.first());
-                    return future;
-                }).toArray(CompletableFuture[]::new);
-                CompletableFuture.allOf(futures).thenRun(() -> {
-                    for (CompletableFuture<ElementOpen.Location> future : 
futures) {
-                        ElementOpen.Location loc = future.getNow(null);
-                        ElementHandle<TypeElement> handle = 
location2Handles.get(future);
-                        if (loc != null && handle != null) {
-                            FileObject fo = loc.getFileObject();
-                            Location location = new Location(Utils.toUri(fo), 
new Range(Utils.createPosition(fo, loc.getStartOffset()), 
Utils.createPosition(fo, loc.getEndOffset())));
-                            String fqn = handle.getQualifiedName();
-                            int idx = fqn.lastIndexOf('.');
-                            String simpleName = idx < 0 ? fqn : 
fqn.substring(idx + 1);
-                            String contextName = idx < 0 ? null : 
fqn.substring(0, idx);
-                            SymbolInformation symbol = new 
SymbolInformation(simpleName, Utils.elementKind2SymbolKind(handle.getKind()), 
location, contextName);
-                            symbols.add(symbol);
-                        }
-                    }
-                    Collections.sort(symbols, (i1, i2) -> 
i1.getName().compareToIgnoreCase(i2.getName()));
-                    result.complete(symbols);
-                });
+                for (Pair<ElementHandle<TypeElement>, FileObject> pair : 
pairs) {
+                    ElementHandle<TypeElement> handle = pair.first();
+                    String fqn = handle.getQualifiedName();
+                    int idx = fqn.lastIndexOf('.');
+                    String simpleName = idx < 0 ? fqn : fqn.substring(idx + 1);
+                    String contextName = idx < 0 ? null : fqn.substring(0, 
idx);
+                    String uri = 
URLEncoder.encode(pair.second().toURI().toString() + '?' + 
handle.getKind().name() + '#' + handle.getBinaryName(), 
StandardCharsets.UTF_8.toString());
+                    SymbolInformation symbol = new 
SymbolInformation(simpleName, Utils.elementKind2SymbolKind(handle.getKind()), 
new Location(SOURCE_FOR + uri, NO_RANGE), contextName);
+                    symbols.add(symbol);
+                }
+                Collections.sort(symbols, (i1, i2) -> 
i1.getName().compareToIgnoreCase(i2.getName()));
+                result.complete(symbols);
             } catch (Throwable t) {
                 result.completeExceptionally(t);
             }
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 6935e5c..9fa1d07 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
@@ -1731,10 +1731,10 @@ public class ServerTest extends NbTestCase {
         indexingComplete.await();
         List<? extends SymbolInformation> symbols = 
server.getWorkspaceService().symbol(new WorkspaceSymbolParams("Tes")).get();
         List<String> actual = symbols.stream().map(si -> si.getKind() + ":" + 
si.getName() + ":" + si.getContainerName() + ":" + 
toString(si.getLocation())).collect(Collectors.toList());
-        assertEquals(Arrays.asList("Class:Test:null:Test.java:0:13-0:17",
+        assertEquals(Arrays.asList("Class:Test:null:Test:0:0-0:0",
                                    "Constructor:Test():Test:Test.java:0:7-0:7",
                                    
"Method:testMethod():Test:Test.java:2:4-2:38",
-                                   "Class:TestNested:Test:Test.java:1:24-1:34",
+                                   
"Class:TestNested:Test:Test%24TestNested:0:0-0:0",
                                    
"Constructor:TestNested():Test.TestNested:Test.java:1:18-1:18"),
                      actual);
     }
@@ -4721,6 +4721,10 @@ public class ServerTest extends NbTestCase {
     private String toString(Location location) {
         String path = location.getUri();
         String simpleName = path.substring(path.lastIndexOf('/') + 1);
+        int idx = simpleName.lastIndexOf("%23");
+        if (idx >= 0) {
+            simpleName = simpleName.substring(idx + 3);
+        }
         return simpleName + ":" + toString(location.getRange());
     }
 
diff --git a/java/java.lsp.server/vscode/src/extension.ts 
b/java/java.lsp.server/vscode/src/extension.ts
index 19446e5..77e3290 100644
--- a/java/java.lsp.server/vscode/src/extension.ts
+++ b/java/java.lsp.server/vscode/src/extension.ts
@@ -237,6 +237,10 @@ export function activate(context: ExtensionContext): 
VSNetBeansAPI {
     
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('java8+',
 debugDescriptionFactory));
     
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('nativeimage',
 debugDescriptionFactory));
 
+    // register content provider
+    let sourceForContentProvider = new NetBeansSourceForContentProvider();
+    
context.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider('sourceFor',
 sourceForContentProvider));
+
     // register commands
     context.subscriptions.push(commands.registerCommand('java.workspace.new', 
async (ctx) => {
         let c : LanguageClient = await client;
@@ -986,4 +990,17 @@ class NetBeansConfigurationNativeResolver implements 
vscode.DebugConfigurationPr
 
         return config;
     }
-}
\ No newline at end of file
+}
+
+class NetBeansSourceForContentProvider implements 
vscode.TextDocumentContentProvider {
+
+    provideTextDocumentContent(uri: vscode.Uri, token: 
vscode.CancellationToken): vscode.ProviderResult<string> {
+        vscode.window.withProgress({location: ProgressLocation.Notification, 
title: 'Finding source...', cancellable: false}, () => {
+            return vscode.commands.executeCommand('java.source.for', 
uri.toString()).then(() => {
+            }, (reason: any) => {
+                vscode.window.showErrorMessage(reason.data);
+            });
+        });
+        return Promise.reject();
+    }
+}
diff --git 
a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementOpen.java 
b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementOpen.java
index f445072..18f3dea 100644
--- a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementOpen.java
+++ b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementOpen.java
@@ -373,23 +373,35 @@ public final class ElementOpen {
                 final FileObject root = cp.findOwnerRoot(resource);
                 if (root != null) {
                     final CompletableFuture<Object[]> future = new 
CompletableFuture<>();
-                    SourceJavadocAttacher.attachSources(root.toURL(), new 
SourceJavadocAttacher.AttachmentListener() {
-                        @Override
-                        public void attachmentSucceeded() {
-                            Object[] openInfo = getOpenInfo(cpInfo, el, 
cancel);
-                            if (openInfo != null && (int) openInfo[1] != (-1) 
&& (int) openInfo[2] != (-1) && openInfo[5] != null) {
-                                future.complete(openInfo);
-                            } else {
-                                attachmentFailed();
+                    try {
+                        SourceJavadocAttacher.attachSources(root.toURL(), new 
SourceJavadocAttacher.AttachmentListener() {
+                            @Override
+                            public void attachmentSucceeded() {
+                                try {
+                                    Object[] openInfo = getOpenInfo(cpInfo, 
el, cancel);
+                                    if (openInfo != null && (int) openInfo[1] 
!= (-1) && (int) openInfo[2] != (-1) && openInfo[5] != null) {
+                                        future.complete(openInfo);
+                                    } else {
+                                        attachmentFailed();
+                                    }
+                                } catch (Throwable t) {
+                                    future.completeExceptionally(t);
+                                }
                             }
-                        }
 
-                        @Override
-                        public void attachmentFailed() {
-                            FileObject generated = 
CodeGenerator.generateCode(cpInfo, el);
-                            future.complete(generated != null ? 
getOpenInfo(generated, el, cancel) : null);
-                        }
-                    });
+                            @Override
+                            public void attachmentFailed() {
+                                try {
+                                    FileObject generated = 
CodeGenerator.generateCode(cpInfo, el);
+                                    future.complete(generated != null ? 
getOpenInfo(generated, el, cancel) : null);
+                                } catch (Throwable t) {
+                                    future.completeExceptionally(t);
+                                }
+                            }
+                        });
+                    } catch (Throwable t) {
+                        future.completeExceptionally(t);
+                    }
                     return future;
                 }
             }
diff --git 
a/java/maven/src/org/netbeans/modules/maven/queries/MavenSourceJavadocAttacher.java
 
b/java/maven/src/org/netbeans/modules/maven/queries/MavenSourceJavadocAttacher.java
index 1fa51cc..a603f5f 100644
--- 
a/java/maven/src/org/netbeans/modules/maven/queries/MavenSourceJavadocAttacher.java
+++ 
b/java/maven/src/org/netbeans/modules/maven/queries/MavenSourceJavadocAttacher.java
@@ -79,7 +79,7 @@ public class MavenSourceJavadocAttacher implements 
SourceJavadocAttacherImplemen
             message = 
StatusDisplayer.getDefault().setStatusText(Bundle.LBL_DOWNLOAD_REPO(), 
StatusDisplayer.IMPORTANCE_ERROR_HIGHLIGHT);
         } else if (file.isFile() && file.exists()) {
             List<RepositoryForBinaryQueryImpl.Coordinates> coordinates2 = 
RepositoryForBinaryQueryImpl.getJarMetadataCoordinates(file);
-            if (coordinates != null && coordinates2.size() == 1) { //only when 
non-shaded?
+            if (coordinates2 != null && coordinates2.size() == 1) { //only 
when non-shaded?
                 RepositoryForBinaryQueryImpl.Coordinates coord = 
coordinates2.get(0);
                 defined = new NBVersionInfo(null, coord.groupId, 
coord.artifactId, coord.version, null, null, null, null, null);
             }

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to