|
| 1 | +diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java |
| 2 | +index 78fdd4caa3..f8869882aa 100644 |
| 3 | +--- a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java |
| 4 | ++++ b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java |
| 5 | +@@ -260,6 +260,8 @@ abstract class BaseTask extends UserTask { |
| 6 | + && (ts.token().id() == JavaTokenId.IDENTIFIER |
| 7 | + || ts.token().id().primaryCategory().startsWith("keyword") || //NOI18N |
| 8 | + ts.token().id().primaryCategory().startsWith("string") || //NOI18N |
| 9 | ++ ts.token().id().primaryCategory().equals("number") || //NOI18N |
| 10 | ++ ts.token().id().primaryCategory().equals("character") || //NOI18N |
| 11 | + ts.token().id().primaryCategory().equals("literal"))) { //NOI18N |
| 12 | + offset++; |
| 13 | + } |
| 14 | +@@ -279,6 +281,10 @@ abstract class BaseTask extends UserTask { |
| 15 | + treePath = treePath.getParentPath(); |
| 16 | + } |
| 17 | + } else { |
| 18 | ++ TreePath newClassPath = findNewClassForConstructorName(path); |
| 19 | ++ if (newClassPath != null) { |
| 20 | ++ path = newClassPath; |
| 21 | ++ } |
| 22 | + if (JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) { |
| 23 | + LinkedList<TreePath> reversePath = new LinkedList<>(); |
| 24 | + TreePath treePath = path; |
| 25 | +@@ -299,6 +305,34 @@ abstract class BaseTask extends UserTask { |
| 26 | + return new Env(offset, prefix, controller, path, controller.getTrees().getSourcePositions(), null); |
| 27 | + } |
| 28 | + |
| 29 | ++ private TreePath findNewClassForConstructorName(TreePath tp) { |
| 30 | ++ if (tp == null) { |
| 31 | ++ return null; |
| 32 | ++ } |
| 33 | ++ |
| 34 | ++ TreePath parentPath = tp.getParentPath(); |
| 35 | ++ |
| 36 | ++ while (parentPath != null) { |
| 37 | ++ boolean goUp = false; |
| 38 | ++ goUp = goUp || (parentPath.getLeaf().getKind() == Kind.PARAMETERIZED_TYPE && |
| 39 | ++ ((ParameterizedTypeTree) parentPath.getLeaf()).getType() == tp.getLeaf()); |
| 40 | ++ goUp = goUp || (parentPath.getLeaf().getKind() == Kind.ANNOTATED_TYPE && |
| 41 | ++ ((AnnotatedTypeTree) parentPath.getLeaf()).getUnderlyingType() == tp.getLeaf()); |
| 42 | ++ if (goUp) { |
| 43 | ++ tp = parentPath; |
| 44 | ++ parentPath = parentPath.getParentPath(); |
| 45 | ++ } else { |
| 46 | ++ break; |
| 47 | ++ } |
| 48 | ++ } |
| 49 | ++ |
| 50 | ++ if (parentPath != null && parentPath.getLeaf().getKind() == Kind.NEW_CLASS && ((NewClassTree) parentPath.getLeaf()).getIdentifier() == tp.getLeaf()) { |
| 51 | ++ return parentPath; |
| 52 | ++ } |
| 53 | ++ |
| 54 | ++ return null; |
| 55 | ++ } |
| 56 | ++ |
| 57 | + private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath path, TreePath pPath, TreePath gpPath, int offset, String prefix, boolean upToOffset) throws IOException { |
| 58 | + Tree tree = path != null ? path.getLeaf() : null; |
| 59 | + Tree parent = pPath != null ? pPath.getLeaf() : null; |
| 60 | +diff --git a/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java |
| 61 | +new file mode 100644 |
| 62 | +index 0000000000..2d85997e34 |
| 63 | +--- /dev/null |
| 64 | ++++ b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java |
| 65 | +@@ -0,0 +1,247 @@ |
| 66 | ++/* |
| 67 | ++ * Licensed to the Apache Software Foundation (ASF) under one |
| 68 | ++ * or more contributor license agreements. See the NOTICE file |
| 69 | ++ * distributed with this work for additional information |
| 70 | ++ * regarding copyright ownership. The ASF licenses this file |
| 71 | ++ * to you under the Apache License, Version 2.0 (the |
| 72 | ++ * "License"); you may not use this file except in compliance |
| 73 | ++ * with the License. You may obtain a copy of the License at |
| 74 | ++ * |
| 75 | ++ * http://www.apache.org/licenses/LICENSE-2.0 |
| 76 | ++ * |
| 77 | ++ * Unless required by applicable law or agreed to in writing, |
| 78 | ++ * software distributed under the License is distributed on an |
| 79 | ++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 80 | ++ * KIND, either express or implied. See the License for the |
| 81 | ++ * specific language governing permissions and limitations |
| 82 | ++ * under the License. |
| 83 | ++ */ |
| 84 | ++ |
| 85 | ++package org.netbeans.modules.java.completion; |
| 86 | ++ |
| 87 | ++import java.io.File; |
| 88 | ++import java.io.FileWriter; |
| 89 | ++import java.io.IOException; |
| 90 | ++import java.io.Writer; |
| 91 | ++import java.util.*; |
| 92 | ++import java.util.concurrent.Callable; |
| 93 | ++ |
| 94 | ++import javax.lang.model.element.*; |
| 95 | ++import javax.lang.model.type.ArrayType; |
| 96 | ++import javax.lang.model.type.DeclaredType; |
| 97 | ++import javax.lang.model.type.ExecutableType; |
| 98 | ++import javax.lang.model.type.TypeKind; |
| 99 | ++import javax.lang.model.type.TypeMirror; |
| 100 | ++import javax.lang.model.util.Elements; |
| 101 | ++import javax.swing.text.Document; |
| 102 | ++ |
| 103 | ++import org.netbeans.api.java.lexer.JavaTokenId; |
| 104 | ++import org.netbeans.api.java.source.*; |
| 105 | ++import org.netbeans.api.java.source.support.ReferencesCount; |
| 106 | ++import org.netbeans.api.lexer.Language; |
| 107 | ++import org.netbeans.modules.parsing.api.ParserManager; |
| 108 | ++import org.netbeans.modules.parsing.api.Source; |
| 109 | ++import org.openide.LifecycleManager; |
| 110 | ++import org.openide.cookies.EditorCookie; |
| 111 | ++import org.openide.filesystems.FileObject; |
| 112 | ++import org.openide.filesystems.FileUtil; |
| 113 | ++import org.openide.loaders.DataObject; |
| 114 | ++import org.openide.util.lookup.ServiceProvider; |
| 115 | ++import org.openide.xml.EntityCatalog; |
| 116 | ++import org.xml.sax.InputSource; |
| 117 | ++import org.xml.sax.SAXException; |
| 118 | ++ |
| 119 | ++/** |
| 120 | ++ * |
| 121 | ++ * @author Dusan Balek, Jan Lahoda |
| 122 | ++ */ |
| 123 | ++public class JavaDocumentationTaskTest extends CompletionTestBaseBase { |
| 124 | ++ |
| 125 | ++ public JavaDocumentationTaskTest(String testName) { |
| 126 | ++ super(testName, "org/netbeans/modules/java/completion/JavaDocumentationTaskTest"); |
| 127 | ++ } |
| 128 | ++ |
| 129 | ++ public void testConstructor() throws Exception { |
| 130 | ++ performTest("import java.util.*;\n" + |
| 131 | ++ "public class Test {\n" + |
| 132 | ++ " List<String> l = new Array|List();\n" + |
| 133 | ++ "}\n", |
| 134 | ++ "", |
| 135 | ++ "11", |
| 136 | ++ "[java.util.ArrayList, <init>, ()V]"); |
| 137 | ++ } |
| 138 | ++ |
| 139 | ++ public void testConstructorDiamond() throws Exception { |
| 140 | ++ performTest("import java.util.*;\n" + |
| 141 | ++ "public class Test {\n" + |
| 142 | ++ " List<String> l = new Array|List<>();\n" + |
| 143 | ++ "}\n", |
| 144 | ++ "", |
| 145 | ++ "11", |
| 146 | ++ "[java.util.ArrayList, <init>, ()V]"); |
| 147 | ++ } |
| 148 | ++ |
| 149 | ++ public void testConstructorTypeParams1() throws Exception { |
| 150 | ++ performTest("import java.util.*;\n"+ |
| 151 | ++ "public class Test {\n"+ |
| 152 | ++ " List<String> l = new Array|List<String>();\n"+ |
| 153 | ++ "}\n", |
| 154 | ++ "", |
| 155 | ++ "11", |
| 156 | ++ "[java.util.ArrayList, <init>, ()V]"); |
| 157 | ++ } |
| 158 | ++ |
| 159 | ++ public void testConstructorTypeParams2() throws Exception { |
| 160 | ++ performTest("import java.util.*;\n"+ |
| 161 | ++ "public class Test {\n"+ |
| 162 | ++ " List<String> l = new ArrayList<Str|ing>();\n"+ |
| 163 | ++ "}\n", |
| 164 | ++ "", |
| 165 | ++ "11", |
| 166 | ++ "[java.lang.String]"); |
| 167 | ++ } |
| 168 | ++ |
| 169 | ++ public void testConstructorAnnotation1() throws Exception { |
| 170 | ++ performTest("import java.lang.annotation.ElementType;\n"+ |
| 171 | ++ "import java.lang.annotation.Target;\n"+ |
| 172 | ++ "import java.util.*;\n"+ |
| 173 | ++ "public class Test {\n"+ |
| 174 | ++ " List<String> l = new @Ann Array|List();\n"+ |
| 175 | ++ "}\n"+ |
| 176 | ++ "@Target(ElementType.TYPE_USE)\n"+ |
| 177 | ++ "@interface Ann {}\n", |
| 178 | ++ "", |
| 179 | ++ "11", |
| 180 | ++ "[java.util.ArrayList, <init>, ()V]"); |
| 181 | ++ } |
| 182 | ++ |
| 183 | ++ public void testConstructorAnnotation2() throws Exception { |
| 184 | ++ performTest("import java.lang.annotation.ElementType;\n"+ |
| 185 | ++ "import java.lang.annotation.Target;\n"+ |
| 186 | ++ "import java.util.*;\n"+ |
| 187 | ++ "public class Test {\n"+ |
| 188 | ++ " List<String> l = new @An|n ArrayList();\n"+ |
| 189 | ++ "}\n"+ |
| 190 | ++ "@Target(ElementType.TYPE_USE)\n"+ |
| 191 | ++ "@interface Ann {}\n", |
| 192 | ++ "", |
| 193 | ++ "11", |
| 194 | ++ "[Ann]"); |
| 195 | ++ } |
| 196 | ++ |
| 197 | ++ public void testConstructorAnnotationTypeParams1() throws Exception { |
| 198 | ++ performTest("import java.lang.annotation.ElementType;\n"+ |
| 199 | ++ "import java.lang.annotation.Target;\n"+ |
| 200 | ++ "import java.util.*;\n"+ |
| 201 | ++ "public class Test {\n"+ |
| 202 | ++ " List<String> l = new @Ann Array|List<String>();\n"+ |
| 203 | ++ "}\n"+ |
| 204 | ++ "@Target(ElementType.TYPE_USE)\n"+ |
| 205 | ++ "@interface Ann {}\n", |
| 206 | ++ "", |
| 207 | ++ "11", |
| 208 | ++ "[java.util.ArrayList, <init>, ()V]"); |
| 209 | ++ } |
| 210 | ++ |
| 211 | ++ public void testConstructorAnnotationTypeParams2() throws Exception { |
| 212 | ++ performTest("import java.lang.annotation.ElementType;\n"+ |
| 213 | ++ "import java.lang.annotation.Target;\n"+ |
| 214 | ++ "import java.util.*;\n"+ |
| 215 | ++ "public class Test {\n"+ |
| 216 | ++ " List<String> l = new @An|n ArrayList<String>();\n"+ |
| 217 | ++ "}\n"+ |
| 218 | ++ "@Target(ElementType.TYPE_USE)\n"+ |
| 219 | ++ "@interface Ann {}\n", |
| 220 | ++ "", |
| 221 | ++ "11", |
| 222 | ++ "[Ann]"); |
| 223 | ++ } |
| 224 | ++ |
| 225 | ++ public void testConstructorAnnotationTypeParams3() throws Exception { |
| 226 | ++ performTest("import java.lang.annotation.ElementType;\n"+ |
| 227 | ++ "import java.lang.annotation.Target;\n"+ |
| 228 | ++ "import java.util.*;\n"+ |
| 229 | ++ "public class Test {\n"+ |
| 230 | ++ " List<String> l = new @Ann ArrayList<Str|ing>();\n"+ |
| 231 | ++ "}\n"+ |
| 232 | ++ "@Target(ElementType.TYPE_USE)\n"+ |
| 233 | ++ "@interface Ann {}\n", |
| 234 | ++ "", |
| 235 | ++ "11", |
| 236 | ++ "[java.lang.String]"); |
| 237 | ++ } |
| 238 | ++ |
| 239 | ++ public void testConstructorIntegerArgument() throws Exception { |
| 240 | ++ performTest("public class Test {\n" + |
| 241 | ++ "/**\n"+ |
| 242 | ++ "This is constructor level Javadoc\n"+ |
| 243 | ++ "**/\n"+ |
| 244 | ++ "Test(int i){}\n"+ |
| 245 | ++ " public static void main(String[] args) {\n"+ |
| 246 | ++ " Test t = new Test(|10000);\n" + |
| 247 | ++ " }\n" + |
| 248 | ++ "}\n", |
| 249 | ++ "", |
| 250 | ++ "11", |
| 251 | ++ null); |
| 252 | ++ } |
| 253 | ++ |
| 254 | ++ public void testConstructorCharacterArgument() throws Exception { |
| 255 | ++ performTest("public class Test {\n" + |
| 256 | ++ "/**\n"+ |
| 257 | ++ "This is constructor level Javadoc\n"+ |
| 258 | ++ "**/\n"+ |
| 259 | ++ "Test(char c){}\n"+ |
| 260 | ++ " public static void main(String[] args) {\n"+ |
| 261 | ++ " Test t = new Test(|'x');\n" + |
| 262 | ++ " }\n" + |
| 263 | ++ "}\n", |
| 264 | ++ "", |
| 265 | ++ "11", |
| 266 | ++ null); |
| 267 | ++ } |
| 268 | ++ |
| 269 | ++ protected void performTest(String source, String textToInsert, String sourceLevel, String expected) throws Exception { |
| 270 | ++ this.sourceLevel.set(sourceLevel); |
| 271 | ++ int caretPos = source.indexOf("|"); |
| 272 | ++ assertTrue(caretPos != (-1)); |
| 273 | ++ String code = source.substring(0, caretPos) + source.substring(caretPos + 1); |
| 274 | ++ File testSource = new File(getWorkDir(), "test/Test.java"); |
| 275 | ++ testSource.getParentFile().mkdirs(); |
| 276 | ++ try (Writer w = new FileWriter(testSource)) { |
| 277 | ++ w.write(code); |
| 278 | ++ } |
| 279 | ++ FileObject testSourceFO = FileUtil.toFileObject(testSource); |
| 280 | ++ assertNotNull(testSourceFO); |
| 281 | ++ DataObject testSourceDO = DataObject.find(testSourceFO); |
| 282 | ++ assertNotNull(testSourceDO); |
| 283 | ++ EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); |
| 284 | ++ assertNotNull(ec); |
| 285 | ++ final Document doc = ec.openDocument(); |
| 286 | ++ assertNotNull(doc); |
| 287 | ++ doc.putProperty(Language.class, JavaTokenId.language()); |
| 288 | ++ doc.putProperty("mimeType", "text/x-java"); |
| 289 | ++ int textToInsertLength = textToInsert != null ? textToInsert.length() : 0; |
| 290 | ++ if (textToInsertLength > 0) { |
| 291 | ++ doc.insertString(caretPos, textToInsert, null); |
| 292 | ++ } |
| 293 | ++ Source s = Source.create(doc); |
| 294 | ++ JavaDocumentationTask<String> task = JavaDocumentationTask.create(caretPos + textToInsertLength, null, new StringFactory(), null); |
| 295 | ++ ParserManager.parse(Collections.singletonList(s), task); |
| 296 | ++ String documentation = task.getDocumentation(); |
| 297 | ++ |
| 298 | ++ assertEquals(expected, documentation); |
| 299 | ++ |
| 300 | ++ LifecycleManager.getDefault().saveAll(); |
| 301 | ++ } |
| 302 | ++ |
| 303 | ++ private static class StringFactory implements JavaDocumentationTask.DocumentationFactory<String> { |
| 304 | ++ |
| 305 | ++ @Override |
| 306 | ++ public String create(CompilationInfo compilationInfo, Element element, Callable<Boolean> cancel) { |
| 307 | ++ return Arrays.toString(SourceUtils.getJVMSignature(ElementHandle.create(element))); |
| 308 | ++ } |
| 309 | ++ |
| 310 | ++ } |
| 311 | ++ |
| 312 | ++} |
| 313 | +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 |
| 314 | +index 4fce71a094..684f5db0a2 100644 |
| 315 | +--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java |
| 316 | ++++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java |
| 317 | +@@ -1362,11 +1362,15 @@ public class ServerTest extends NbTestCase { |
| 318 | + File src = new File(getWorkDir(), "Test.java"); |
| 319 | + src.getParentFile().mkdirs(); |
| 320 | + String code = "/**\n" + |
| 321 | +- " * This is a test class with Javadoc.\n" + |
| 322 | ++ " * This is a class level Javadoc.\n" + |
| 323 | + " */\n" + |
| 324 | + "public class Test {\n" + |
| 325 | +- " public static void main(String[] args) {\n" + |
| 326 | +- " Test t = new Test();\n" + |
| 327 | ++ "/**\n"+ |
| 328 | ++ "This is constructor level Javadoc\n"+ |
| 329 | ++ "**/\n"+ |
| 330 | ++ "Test(int i){}\n"+ |
| 331 | ++ " public static void main(String[] args) {\n"+ |
| 332 | ++ " Test t = new Test(10000);\n" + |
| 333 | + " }\n" + |
| 334 | + "}\n"; |
| 335 | + try (Writer w = new FileWriter(src)) { |
| 336 | +@@ -1401,18 +1405,35 @@ public class ServerTest extends NbTestCase { |
| 337 | + InitializeResult result = server.initialize(new InitializeParams()).get(); |
| 338 | + assertTrue(result.getCapabilities().getHoverProvider().isLeft() && result.getCapabilities().getHoverProvider().getLeft()); |
| 339 | + server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code))); |
| 340 | +- Hover hover = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(5, 10))).get(); |
| 341 | +- assertNotNull(hover); |
| 342 | +- assertTrue(hover.getContents().isRight()); |
| 343 | +- MarkupContent content = hover.getContents().getRight(); |
| 344 | +- assertNotNull(content); |
| 345 | +- assertEquals(content.getKind(), "markdown"); |
| 346 | +- assertEquals(content.getValue(), "```\n" + |
| 347 | ++ Hover hoverClass = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 10))).get(); |
| 348 | ++ Hover hoverConstructor = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 23))).get(); |
| 349 | ++ Hover hoverIntegerArgument = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 26))).get(); |
| 350 | ++ assertNotNull(hoverClass); |
| 351 | ++ assertNotNull(hoverConstructor); |
| 352 | ++ assertNull(hoverIntegerArgument); |
| 353 | ++ assertTrue(hoverConstructor.getContents().isRight()); |
| 354 | ++ assertTrue(hoverClass.getContents().isRight()); |
| 355 | ++ MarkupContent classContent = hoverClass.getContents().getRight(); |
| 356 | ++ MarkupContent constructorContent = hoverConstructor.getContents().getRight(); |
| 357 | ++ assertNotNull(classContent); |
| 358 | ++ assertNotNull(constructorContent); |
| 359 | ++ assertEquals(classContent.getKind(), "markdown"); |
| 360 | ++ assertEquals(constructorContent.getKind(), "markdown"); |
| 361 | ++ assertEquals(classContent.getValue(), "```\n" + |
| 362 | + "public class Test\n" + |
| 363 | + "extends Object\n" + |
| 364 | + "```\n" + |
| 365 | + "\n" + |
| 366 | +- "This is a test class with Javadoc.\n" + |
| 367 | ++ "This is a class level Javadoc.\n" + |
| 368 | ++ "\n"); |
| 369 | ++ assertEquals(constructorContent.getValue(), |
| 370 | ++ "**Test**\n"+ |
| 371 | ++ "\n"+ |
| 372 | ++ "```\n" + |
| 373 | ++ "Test(int i)\n" + |
| 374 | ++ "```\n" + |
| 375 | ++ "\n" + |
| 376 | ++ "This is constructor level Javadoc\n" + |
| 377 | + "\n"); |
| 378 | + } |
| 379 | + |
0 commit comments