summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Felber2012-05-25 03:49:52 (EDT)
committer Sergey Prigogin2012-07-02 14:11:50 (EDT)
commitd9b954e28aceb06a53bd329c7f291b6137f96d61 (patch)
treebfb0a72fafa65d7e78d5199441a700ce79b49806
parentdab97f1d3f89d616a03006615b9c7086b01fdc21 (diff)
downloadorg.eclipse.cdt-d9b954e28aceb06a53bd329c7f291b6137f96d61.zip
org.eclipse.cdt-d9b954e28aceb06a53bd329c7f291b6137f96d61.tar.gz
org.eclipse.cdt-d9b954e28aceb06a53bd329c7f291b6137f96d61.tar.bz2
Bug 380615 - Assign comments belonging to preprocessor directives to them in NodeCommentMap instead of ignoring them.
minor renames and reformatting. added additional comment to "CommentRecognition preprocessor directives comment recognition". Change-Id: Idabbe95ff7dd4e11b173474b708e622252264adb Reviewed-on: https://git.eclipse.org/r/6119 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
-rw-r--r--core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingTestSource.rts53
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenter.java251
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenterVisitor.java20
3 files changed, 180 insertions, 144 deletions
diff --git a/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingTestSource.rts b/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingTestSource.rts
index 422b99a..c89f494 100644
--- a/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingTestSource.rts
+++ b/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingTestSource.rts
@@ -2978,6 +2978,7 @@ class test
//=
=>leading
+#ifndef TEST_H_ = //TEST
=>trailing
=>freestanding
@@ -2999,6 +3000,9 @@ class test
//=
=>leading
+#ifndef TEST_H_ = /*
+ * Licence information...
+ */
=>trailing
=>freestanding
@@ -3021,6 +3025,9 @@ class test
//=
=>leading
+#ifndef TEST_H_ = /*
+ * Licence information...
+ */
class test
{
}; = //test
@@ -3054,7 +3061,11 @@ private:
//=
=>leading
+#ifndef HIDEMETHOD_H_ = /*
+ * HideMethod.h
+ */
=>trailing
+#endif = /* HIDEMETHOD_H_ */
=>freestanding
//!CommentRecognition Bug 233438
@@ -3077,6 +3088,7 @@ private:
//=
=>leading
=>trailing
+#endif = /* HIDEMETHOD_H_ */
=>freestanding
//@test.cpp
@@ -3122,6 +3134,7 @@ private:
//=
=>leading
=>trailing
+#endif = /* HIDEMETHOD_H_ */
=>freestanding
//@test.cpp
@@ -3145,4 +3158,44 @@ int HideMethod::methode2(){
=>trailing
i++; = //comment
=>freestanding
+//!CommentRecognition preprocessor directives comment recognition
+//#org.eclipse.cdt.core.parser.tests.rewrite.comenthandler.CommentHandlingTest
+//@main.cpp
+//c1
+int i;//c2
+//inc1
+//inc2
+
+#include "foo.h" /*inc3*/ /*inc4*/
+//main
+int main() {
+ return 0;
+ //block1
+}
+//ifdef1
+#ifdef X //ifdef2
+//=
+=>leading
+int i; = //c1
+#include "foo.h" = //inc1 , //inc2
+int main() {
+ return 0;
+ //block1
+} = //main
+#ifdef X = //ifdef1
+=>trailing
+int i; = //c2
+#include "foo.h" = /*inc3*/ , /*inc4*/
+#ifdef X = //ifdef2
+=>freestanding
+{
+ return 0;
+ //block1
+} = //block1
+//@foo.h
+void foo();
+//=
+=>leading
+=>trailing
+=>freestanding \ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenter.java
index a7d748a..402fb71 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenter.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenter.java
@@ -12,9 +12,9 @@
package org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
-import java.util.TreeMap;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
@@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
@@ -33,15 +34,10 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
-import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
-import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
/**
* This is the starting point of the entire comment handling process. The creation of the
@@ -56,33 +52,40 @@ import org.eclipse.core.runtime.Path;
*/
public class ASTCommenter {
- private static final class PPRangeChecker extends ASTVisitor {
- int ppOffset;
- int commentOffset;
- boolean isPrePPComment = true;
+ private static final class PreprocessorRangeChecker extends ASTVisitor {
+ int statementOffset;
+ IASTFileLocation commentNodeLocation;
+ boolean isPreStatementComment = true;
- private PPRangeChecker(boolean visitNodes, int nextPPOfset, int commentNodeOffset) {
- super(visitNodes);
- ppOffset = nextPPOfset;
- commentOffset = commentNodeOffset;
+ private PreprocessorRangeChecker(int statementOffset, IASTFileLocation commentNodeLocation) {
+ super(true);
+ this.statementOffset = statementOffset;
+ this.commentNodeLocation = commentNodeLocation;
}
private int checkOffsets(IASTNode node) {
int offset = ((ASTNode)node).getOffset();
- int status = ASTVisitor.PROCESS_CONTINUE;
+ int status = PROCESS_CONTINUE;
- if (offset > commentOffset && offset < ppOffset) {
- isPrePPComment = false;
- status = ASTVisitor.PROCESS_ABORT;
- } else if ((offset + ((ASTNode)node).getLength() < commentOffset)) {
- status = ASTVisitor.PROCESS_SKIP;
- } else if (offset > ppOffset) {
- status = ASTVisitor.PROCESS_ABORT;
+ if (isCommentOnSameLine(node)
+ || offset > commentNodeLocation.getNodeOffset()
+ && offset < statementOffset) {
+ isPreStatementComment = false;
+ status = PROCESS_ABORT;
+ } else if ((offset + ((ASTNode) node).getLength() < commentNodeLocation.getNodeOffset())) {
+ status = PROCESS_SKIP;
+ } else if (offset > statementOffset) {
+ status = PROCESS_ABORT;
}
return status;
}
+ private boolean isCommentOnSameLine(IASTNode node) {
+ return commentNodeLocation.getStartingLineNumber() == node.getFileLocation()
+ .getEndingLineNumber();
+ }
+
@Override
public int visit(ICPPASTBaseSpecifier baseSpecifier) {
return checkOffsets(baseSpecifier);
@@ -168,141 +171,115 @@ public class ASTCommenter {
* Creates a NodeCommentMap for the given TranslationUnit. This is the only way
* to get a NodeCommentMap which contains all the comments mapped against nodes.
*
- * @param transUnit TranslationUnit
+ * @param tu TranslationUnit
* @return NodeCommentMap
*/
- public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit transUnit){
- if (transUnit == null) {
- return new NodeCommentMap();
+ public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit tu){
+ NodeCommentMap commentMap = new NodeCommentMap();
+ if (tu == null) {
+ return commentMap;
}
- List<IASTComment> comments = removeNotNeededComments(transUnit);
- if (comments == null || comments.isEmpty()) {
- return new NodeCommentMap();
+ IASTComment[] commentsArray = tu.getComments();
+ if (commentsArray == null) {
+ return commentMap;
}
- return addCommentsToCommentMap(transUnit, comments);
+ // Note that constructing a real ArrayList is required here, since in filterNonTuComments, the
+ // remove-method will be invoked on the list's iterator. Calling it on the type Arrays$ArrayList (the
+ // resulting type of Arrays.asList() ) would throw a UnsupportedOperationException.
+ ArrayList<IASTComment> comments = new ArrayList<IASTComment>(Arrays.asList(commentsArray));
+ filterNonTuComments(comments);
+ return addCommentsToCommentMap(tu, comments);
}
- private static List<IASTComment> removeNotNeededComments(IASTTranslationUnit transUnit) {
- List<IASTComment> comments = getCommentsInWorkspace(transUnit);
- if (comments == null || comments.isEmpty()) {
- return null;
+ /**
+ * Note that passing an ArrayList (instead of just List or Collection) is required here, since this
+ * guarantees that the call to the remove-method on the list's iterator will not result in an
+ * UnsupportedOperationException which might be the case for other Collection/List types.
+ */
+ private static void filterNonTuComments(ArrayList<IASTComment> comments) {
+ Iterator<IASTComment> iterator = comments.iterator();
+ while (iterator.hasNext()) {
+ if (!iterator.next().isPartOfTranslationUnitFile()) {
+ iterator.remove();
+ }
}
- return removeAllPreprocessorComments(transUnit, comments);
}
- private static List<IASTComment> getCommentsInWorkspace(IASTTranslationUnit tu) {
- IASTComment[] comments = tu.getComments();
- ArrayList<IASTComment> commentsInWorkspace = new ArrayList<IASTComment>();
-
- if (comments == null || comments.length == 0) {
- return null;
+ private static boolean isCommentDirectlyBeforePreprocessorStatement(IASTComment comment,
+ IASTPreprocessorStatement statement, IASTTranslationUnit tu) {
+ if (tu == null || tu.getDeclarations().length == 0) {
+ return true;
}
-
- for (IASTComment comment : comments) {
- if (isInWorkspace(comment)) {
- commentsInWorkspace.add(comment);
- }
+ IASTFileLocation commentLocation = comment.getFileLocation();
+ int preprcessorOffset = statement.getFileLocation().getNodeOffset();
+ if (preprcessorOffset > commentLocation.getNodeOffset()) {
+ PreprocessorRangeChecker vister = new PreprocessorRangeChecker(preprcessorOffset, commentLocation);
+ tu.accept(vister);
+ return vister.isPreStatementComment;
}
- return commentsInWorkspace;
+ return false;
}
- private static List<IASTComment> removeAllPreprocessorComments(IASTTranslationUnit tu,
- List<IASTComment> comments) {
- IASTPreprocessorStatement[] preprocessorStatements = tu.getAllPreprocessorStatements();
- TreeMap<Integer, String> treeOfPreProcessorLines = new TreeMap<Integer,String>();
- TreeMap<String, ArrayList<Integer>> ppOffsetForFiles = new TreeMap<String, ArrayList<Integer>>();
+ public static boolean isInWorkspace(IASTNode node) {
+ return node.isPartOfTranslationUnitFile();
+ }
+
+ private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit tu,
+ ArrayList<IASTComment> comments){
+ NodeCommentMap commentMap = new NodeCommentMap();
+ CommentHandler commHandler = new CommentHandler(comments);
- for (IASTPreprocessorStatement statement : preprocessorStatements) {
- if (isInWorkspace(statement)) {
- String fileName = statement.getFileLocation().getFileName();
- treeOfPreProcessorLines.put(statement.getFileLocation().getStartingLineNumber(), fileName);
- ArrayList<Integer> offsetList = ppOffsetForFiles.get(fileName);
- if (offsetList == null) {
- offsetList = new ArrayList<Integer>();
- ppOffsetForFiles.put(fileName, offsetList);
- }
- offsetList.add(((ASTNode)statement).getOffset());
- }
+ assignPreprocessorComments(commentMap, comments, tu);
+ ASTCommenterVisitor commenter = new ASTCommenterVisitor(commHandler, commentMap);
+ tu.accept(commenter);
+ return commentMap;
+ }
+
+ /**
+ * Note that passing an ArrayList (instead of just List or Collection) is required here, since this
+ * guarantees that the call to the remove-method on the list's iterator will not result in an
+ * UnsupportedOperationException which might be the case for other Collection/List types.
+ */
+ private static void assignPreprocessorComments(NodeCommentMap commentMap,
+ ArrayList<IASTComment> comments, IASTTranslationUnit tu) {
+ IASTPreprocessorStatement[] preprocessorStatementsArray = tu.getAllPreprocessorStatements();
+ if (preprocessorStatementsArray == null) {
+ return;
}
+ List<IASTPreprocessorStatement> preprocessorStatements = Arrays.asList(preprocessorStatementsArray);
- ArrayList<IASTComment> commentsInCode = new ArrayList<IASTComment>();
- for (IASTComment comment : comments) {
- IASTFileLocation commentFileLocation = comment.getFileLocation();
- int comStartLineNumber = commentFileLocation.getStartingLineNumber();
- String fileName = commentFileLocation.getFileName();
- if (treeOfPreProcessorLines.containsKey(comStartLineNumber)
- && treeOfPreProcessorLines.get(comStartLineNumber).equals(fileName)) {
- continue;
- }
- if (commentIsAtTheBeginningBeforePreprocessorStatements(comment,
- ppOffsetForFiles.get(fileName), tu)) {
- continue;
- }
- commentsInCode.add(comment);
+ if (preprocessorStatements.isEmpty() || comments.isEmpty()) {
+ return;
}
- return commentsInCode;
- }
- private static boolean commentIsAtTheBeginningBeforePreprocessorStatements(IASTComment comment,
- ArrayList<Integer> listOfPreProcessorOffset, IASTTranslationUnit tu) {
- if (listOfPreProcessorOffset == null) {
- return false;
- }
-
- if (comment.getTranslationUnit() == null || comment.getTranslationUnit().getDeclarations().length < 1) {
- return true;
- }
- IASTDeclaration decl = comment.getTranslationUnit().getDeclarations()[0];
- String commentFileName = comment.getFileLocation().getFileName();
- boolean sameFile = decl.getFileLocation().getFileName().equals(commentFileName);
- int commentNodeOffset = ((ASTNode)comment).getOffset();
- if (sameFile) {
- if (decl.getFileLocation().getNodeOffset() < commentNodeOffset) {
- return false;
- }
- }
- Collections.sort(listOfPreProcessorOffset);
- int nextPPOfset = -1;
- for (Integer integer : listOfPreProcessorOffset) {
- if (integer > commentNodeOffset) {
- nextPPOfset = integer;
- PPRangeChecker visti = new PPRangeChecker(true, nextPPOfset, commentNodeOffset);
- tu.accept(visti);
- if (visti.isPrePPComment) {
- return true;
- }
+ Iterator<IASTPreprocessorStatement> statementsIter = preprocessorStatements.iterator();
+ Iterator<IASTComment> commentIter = comments.iterator();
+ IASTPreprocessorStatement curStatement = getNextNodeInTu(statementsIter);
+ IASTComment curComment = getNextNodeInTu(commentIter);
+ while (curStatement != null && curComment != null) {
+ int statementLineNr = curStatement.getFileLocation().getStartingLineNumber();
+ int commentLineNr = curComment.getFileLocation().getStartingLineNumber();
+ if (commentLineNr == statementLineNr) {
+ commentMap.addTrailingCommentToNode(curStatement, curComment);
+ commentIter.remove();
+ curComment = getNextNodeInTu(commentIter);
+ } else if (commentLineNr > statementLineNr) {
+ curStatement = getNextNodeInTu(statementsIter);
+ } else if (isCommentDirectlyBeforePreprocessorStatement(curComment, curStatement, tu)) {
+ commentMap.addLeadingCommentToNode(curStatement, curComment);
+ commentIter.remove();
+ curComment = getNextNodeInTu(commentIter);
+ } else {
+ curComment = getNextNodeInTu(commentIter);
}
}
-
- return false;
}
- private static boolean isInWorkspace(IASTNode node) {
- IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
- IPath nodePath = new Path(node.getContainingFilename());
- for (IProject project : projects) {
- if (project.getLocation().isPrefixOf(nodePath)) return true;
+ private static <T extends IASTNode> T getNextNodeInTu(Iterator<T> iter) {
+ if (!iter.hasNext()) {
+ return null;
}
- return false;
+ T next = iter.next();
+ return next.isPartOfTranslationUnitFile() ? next : getNextNodeInTu(iter);
}
-
- private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit rootNode,
- List<IASTComment> comments){
- NodeCommentMap commentMap = new NodeCommentMap();
- CommentHandler commHandler = new CommentHandler(comments);
-
- IASTDeclaration[] declarations = rootNode.getDeclarations();
- for (int i = 0; i < declarations.length; i++) {
- if (isInWorkspace(declarations[i])) {
- ASTCommenterVisitor commenter = new ASTCommenterVisitor(commHandler, commentMap);
- declarations[i].accept(commenter);
-
- // Add the remaining comments to the last declaration to prevent comment loss.
- if (i == declarations.length - 1) {
- commenter.addRemainingComments(declarations[i]);
- }
- }
- }
- return commentMap;
- }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenterVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenterVisitor.java
index 9fbd6bb..a8a97e9 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenterVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/ASTCommenterVisitor.java
@@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName;
@@ -25,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
-import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@@ -43,6 +43,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
protected NodeCommentMap commentMap;
private NodeCommenter nodeCommenter;
+ private IASTDeclaration lastDecl;
{
shouldVisitBaseSpecifiers = true;
@@ -57,6 +58,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
shouldVisitStatements = true;
shouldVisitTemplateParameters = true;
shouldVisitTypeIds = true;
+ shouldVisitTranslationUnit = true;
}
public ASTCommenterVisitor(CommentHandler commHandler, NodeCommentMap commentMap) {
@@ -69,10 +71,6 @@ public class ASTCommenterVisitor extends ASTVisitor {
nodeCommenter = new NodeCommenter(this, commHandler, commentMap);
}
- public void addRemainingComments(IASTDeclaration declaration) {
- nodeCommenter.appendRemainingComments(declaration);
- }
-
@Override
public int visit(IASTName name) {
return nodeCommenter.appendComments((ASTNode) name);
@@ -100,7 +98,10 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override
public int visit(IASTDeclaration declaration) {
- return nodeCommenter.appendComments((ASTNode) declaration);
+ if (ASTCommenter.isInWorkspace(declaration)) {
+ return nodeCommenter.appendComments((ASTNode) declaration);
+ }
+ return PROCESS_SKIP;
}
@Override
@@ -131,9 +132,13 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override
public int leave(IASTTranslationUnit tu) {
nodeCommenter.appendComments((ASTNode) tu);
+ if (lastDecl != null) {
+ nodeCommenter.appendRemainingComments(lastDecl);
+ }
return PROCESS_CONTINUE;
}
+
@Override
public int leave(IASTName name) {
nodeCommenter.appendComments((ASTNode) name);
@@ -142,6 +147,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override
public int leave(IASTDeclaration declaration) {
+ lastDecl = declaration;
nodeCommenter.appendComments((ASTNode) declaration);
return PROCESS_CONTINUE;
}
@@ -215,5 +221,5 @@ public class ASTCommenterVisitor extends ASTVisitor {
public int leave( IASTComment comment){
nodeCommenter.appendComments((ASTNode) comment);
return PROCESS_CONTINUE;
- }
+ }
}