You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2021/01/08 18:17:38 UTC

[netbeans] branch master updated: LSP - Go to definition enhanced with possible sources download. (#2649)

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 fe9ebc9  LSP - Go to definition enhanced with possible sources download. (#2649)
fe9ebc9 is described below

commit fe9ebc9d22832cf82c5d9408ad25b5bd8e10b466
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Fri Jan 8 19:17:16 2021 +0100

    LSP - Go to definition enhanced with possible sources download. (#2649)
---
 .../netbeans/modules/editor/java/GoToSupport.java  | 15 ++++--
 .../queries/DefaultSourceLevelQueryImpl.java       |  2 +-
 .../queries/SourceJavadocAttacherUtil.java         | 51 +++++++++++-------
 java/java.lsp.server/nbproject/project.xml         |  8 +++
 .../server/protocol/TextDocumentServiceImpl.java   | 62 ++++++++++++++++++++++
 5 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java b/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
index f50ccdb..0d83bbf 100644
--- a/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
+++ b/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java
@@ -201,7 +201,7 @@ public class GoToSupport {
                     Context resolved = resolveContext(controller, doc, offset, goToSource, false);
 
                     if (resolved == null) {
-                        target[0] = new GoToTarget(-1, -1, null, null, null, false);
+                        target[0] = new GoToTarget(-1, -1, null, null, null, null, false);
                         return;
                     }
                     
@@ -210,7 +210,7 @@ public class GoToSupport {
                         if (url != null) {
                             HtmlBrowser.URLDisplayer.getDefault().showURL(url);
                         } else {
-                            target[0] = new GoToTarget(-1, -1, null, null, null, false);
+                            target[0] = new GoToTarget(-1, -1, null, null, null, null, false);
                         }
                     } else {
                         target[0] = computeGoToTarget(controller, resolved, offset);
@@ -255,7 +255,7 @@ public class GoToSupport {
             if (startPos != (-1)) {
                 //check if the caret is inside the declaration itself, as jump in this case is not very usefull:
                 if (isCaretInsideDeclarationName(controller, tree, elpath, offset)) {
-                    return new GoToTarget(-1, -1, null, null, null, false);
+                    return new GoToTarget(-1, -1, null, null, null, null, false);
                 } else {
                     long endPos = controller.getTrees().getSourcePositions().getEndPosition(controller.getCompilationUnit(), tree);
                     //#71272: it is necessary to translate the offset:
@@ -263,17 +263,20 @@ public class GoToSupport {
                                           controller.getSnapshot().getOriginalOffset((int) endPos),
                                           null,
                                           null,
+                                          null,
                                           controller.getElementUtilities().getElementName(resolved.resolved, false).toString(),
                                           true);
                 }
             } else {
-                return new GoToTarget(-1, -1, null, null, null, false);
+                return new GoToTarget(-1, -1, null, null, null, null, false);
             }
         } else {
+            TypeElement te = resolved.resolved != null ? controller.getElementUtilities().outermostTypeElement(resolved.resolved) : null;
             return new GoToTarget(-1,
                                   -1,
                                   controller.getClasspathInfo(),
                                   ElementHandle.create(resolved.resolved),
+                                  te != null ? te.getQualifiedName().toString().replace('.', '/') + ".class" : null,
                                   controller.getElementUtilities().getElementName(resolved.resolved, false).toString(),
                                   true);
         }
@@ -284,14 +287,16 @@ public class GoToSupport {
         public final int endPos;
         public final ClasspathInfo cpInfo;
         public final ElementHandle elementToOpen;
+        public final String resourceName;
         public final String displayNameForError;
         public final boolean success;
 
-        public GoToTarget(int offsetToOpen, int endPos, ClasspathInfo cpInfo, ElementHandle elementToOpen, String displayNameForError, boolean success) {
+        public GoToTarget(int offsetToOpen, int endPos, ClasspathInfo cpInfo, ElementHandle elementToOpen, String resourceName, String displayNameForError, boolean success) {
             this.offsetToOpen = offsetToOpen;
             this.endPos = endPos;
             this.cpInfo = cpInfo;
             this.elementToOpen = elementToOpen;
+            this.resourceName = resourceName;
             this.displayNameForError = displayNameForError;
             this.success = success;
         }
diff --git a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceLevelQueryImpl.java b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceLevelQueryImpl.java
index e600684..ea3a48f 100644
--- a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceLevelQueryImpl.java
+++ b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/DefaultSourceLevelQueryImpl.java
@@ -205,7 +205,7 @@ public class DefaultSourceLevelQueryImpl implements SourceLevelQueryImplementati
                     .map((xt) -> xt.toString())
                     .orElse(pkg);
             }
-        } catch (IOException ioe) {
+        } catch (Exception e) {
             //TODO: Log & pass
         }
         return pkg;
diff --git a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SourceJavadocAttacherUtil.java b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SourceJavadocAttacherUtil.java
index 2b3d632..1c2dcc9 100644
--- a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SourceJavadocAttacherUtil.java
+++ b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/queries/SourceJavadocAttacherUtil.java
@@ -18,14 +18,17 @@
  */
 package org.netbeans.modules.java.j2seplatform.queries;
 
+import java.awt.GraphicsEnvironment;
 import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
 import javax.swing.JFileChooser;
 import javax.swing.filechooser.FileFilter;
 import org.netbeans.api.annotations.common.CheckForNull;
@@ -34,7 +37,6 @@ import org.netbeans.api.annotations.common.NullAllowed;
 import org.netbeans.api.java.queries.SourceJavadocAttacher.AttachmentListener;
 import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
 import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation;
-import org.netbeans.spi.java.queries.SourceJavadocAttacherImplementation.Definer;
 import org.openide.DialogDescriptor;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
@@ -111,23 +113,36 @@ public final class SourceJavadocAttacherUtil {
         assert root != null;
         assert browseCall != null;
         assert convertor != null;
-        final SelectRootsPanel selectSources = new SelectRootsPanel(
-                SelectRootsPanel.SOURCES,
-                root,
-                attachedRoots,
-                browseCall,
-                convertor,
-                plugin);
-        final DialogDescriptor dd = new DialogDescriptor(selectSources, Bundle.TXT_SelectSources());
-        dd.setButtonListener(selectSources);
-        if (DialogDisplayer.getDefault().notify(dd) == DialogDescriptor.OK_OPTION) {
-            try {
-                return selectSources.getRoots();
-            } catch (Exception e) {
-                DialogDisplayer.getDefault().notify(
-                        new NotifyDescriptor.Message(
-                            Bundle.TXT_InvalidSourceRoot(),
-                            NotifyDescriptor.ERROR_MESSAGE));
+        if (GraphicsEnvironment.isHeadless()) {
+            List<? extends URI> sources = plugin.getSources(root, () -> false).stream().map(url -> {
+                try {
+                    return url.toURI();
+                } catch (URISyntaxException ex) {
+                }
+                return null;
+            }).filter(uri -> uri != null).collect(Collectors.toList());
+            if (!sources.isEmpty()) {
+                return sources;
+            }
+        } else {
+            final SelectRootsPanel selectSources = new SelectRootsPanel(
+                    SelectRootsPanel.SOURCES,
+                    root,
+                    attachedRoots,
+                    browseCall,
+                    convertor,
+                    plugin);
+            final DialogDescriptor dd = new DialogDescriptor(selectSources, Bundle.TXT_SelectSources());
+            dd.setButtonListener(selectSources);
+            if (DialogDisplayer.getDefault().notify(dd) == DialogDescriptor.OK_OPTION) {
+                try {
+                    return selectSources.getRoots();
+                } catch (Exception e) {
+                    DialogDisplayer.getDefault().notify(
+                            new NotifyDescriptor.Message(
+                                Bundle.TXT_InvalidSourceRoot(),
+                                NotifyDescriptor.ERROR_MESSAGE));
+                }
             }
         }
         return null;
diff --git a/java/java.lsp.server/nbproject/project.xml b/java/java.lsp.server/nbproject/project.xml
index 834faa2..77da402 100644
--- a/java/java.lsp.server/nbproject/project.xml
+++ b/java/java.lsp.server/nbproject/project.xml
@@ -208,6 +208,14 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
+                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <implementation-version/>
+                    </run-dependency>
+                </dependency>
+                <dependency>
                     <code-name-base>org.netbeans.modules.java.source.base</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
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 fc685e2..2a55323 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
@@ -124,7 +124,10 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either;
 import org.eclipse.lsp4j.services.LanguageClient;
 import org.eclipse.lsp4j.services.LanguageClientAware;
 import org.eclipse.lsp4j.services.TextDocumentService;
+import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.api.java.lexer.JavaTokenId;
+import org.netbeans.api.java.queries.SourceJavadocAttacher;
+import org.netbeans.api.java.source.ClasspathInfo;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.CompilationInfo;
 import org.netbeans.api.java.source.CompilationInfo.CacheClearPolicy;
@@ -187,6 +190,7 @@ import org.netbeans.spi.editor.hints.EnhancedFix;
 import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.Fix;
 import org.netbeans.spi.editor.hints.LazyFixList;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
 import org.netbeans.spi.java.hints.JavaFix;
 import org.openide.cookies.EditorCookie;
 import org.openide.filesystems.FileObject;
@@ -817,6 +821,64 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli
         if (target[0] != null && target[0].success) {
             if (target[0].offsetToOpen < 0) {
                 Object[] openInfo = ElementOpenAccessor.getInstance().getOpenInfo(target[0].cpInfo, target[0].elementToOpen, new AtomicBoolean());
+                if (openInfo == null && target[0].resourceName != null) {
+                    // try to attach sources
+                    final ClassPath cp = ClassPathSupport.createProxyClassPath(
+                            target[0].cpInfo.getClassPath(ClasspathInfo.PathKind.BOOT),
+                            target[0].cpInfo.getClassPath(ClasspathInfo.PathKind.COMPILE),
+                            target[0].cpInfo.getClassPath(ClasspathInfo.PathKind.SOURCE));
+                    final FileObject resource = cp.findResource(target[0].resourceName);
+                    if (resource != null) {
+                        final FileObject root = cp.findOwnerRoot(resource);
+                        if (root != null) {
+                            final CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>> future = new CompletableFuture<>();
+                            SourceJavadocAttacher.attachSources(root.toURL(), new SourceJavadocAttacher.AttachmentListener() {
+                                @Override
+                                public void attachmentSucceeded() {
+                                    Object[] openInfo = ElementOpenAccessor.getInstance().getOpenInfo(target[0].cpInfo, target[0].elementToOpen, new AtomicBoolean());
+                                    if (openInfo != null && (int) openInfo[1] != (-1) && (int) openInfo[2] != (-1) && openInfo[3] != null) {
+                                        FileObject file = (FileObject) openInfo[0];
+                                        int start = (int) openInfo[1];
+                                        int end = (int) openInfo[2];
+                                        LineMap lm = (LineMap) openInfo[3];
+                                        future.complete(Either.forLeft(Collections.singletonList(new Location(Utils.toUri(file),
+                                                new Range(Utils.createPosition(lm, start), Utils.createPosition(lm, end))))));
+                                    }
+                                }
+                                @Override
+                                public void attachmentFailed() {
+                                    try {
+                                        FileObject generated = org.netbeans.modules.java.classfile.CodeGenerator.generateCode(target[0].cpInfo, target[0].elementToOpen);
+                                        if (generated != null) {
+                                            final int[] pos = new int[] {-1};
+                                            try {
+                                                JavaSource.create(target[0].cpInfo, generated).runUserActionTask(new Task<CompilationController>() {
+                                                    @Override public void run(CompilationController parameter) throws Exception {
+                                                        parameter.toPhase(JavaSource.Phase.RESOLVED);
+                                                        Element el = target[0].elementToOpen.resolve(parameter);
+                                                        if (el != null) {
+                                                            TreePath p = parameter.getTrees().getPath(el);
+                                                            if (p != null) {
+                                                                pos[0] = (int) parameter.getTrees().getSourcePositions().getStartPosition(p.getCompilationUnit(), p.getLeaf());
+                                                            }
+                                                        }
+                                                    }
+                                                }, true);
+                                            } catch (IOException ex) {
+                                            }
+                                            int offset = pos[0] != -1 ? pos[0] : 0;
+                                            future.complete(Either.forLeft(Collections.singletonList(new Location(Utils.toUri(generated), new Range(Utils.createPosition(generated, offset), Utils.createPosition(generated, offset))))));
+                                            return;
+                                        }
+                                    } catch (Exception e) {
+                                    }
+                                    future.complete(Either.forLeft((Collections.emptyList())));
+                                }
+                            });
+                            return future;
+                        }
+                    }
+                }
                 if (openInfo != null && (int) openInfo[1] != (-1) && (int) openInfo[2] != (-1) && openInfo[3] != null) {
                     FileObject file = (FileObject) openInfo[0];
                     int start = (int) openInfo[1];


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

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