diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/javadoc/JavadocContentAccess2.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/javadoc/JavadocContentAccess2.java index 1d5607e6e8..9d9790c60a 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/javadoc/JavadocContentAccess2.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/javadoc/JavadocContentAccess2.java @@ -201,16 +201,44 @@ private static void collectLinkedTag(IJavaElement element, TagElement t, StringB if (t.fragments().size() > 0) { try { String[] res; - String linkTitle; + String linkTitle = null; if (t.fragments().size() == 2) { linkTitle = ((TextElement) t.fragments().get(0)).getText(); res = collectLinkElement((ASTNode) children.get(1)); } else { + res = collectLinkElement((ASTNode) children.get(0)); - if (res[0].isEmpty() && children.get(0).toString().startsWith("#") && res.length > 1) {// member implicitly refers to the current class - linkTitle = res[1]; + if (t.fragments().get(0) instanceof MethodRef methodRef) { + if (methodRef.getName().isSimpleName() && !methodRef.getName().getIdentifier().isEmpty() && methodRef.getQualifier() != null && methodRef.getQualifier().isSimpleName() + && !methodRef.getQualifier().getFullyQualifiedName().isEmpty()) { + linkTitle = methodRef.getQualifier().getFullyQualifiedName() + "." + methodRef.getName().getIdentifier(); + @SuppressWarnings("unchecked") + List params = methodRef.parameters(); + for (int i = 0; i < params.size(); i++) { + if (i == 0) { + linkTitle += "("; + } + linkTitle += params.get(i).toString(); + if (i < params.size() - 1) { + linkTitle += ", "; + } + if (i == params.size() - 1) { + linkTitle += ")"; + } + } + if (params.size() == 0) { + linkTitle += "()"; + } + + } else if (methodRef.getQualifier() == null) { + linkTitle = methodRef.getName().getIdentifier() + "()"; + } } else { - linkTitle = res[0]; + if (res[0].isEmpty() && children.get(0).toString().startsWith("#") && res.length > 1) {// member implicitly refers to the current class + linkTitle = res[1]; + } else { + linkTitle = res[0] + "." + res[1]; + } } } buf.append("[" + linkTitle + "]"); diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HoverHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HoverHandlerTest.java index fbd6a3bd22..de7a90305b 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HoverHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/HoverHandlerTest.java @@ -1124,4 +1124,92 @@ public void testHoverInlineLinkTagInMarkdown_02() throws Exception { actual = ResourceUtils.dos2Unix(actual); assertEquals(expectedJavadoc.toString(), actual.stripTrailing(), "Unexpected hover "); } + + enum HoverSignatureCase { + FIELD_REF("Ball.xxx", 3, 9), + SELF_METHOD("newMethodBeingLinkedToo()", 6, 9), + METHOD_REF("Ball.abc()", 9, 9), + CTOR_REF("Ball.Ball", 12, 9), + CTOR_X("Ball.Ball(int x)", 15, 9), + CTOR_Y("Ball.Ball(String y)", 18,9), + CTOR_MANY("Ball.Ball(String y, int i, Double x)", 21, 9); + + final String link; + final int line; + final int column; + + HoverSignatureCase(String link, int line, int column) { + this.link = link; + this.line = line; + this.column = column; + } + } + + @Test + public void testJavadocHoverShowFullSignature3690_01() throws Exception { + String name = "java25"; + importProjects("eclipse/" + name); + IProject project = getProject(name); + IJavaProject javaProject = JavaCore.create(project); + IPackageFragmentRoot packageFragmentRoot = javaProject.getPackageFragmentRoot(project.getFolder("src/main/java")); + IPackageFragment pack1 = packageFragmentRoot.createPackageFragment("test", false, null); + StringBuilder buf = new StringBuilder(); + //@formatter:off + buf.append(""" + package test; + public class Apple { + /// {@link Ball#xxx} + void foo(){} + + /// {@link #newMethodBeingLinkedToo()} + void foo1(){} + + /// {@link Ball#abc()} + void voo(){} + + /// {@link Ball#Ball} + void voo1(){} + + /// {@link Ball#Ball(int x)} + void voo2(){} + + /// {@link Ball#Ball(String y)} + void voo3(){} + + /// {@link Ball#Ball(String y, int i, Double x)} + void voo4(){} + + void newMethodBeingLinkedToo(){} + } + class Ball { + private String xxx; + Ball(int x){} + Ball(String y){} + void abc(){} + } + """); + //@formatter:on + ICompilationUnit cu = pack1.createCompilationUnit("Markdown.java", buf.toString(), false, null); + for (HoverSignatureCase hovercase : HoverSignatureCase.values()) { + enumLinkTest(cu, hovercase.line, hovercase.column, hovercase.link); + } + } + + void enumLinkTest(ICompilationUnit cu, int line, int column, String link) { + Hover hover = getHover(cu, line, column); + assertNotNull(hover); + assertEquals(3, hover.getContents().getLeft().size()); + + String actual = hover.getContents().getLeft().get(1).getLeft(); + int hashIndex = actual.lastIndexOf('#'); + int endIndex = actual.lastIndexOf(')'); + String lineNbr = actual.substring(hashIndex + 1, endIndex); + String uri = JDTUtils.toURI(cu) + "#" + lineNbr; + //@formatter:off + String expectedJavadoc = "[" + link +"](" + uri +")"; + //@formatter:on + + actual = ResourceUtils.dos2Unix(actual); + assertEquals(expectedJavadoc.toString(), actual.stripTrailing(), "Unexpected hover "); + } }