diff --git a/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java index ad9e2d5c2039..6a70a939c00c 100644 --- a/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java +++ b/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java @@ -1547,6 +1547,7 @@ static T importComments(CompilationInfo info, T original, Compi TokenSequence seq = tokens.tokenSequence(JavaTokenId.language()); TreePath tp = TreePath.getPath(cut, original); Tree toMap = original; + TreePath toMapPath = tp; Tree mapTarget = null; if (tp != null && original.getKind() != Kind.COMPILATION_UNIT) { @@ -1579,17 +1580,33 @@ static T importComments(CompilationInfo info, T original, Compi } if (p2 != null) { toMap = p2.getLeaf(); + toMapPath = p2; } if (toMap == tp.getLeaf()) { // go at least one level up in a hope it's sufficient. toMap = tp.getParentPath().getLeaf(); + toMapPath = tp.getParentPath(); } } if (mapTarget == null) { mapTarget = original; } + AssignComments translator = new AssignComments(info, mapTarget, seq, unit); - + + if (toMapPath != null && + toMapPath.getParentPath() != null && + TreeUtilities.CLASS_TREE_KINDS.contains(toMapPath.getParentPath().getLeaf().getKind())) { + //run the mapping the preceding member, so that its trailing comments are properly consumed: + ClassTree enclClass = (ClassTree) toMapPath.getParentPath().getLeaf(); + List members = enclClass.getMembers(); + int currentIndex = members.indexOf(toMap); + + if (currentIndex > 0) { + translator.scan(members.get(currentIndex - 1), null); + } + } + translator.scan(toMap, null); return original; diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/CommentCollectorTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/CommentCollectorTest.java index e5cef1a3b6a2..549a6ac0ab0f 100644 --- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/CommentCollectorTest.java +++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/CommentCollectorTest.java @@ -778,4 +778,64 @@ public Void visitCompilationUnit(CompilationUnitTree node, Void aVoid) { } } + public void testImproperlyMappedCommentsMembersStartFromModifiers() throws Exception { + File testFile = new File(work, "Test.java"); + final String origin = + """ + public class Test { + static final int I = 1; //trailing + + //preceding + @Deprecated + void test() { + } + + Test() {} + } + """; + TestUtilities.copyStringToFile(testFile, origin); + JavaSource src = getJavaSource(testFile); + + Task task = new Task() { + public void run(final WorkingCopy workingCopy) throws Exception { + workingCopy.toPhase(JavaSource.Phase.PARSED); + final CommentHandlerService service = CommentHandlerService.instance(workingCopy.impl.getJavacTask().getContext()); + + ErrorAwareTreeScanner w = new ErrorAwareTreeScanner() { + @Override + public Void visitClass(ClassTree node, Void p) { + super.visitClass(node, p); + + //verify the comments for the field I are not mapped: + Tree fieldMember = node.getMembers().get(0); + + assertEquals(Tree.Kind.VARIABLE, fieldMember.getKind()); + assertEquals("I", ((VariableTree) fieldMember).getName().toString()); + + CommentSetImpl fieldCommentSet = service.getComments(fieldMember); + + assertFalse(fieldCommentSet.areCommentsMapped()); + verify(fieldMember, CommentSet.RelativePosition.PRECEDING, service); + verify(fieldMember, CommentSet.RelativePosition.INLINE, service); + verify(fieldMember, CommentSet.RelativePosition.TRAILING, service); + return null; + } + + @Override + public Void visitMethod(MethodTree node, Void p) { + if (node.getName().contentEquals("test")) { + workingCopy.getTreeUtilities().getComments(node.getModifiers(), true); + verify(node, CommentSet.RelativePosition.PRECEDING, service, "//preceding"); + verify(node, CommentSet.RelativePosition.INLINE, service); + verify(node, CommentSet.RelativePosition.TRAILING, service); + } + return super.visitMethod(node, p); + } + }; + w.scan(workingCopy.getCompilationUnit(), null); + } + }; + + src.runModificationTask(task); + } }