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