diff --git a/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/AbstractJdtTreeGenerator.java b/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/AbstractJdtTreeGenerator.java index d5908f87..81abd3b3 100644 --- a/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/AbstractJdtTreeGenerator.java +++ b/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/AbstractJdtTreeGenerator.java @@ -29,13 +29,17 @@ import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.CompilationUnit; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.util.List; import java.util.Map; public abstract class AbstractJdtTreeGenerator extends TreeGenerator { + protected boolean includeComments = Boolean.parseBoolean(System.getProperty("gumtree.jdt.includeComments", "true")); + private static final String JAVA_VERSION = JavaCore.latestSupportedJavaVersion(); private static char[] readerToCharArray(Reader r) throws IOException { @@ -72,6 +76,15 @@ public TreeContext generate(Reader r) throws IOException { if ((node.getFlags() & ASTNode.MALFORMED) != 0) // bitwise flag to check if the node has a syntax error throw new SyntaxException(this, r, null); node.accept(v); + if (includeComments) { + if (node instanceof CompilationUnit) { + List commentList = ((CompilationUnit) node).getCommentList(); + for (Object o : commentList) { + ASTNode comment = (ASTNode) o; + comment.accept(new JdtCommentVisitor(scanner, v.getTreeContext())); + } + } + } return v.getTreeContext(); } diff --git a/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/JdtCommentVisitor.java b/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/JdtCommentVisitor.java new file mode 100644 index 00000000..3b26983a --- /dev/null +++ b/gen.jdt/src/main/java/com/github/gumtreediff/gen/jdt/JdtCommentVisitor.java @@ -0,0 +1,89 @@ +/* + * This file is part of GumTree. + * + * GumTree is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GumTree is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with GumTree. If not, see . + * + * Copyright 2011-2015 Jean-Rémy Falleri + * Copyright 2011-2015 Floréal Morandat + */ + +package com.github.gumtreediff.gen.jdt; + +import com.github.gumtreediff.tree.*; +import org.eclipse.jdt.core.compiler.IScanner; +import org.eclipse.jdt.core.dom.*; + +import java.util.List; + +/* Created by pourya on 2024-08-28*/ +class JdtCommentVisitor extends JdtVisitor { + final TreeContext context; + final char[] source; + + public JdtCommentVisitor(IScanner scanner, TreeContext context) { + super(scanner); + this.source = scanner.getSource(); + this.context = context; + } + + public boolean visit(BlockComment node) { + return visitComment(node); + } + + public boolean visit(LineComment node) { + return visitComment(node); + } + + public boolean visitComment(Comment node) { + int start = node.getStartPosition(); + int end = start + node.getLength(); + Tree parent = findMostInnerEnclosingParent(context.getRoot(), start, end); + Tree t = context.createTree(nodeAsSymbol(node), new String(source, start, end - start)); + t.setPos(start); + t.setLength(node.getLength()); + insertChildProperly(parent, t); + return true; + } + + public void insertChildProperly(Tree parent, Tree newChild) { + int position = 0; + for (Tree child : parent.getChildren()) + { + if (child.getPos() < newChild.getPos()) { + position += 1; + } + else + break; + } + parent.insertChild(newChild,position); + } + + private Tree findMostInnerEnclosingParent(Tree root, int start, int end) { + Tree mostInnerParent = root; + List children = root.getChildren(); + + for (Tree child : children) { + if (child.getPos() <= start && child.getEndPos() >= end) { + Tree candidate = findMostInnerEnclosingParent(child, start, end); + if (candidate.getPos() >= mostInnerParent.getPos() + && candidate.getEndPos() <= mostInnerParent.getEndPos()) { + mostInnerParent = candidate; + } + } + } + + return mostInnerParent; + } + +} \ No newline at end of file diff --git a/gen.jdt/src/test/java/com/github/gumtreediff/gen/jdt/TestJdtGenerator.java b/gen.jdt/src/test/java/com/github/gumtreediff/gen/jdt/TestJdtGenerator.java index 8cf4775d..7c233040 100644 --- a/gen.jdt/src/test/java/com/github/gumtreediff/gen/jdt/TestJdtGenerator.java +++ b/gen.jdt/src/test/java/com/github/gumtreediff/gen/jdt/TestJdtGenerator.java @@ -202,4 +202,26 @@ public void testTagElement() throws IOException { + " SimpleName: C [26,27]"; assertEquals(expected, ct.getRoot().toTreeString()); } + + @Test + public void testComments() throws IOException { + String input = "class bar {\n" + + " void foo(/*int a*/)\n" + + " {\n" + + " //run();\n" + + " }\n" + + "}\n"; + TreeContext ct = new JdtTreeGenerator().generateFrom().string(input); + String expected = "CompilationUnit [0,87]\n" + + " TypeDeclaration [0,86]\n" + + " TYPE_DECLARATION_KIND: class [0,5]\n" + + " SimpleName: bar [6,9]\n" + + " MethodDeclaration [20,84]\n" + + " PrimitiveType: void [20,24]\n" + + " SimpleName: foo [25,28]\n" + + " BlockComment: /*int a*/ [29,38]\n" + + " Block [48,84]\n" + + " LineComment: //run(); [66,74]"; + assertEquals(expected, ct.getRoot().toTreeString()); + } }