From ae5a22443e1f9ac640704e19797574e6d852d292 Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Thu, 18 May 2023 18:03:57 +0200 Subject: [PATCH 1/6] VSCode: Code completion and hover improvements. --- .../completion/JavaDocumentationTask.java | 5 ++ .../editor/java/JavaCompletionCollector.java | 12 +++- .../editor/java/JavaHoverProvider.java | 5 +- .../modules/editor/java/Utilities.java | 34 +++++++-- .../protocol/TextDocumentServiceImpl.java | 2 +- .../api/java/source/ui/ElementJavadoc.java | 70 ++++++++++++------- 6 files changed, 92 insertions(+), 36 deletions(-) diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/JavaDocumentationTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/JavaDocumentationTask.java index fc8228c13444..1ca8c0b2052f 100644 --- a/java/java.completion/src/org/netbeans/modules/java/completion/JavaDocumentationTask.java +++ b/java/java.completion/src/org/netbeans/modules/java/completion/JavaDocumentationTask.java @@ -89,6 +89,11 @@ protected void resolve(CompilationController controller) throws IOException { case ENUM_CONSTANT: case FIELD: case METHOD: + case LOCAL_VARIABLE: + case PARAMETER: + case EXCEPTION_PARAMETER: + case RESOURCE_VARIABLE: + case BINDING_VARIABLE: documentation = (T)factory.create(controller, el, cancel); } } diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java index eb5c30c403c4..1d4e9d867d5e 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java @@ -41,6 +41,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -160,7 +161,10 @@ public static Supplier getDocumentation(Document doc, int offset, Elemen JavaDocumentationTask> task = JavaDocumentationTask.create(offset, handle, new JavaDocumentationTask.DocumentationFactory>() { @Override public Future create(CompilationInfo compilationInfo, Element element, Callable cancel) { - return ElementJavadoc.create(compilationInfo, element, cancel).getTextAsync(); + ElementJavadoc doc = ElementJavadoc.create(compilationInfo, element, cancel); + return ((CompletableFuture) doc.getTextAsync()).thenApply(content -> { + return Utilities.resolveLinks(content, doc); + }); } }, () -> false); ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() { @@ -890,8 +894,10 @@ public Completion createLambdaItem(CompilationInfo info, TypeElement elem, Decla } cnt++; String paramTypeName = Utilities.getTypeName(info, tm, false, desc.isVarArgs() && !tIt.hasNext()).toString(); - String paramName = it.next().getSimpleName().toString(); - label.append(paramTypeName).append(' ').append(paramName); + VariableElement var = it.next(); + List varNames = Utilities.varNamesSuggestions(tm, var.getKind(), Collections.emptySet(), null, null, info.getTypes(), info.getElements(), Collections.emptyList(), CodeStyle.getDefault(info.getFileObject())); + String paramName = varNames.isEmpty() ? var.getSimpleName().toString() : varNames.get(0); + label.append(paramName); insertText.append("${").append(cnt).append(":").append(paramName).append("}"); sortText.append(paramTypeName); } diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java index 31ee21ef0980..4112cc93f9c4 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java @@ -47,7 +47,10 @@ public CompletableFuture getHoverContent(Document doc, int offset) { JavaDocumentationTask> task = JavaDocumentationTask.create(offset, null, new JavaDocumentationTask.DocumentationFactory>() { @Override public CompletableFuture create(CompilationInfo compilationInfo, Element element, Callable cancel) { - return (CompletableFuture) ElementJavadoc.create(compilationInfo, element, cancel).getTextAsync(); + ElementJavadoc doc = ElementJavadoc.create(compilationInfo, element, cancel); + return ((CompletableFuture) doc.getTextAsync()).thenApply(content -> { + return Utilities.resolveLinks(content, doc); + }); } }, () -> false); ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() { diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java index ef66a8d2c3aa..30ba19cd0b8e 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java @@ -44,12 +44,13 @@ import org.netbeans.api.java.source.support.ErrorAwareTreeScanner; import java.awt.Color; +import java.net.URL; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; +import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.lang.model.SourceVersion; @@ -62,7 +63,6 @@ import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.editor.mimelookup.MimeLookup; -import org.netbeans.api.editor.settings.SimpleValueNames; import org.netbeans.api.java.lexer.JavaTokenId; import org.netbeans.api.java.source.CodeStyle; import org.netbeans.api.java.source.CodeStyleUtils; @@ -72,6 +72,7 @@ import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.api.java.source.TypeUtilities.TypeNameOptions; import org.netbeans.api.java.source.support.ReferencesCount; +import org.netbeans.api.java.source.ui.ElementJavadoc; import org.netbeans.api.lexer.InputAttributes; import org.netbeans.api.lexer.Language; import org.netbeans.api.lexer.LanguagePath; @@ -93,6 +94,7 @@ public final class Utilities { private static final String ERROR = ""; //NOI18N + private static final Pattern LINK_PATTERN = Pattern.compile("(.*?)<\\/a>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static boolean guessMethodArguments = CodeCompletionPanel.GUESS_METHOD_ARGUMENTS_DEFAULT; private static boolean autoPopupOnJavaIdentifierPart = CodeCompletionPanel.JAVA_AUTO_POPUP_ON_IDENTIFIER_PART_DEFAULT; @@ -572,7 +574,11 @@ private static List varNamesForType(TypeMirror type, Types types, Elemen if ("Iterator".equals(tn)) //NOI18N al.add("it"); //NOI18N while((tn = nextName(tn)).length() > 0) { - al.add(tn); + if (SourceVersion.isKeyword(tn)) { + al.add('a' + tn.substring(0, 1).toUpperCase() + tn.substring(1)); + } else { + al.add(tn); + } sb.append(tn.charAt(0)); } if (sb.length() > 0) { @@ -592,7 +598,11 @@ private static List varNamesForType(TypeMirror type, Types types, Elemen if ("Iterator".equals(tn)) //NOI18N al.add("it"); //NOI18N while((tn = nextName(tn)).length() > 0) { - al.add(tn); + if (SourceVersion.isKeyword(tn)) { + al.add('a' + tn.substring(0, 1).toUpperCase() + tn.substring(1)); + } else { + al.add(tn); + } sb.append(tn.charAt(0)); } if (iterable != null && types.isSubtype(type, iterable)) { @@ -1066,6 +1076,22 @@ private static List resolveMethod(CompilationInfo info, List< return found; } + static String resolveLinks(String content, ElementJavadoc doc) { + Matcher matcher = LINK_PATTERN.matcher(content); + String updatedContent = matcher.replaceAll(result -> { + if (result.groupCount() == 2) { + ElementJavadoc link = doc.resolveLink(result.group(1)); + URL url = link != null ? link.getURL() : null; + if (url != null) { + return "" + result.group(2) + ""; + } + return result.group(2); + } + return result.group(); + }); + return updatedContent; + } + private Utilities() { } } 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 ba2f9db63c32..51ad125c611a 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 @@ -1937,7 +1937,7 @@ private FileObject fromURI(String uri, boolean tryHard) { } missingFileDiscovered(uri); } catch (MalformedURLException ex) { - if (!uri.startsWith("untitled:")) { + if (!uri.startsWith("untitled:") && !uri.startsWith("jdt:")) { LOG.log(Level.WARNING, "Invalid file URL: " + uri, ex); } } diff --git a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java index 6d1df08284d8..3dfdd96d3f2c 100644 --- a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java +++ b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java @@ -394,11 +394,15 @@ private ElementJavadoc resolveElement( public Action getGotoSourceAction() { return goToSource; } - + private ElementJavadoc(CompilationInfo compilationInfo, Element element, final URL url, final Callable cancel) { this.cpInfo = compilationInfo.getClasspathInfo(); this.fileObject = compilationInfo.getFileObject(); - this.handle = element == null ? null : ElementHandle.create(element); + ElementHandle eh = null; + try { + eh = element == null ? null : ElementHandle.create(element); + } catch (IllegalArgumentException iae) {} + this.handle = eh; this.cancel = cancel; this.packageName = compilationInfo.getCompilationUnit().getPackageName() != null ? compilationInfo.getCompilationUnit().getPackageName().toString() : ""; @@ -406,6 +410,10 @@ private ElementJavadoc(CompilationInfo compilationInfo, Element element, final U this.className = compilationInfo.getCompilationUnit().getSourceFile().getName().replaceFirst("[.][^.]+$", ""); final StringBuilder header = getElementHeader(element, compilationInfo); + if (handle == null) { + this.content = CompletableFuture.completedFuture(header.toString()); + return; + } try { //Optimisitic no http CharSequence doc = getElementDoc(element, compilationInfo, header, url, true); @@ -465,22 +473,30 @@ private ElementJavadoc(final String message, final Callable cancel) { private StringBuilder getElementHeader(final Element element, final CompilationInfo info) { final StringBuilder sb = new StringBuilder(); if (element != null) { - sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); switch(element.getKind()) { case METHOD: case CONSTRUCTOR: + sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); sb.append(getMethodHeader((ExecutableElement)element)); break; case FIELD: case ENUM_CONSTANT: + sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); sb.append(getFieldHeader((VariableElement)element)); break; case CLASS: case INTERFACE: case ENUM: case ANNOTATION_TYPE: + sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); sb.append(getClassHeader((TypeElement)element)); break; + case LOCAL_VARIABLE: + case PARAMETER: + case EXCEPTION_PARAMETER: + case RESOURCE_VARIABLE: + sb.append(getFieldHeader((VariableElement)element)); + break; case PACKAGE: sb.append(getPackageHeader((PackageElement)element)); break; @@ -494,26 +510,24 @@ private StringBuilder getElementHeader(final Element element, final CompilationI private StringBuilder getContainingClassOrPackageHeader(Element el, Elements elements, ElementUtilities eu) { StringBuilder sb = new StringBuilder(); - if (el.getKind() != ElementKind.PACKAGE && el.getKind() != ElementKind.MODULE) { - TypeElement cls = eu.enclosingTypeElement(el); - if (cls != null) { - switch(cls.getEnclosingElement().getKind()) { - case ANNOTATION_TYPE: - case CLASS: - case ENUM: - case INTERFACE: - case PACKAGE: - sb.append(""); //NOI18N - createLink(sb, cls, makeNameLineBreakable(cls.getQualifiedName().toString())); - sb.append(""); //NOI18N) - } - } else { - PackageElement pkg = elements.getPackageOf(el); - if (pkg != null) { + TypeElement cls = eu.enclosingTypeElement(el); + if (cls != null) { + switch(cls.getEnclosingElement().getKind()) { + case ANNOTATION_TYPE: + case CLASS: + case ENUM: + case INTERFACE: + case PACKAGE: sb.append(""); //NOI18N - createLink(sb, pkg, makeNameLineBreakable(pkg.getQualifiedName().toString())); + createLink(sb, cls, makeNameLineBreakable(cls.getQualifiedName().toString())); sb.append(""); //NOI18N) - } + } + } else { + PackageElement pkg = elements.getPackageOf(el); + if (pkg != null) { + sb.append(""); //NOI18N + createLink(sb, pkg, makeNameLineBreakable(pkg.getQualifiedName().toString())); + sb.append(""); //NOI18N) } } return sb; @@ -2126,12 +2140,14 @@ private void assignSource( if (docURL == null && goToSource == null) { content.insert(0, ""); //NOI18N } - goToSource = new AbstractAction() { - @Override - public void actionPerformed(ActionEvent evt) { - ElementOpen.open(fo, handle); - } - }; + if (handle != null) { + goToSource = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent evt) { + ElementOpen.open(fo, handle); + } + }; + } } if (url != null) { docURL = url; From 2e970e43a4c6429f25babe16df5601f451080249 Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Thu, 18 May 2023 18:05:07 +0200 Subject: [PATCH 2/6] Default JavaDoc links updated. --- .../platformdefinition/J2SEPlatformDefaultJavadocImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java index 30369b12dade..0cc007ec0398 100644 --- a/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java +++ b/java/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/J2SEPlatformDefaultJavadocImpl.java @@ -68,7 +68,7 @@ public final class J2SEPlatformDefaultJavadocImpl implements J2SEPlatformDefault if (now.isAfter(jdk9)) { // time traveler -> only java 8 doc for you int jdk = 9; for (LocalDate t = jdk9; t.isBefore(now); t = t.plusMonths(6)) { - OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://docs.oracle.com/javase/" + jdk + "/docs/api/"); // NOI18N + OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://docs.oracle.com/en/java/javase/" + jdk + "/docs/api/"); // NOI18N jdk++; } OFFICIAL_JAVADOC.put(String.valueOf(jdk), "https://download.java.net/java/early_access/jdk" + jdk + "/docs/api/"); // NOI18N Early access From 44b423638bd7a456f050f8bb31a3058c2aa35f4c Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Thu, 18 May 2023 18:06:11 +0200 Subject: [PATCH 3/6] Platform JavaDoc should be returned for classes originating in src.zip. --- .../java/platform/queries/PlatformJavadocForBinaryQuery.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/java.platform/src/org/netbeans/modules/java/platform/queries/PlatformJavadocForBinaryQuery.java b/java/java.platform/src/org/netbeans/modules/java/platform/queries/PlatformJavadocForBinaryQuery.java index 8ec977ace23f..39706bcf48a0 100644 --- a/java/java.platform/src/org/netbeans/modules/java/platform/queries/PlatformJavadocForBinaryQuery.java +++ b/java/java.platform/src/org/netbeans/modules/java/platform/queries/PlatformJavadocForBinaryQuery.java @@ -80,6 +80,11 @@ public JavadocForBinaryQuery.Result findJavadoc(@NonNull final URL binaryRoot) { candidates.add(jp); } } + for (ClassPath.Entry entry : jp.getSourceFolders().entries()) { + if (binaryRoot.equals(entry.getURL())) { + candidates.add(jp); + } + } } return candidates.isEmpty() ? null : new R(candidates); } From 62c3970a03796e5abf53b123566e13da6d0b8d1a Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Fri, 19 May 2023 12:50:49 +0200 Subject: [PATCH 4/6] Modified to make ServerTest pass. --- .../org/netbeans/modules/editor/java/Utilities.java | 12 +++++++----- .../modules/java/lsp/server/protocol/ServerTest.java | 6 ++---- .../netbeans/api/java/source/ui/ElementJavadoc.java | 8 ++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java index 30ba19cd0b8e..bb3e33fef9ce 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java @@ -1080,11 +1080,13 @@ static String resolveLinks(String content, ElementJavadoc doc) { Matcher matcher = LINK_PATTERN.matcher(content); String updatedContent = matcher.replaceAll(result -> { if (result.groupCount() == 2) { - ElementJavadoc link = doc.resolveLink(result.group(1)); - URL url = link != null ? link.getURL() : null; - if (url != null) { - return "" + result.group(2) + ""; - } + try { + ElementJavadoc link = doc.resolveLink(result.group(1)); + URL url = link != null ? link.getURL() : null; + if (url != null) { + return "" + result.group(2) + ""; + } + } catch (Exception ex) {} return result.group(2); } return result.group(); 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 17e784182484..ca25bce6c7de 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 @@ -400,7 +400,7 @@ public void testMain() throws Exception { assertEquals(Arrays.asList("Method:test() : void"), actualItems); assertEquals(null, actualCompletionItem.get(0).getDocumentation()); CompletionItem resolvedItem = server.getTextDocumentService().resolveCompletionItem(actualCompletionItem.get(0)).get(); - assertEquals("**[Test](*0)**\n" + + assertEquals("**Test**\n" + "\n" + "```\n" + "public void test()\n" + @@ -1386,9 +1386,7 @@ public void logMessage(MessageParams arg0) { MarkupContent content = hover.getContents().getRight(); assertNotNull(content); assertEquals(content.getKind(), "markdown"); - assertEquals(content.getValue(), "**[](*0)**\n" + - "\n" + - "```\n" + + assertEquals(content.getValue(), "```\n" + "public class Test\n" + "extends Object\n" + "```\n" + diff --git a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java index 3dfdd96d3f2c..bc9ac47adb0b 100644 --- a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java +++ b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java @@ -524,7 +524,7 @@ private StringBuilder getContainingClassOrPackageHeader(Element el, Elements ele } } else { PackageElement pkg = elements.getPackageOf(el); - if (pkg != null) { + if (pkg != null && !pkg.isUnnamed()) { sb.append(""); //NOI18N createLink(sb, pkg, makeNameLineBreakable(pkg.getQualifiedName().toString())); sb.append(""); //NOI18N) @@ -703,7 +703,11 @@ private StringBuilder getPackageHeader(PackageElement pdoc) { pdoc.getAnnotationMirrors().forEach((annotationDesc) -> { appendAnnotation(sb, annotationDesc, true); }); - sb.append("package ").append(pdoc.getQualifiedName()).append(""); //NOI18N + if (pdoc.isUnnamed()) { + sb.append("package <unnamed>"); //NOI18N + } else { + sb.append("package ").append(pdoc.getQualifiedName()).append(""); //NOI18N + } sb.append(""); //NOI18N return sb; } From ea9fbbc0217411f40a00c0f871e55c5badb3ce3e Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Fri, 19 May 2023 18:41:43 +0200 Subject: [PATCH 5/6] Links should be resolved asynchronously --- .../netbeans/modules/editor/java/JavaCompletionCollector.java | 2 +- .../src/org/netbeans/modules/editor/java/JavaHoverProvider.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java index 1d4e9d867d5e..0b69d79d4e3f 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java @@ -162,7 +162,7 @@ public static Supplier getDocumentation(Document doc, int offset, Elemen @Override public Future create(CompilationInfo compilationInfo, Element element, Callable cancel) { ElementJavadoc doc = ElementJavadoc.create(compilationInfo, element, cancel); - return ((CompletableFuture) doc.getTextAsync()).thenApply(content -> { + return ((CompletableFuture) doc.getTextAsync()).thenApplyAsync(content -> { return Utilities.resolveLinks(content, doc); }); } diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java index 4112cc93f9c4..e77478e3999e 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaHoverProvider.java @@ -48,7 +48,7 @@ public CompletableFuture getHoverContent(Document doc, int offset) { @Override public CompletableFuture create(CompilationInfo compilationInfo, Element element, Callable cancel) { ElementJavadoc doc = ElementJavadoc.create(compilationInfo, element, cancel); - return ((CompletableFuture) doc.getTextAsync()).thenApply(content -> { + return ((CompletableFuture) doc.getTextAsync()).thenApplyAsync(content -> { return Utilities.resolveLinks(content, doc); }); } From 13bde22880a9b99aa7ec82098cbcb4e58f38042a Mon Sep 17 00:00:00 2001 From: Dusan Balek Date: Fri, 19 May 2023 18:43:04 +0200 Subject: [PATCH 6/6] Doc support for records. --- .../modules/editor/java/GoToSupportTest.java | 4 +-- .../api/java/source/ui/ElementJavadoc.java | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java index 7fe0dfe82478..8deac6817b8f 100644 --- a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java +++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java @@ -1423,7 +1423,7 @@ public void testRecords2() throws Exception { }, true, false); toolTip = toolTip.replace(source.toURI().toString(), "FILE"); - assertEquals("test.​Test.​R", toolTip); + assertEquals("test.​Test.​R
int ff
", toolTip); } public void testRecords3() throws Exception { @@ -1457,7 +1457,7 @@ public void testRecords3() throws Exception { }, true, false); toolTip = toolTip.replace(source.toURI().toString(), "FILE"); - assertEquals("test.​Test", toolTip); + assertEquals("test.​Test
public record RR
", toolTip); } public void testRecords4() throws Exception { diff --git a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java index bc9ac47adb0b..a23ad14caaa6 100644 --- a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java +++ b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java @@ -119,6 +119,7 @@ import com.sun.source.tree.ImportTree; import com.sun.source.tree.Tree; import com.sun.source.util.JavacTask; +import javax.lang.model.element.RecordComponentElement; import org.netbeans.api.java.queries.SourceLevelQuery; import org.netbeans.api.java.queries.SourceLevelQuery.Profile; import org.netbeans.api.java.source.ui.snippet.MarkupTagProcessor; @@ -484,10 +485,15 @@ private StringBuilder getElementHeader(final Element element, final CompilationI sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); sb.append(getFieldHeader((VariableElement)element)); break; + case RECORD_COMPONENT: + sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); + sb.append(getRecordComponentHeader((RecordComponentElement)element)); + break; case CLASS: case INTERFACE: case ENUM: case ANNOTATION_TYPE: + case RECORD: sb.append(getContainingClassOrPackageHeader(element, info.getElements(), info.getElementUtilities())); sb.append(getClassHeader((TypeElement)element)); break; @@ -512,11 +518,12 @@ private StringBuilder getContainingClassOrPackageHeader(Element el, Elements ele StringBuilder sb = new StringBuilder(); TypeElement cls = eu.enclosingTypeElement(el); if (cls != null) { - switch(cls.getEnclosingElement().getKind()) { + switch(cls.getKind()) { case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE: + case RECORD: case PACKAGE: sb.append(""); //NOI18N createLink(sb, cls, makeNameLineBreakable(cls.getQualifiedName().toString())); @@ -629,6 +636,18 @@ private StringBuilder getFieldHeader(VariableElement fdoc) { sb.append(""); //NOI18N return sb; } + + private StringBuilder getRecordComponentHeader(RecordComponentElement rcdoc) { + StringBuilder sb = new StringBuilder(); + sb.append("
"); //NOI18N
+        rcdoc.getAnnotationMirrors().forEach((annotationDesc) -> {
+            appendAnnotation(sb, annotationDesc, true);
+        });
+        appendType(sb, rcdoc.asType(), false, false, false);
+        sb.append(" ").append(rcdoc.getSimpleName()).append(""); //NOI18N
+        sb.append("
"); //NOI18N + return sb; + } private StringBuilder getClassHeader(TypeElement cdoc) { StringBuilder sb = new StringBuilder(); @@ -642,6 +661,10 @@ private StringBuilder getClassHeader(TypeElement cdoc) { if (modifier == Modifier.FINAL) continue; break; + case RECORD: + if (modifier == Modifier.FINAL || modifier == Modifier.STATIC) + continue; + break; case INTERFACE: case ANNOTATION_TYPE: if (modifier == Modifier.ABSTRACT) @@ -660,6 +683,9 @@ private StringBuilder getClassHeader(TypeElement cdoc) { case INTERFACE: sb.append("interface "); //NOI18N break; + case RECORD: + sb.append("record "); //NOI18N + break; default: sb.append("class "); //NOI18N } @@ -676,7 +702,7 @@ private StringBuilder getClassHeader(TypeElement cdoc) { sb.append(">"); //NOI18N } sb.append("
"); //NOi18N - if (cdoc.getKind() != ElementKind.ANNOTATION_TYPE) { + if (cdoc.getKind() != ElementKind.ANNOTATION_TYPE && cdoc.getKind() != ElementKind.RECORD) { TypeMirror supercls = cdoc.getSuperclass(); if (supercls != null && supercls.getKind() != TypeKind.NONE) { sb.append("
extends "); //NOI18N