1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

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>
This commit is contained in:
Lukas Felber 2012-05-25 09:49:52 +02:00 committed by Sergey Prigogin
parent dab97f1d3f
commit d9b954e28a
3 changed files with 182 additions and 146 deletions

View file

@ -2978,6 +2978,7 @@ class test
//= //=
=>leading =>leading
#ifndef TEST_H_ = //TEST
=>trailing =>trailing
=>freestanding =>freestanding
@ -2999,6 +3000,9 @@ class test
//= //=
=>leading =>leading
#ifndef TEST_H_ = /*
* Licence information...
*/
=>trailing =>trailing
=>freestanding =>freestanding
@ -3021,6 +3025,9 @@ class test
//= //=
=>leading =>leading
#ifndef TEST_H_ = /*
* Licence information...
*/
class test class test
{ {
}; = //test }; = //test
@ -3054,7 +3061,11 @@ private:
//= //=
=>leading =>leading
#ifndef HIDEMETHOD_H_ = /*
* HideMethod.h
*/
=>trailing =>trailing
#endif = /* HIDEMETHOD_H_ */
=>freestanding =>freestanding
//!CommentRecognition Bug 233438 //!CommentRecognition Bug 233438
@ -3077,6 +3088,7 @@ private:
//= //=
=>leading =>leading
=>trailing =>trailing
#endif = /* HIDEMETHOD_H_ */
=>freestanding =>freestanding
//@test.cpp //@test.cpp
@ -3122,6 +3134,7 @@ private:
//= //=
=>leading =>leading
=>trailing =>trailing
#endif = /* HIDEMETHOD_H_ */
=>freestanding =>freestanding
//@test.cpp //@test.cpp
@ -3145,4 +3158,44 @@ int HideMethod::methode2(){
=>trailing =>trailing
i++; = //comment i++; = //comment
=>freestanding =>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

View file

@ -12,9 +12,9 @@
package org.eclipse.cdt.internal.core.dom.rewrite.commenthandler; package org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.TreeMap;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; 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.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTInitializer; 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.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; 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.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; 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.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 * 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 { public class ASTCommenter {
private static final class PPRangeChecker extends ASTVisitor { private static final class PreprocessorRangeChecker extends ASTVisitor {
int ppOffset; int statementOffset;
int commentOffset; IASTFileLocation commentNodeLocation;
boolean isPrePPComment = true; boolean isPreStatementComment = true;
private PPRangeChecker(boolean visitNodes, int nextPPOfset, int commentNodeOffset) { private PreprocessorRangeChecker(int statementOffset, IASTFileLocation commentNodeLocation) {
super(visitNodes); super(true);
ppOffset = nextPPOfset; this.statementOffset = statementOffset;
commentOffset = commentNodeOffset; this.commentNodeLocation = commentNodeLocation;
} }
private int checkOffsets(IASTNode node) { private int checkOffsets(IASTNode node) {
int offset = ((ASTNode)node).getOffset(); int offset = ((ASTNode)node).getOffset();
int status = ASTVisitor.PROCESS_CONTINUE; int status = PROCESS_CONTINUE;
if (offset > commentOffset && offset < ppOffset) { if (isCommentOnSameLine(node)
isPrePPComment = false; || offset > commentNodeLocation.getNodeOffset()
status = ASTVisitor.PROCESS_ABORT; && offset < statementOffset) {
} else if ((offset + ((ASTNode)node).getLength() < commentOffset)) { isPreStatementComment = false;
status = ASTVisitor.PROCESS_SKIP; status = PROCESS_ABORT;
} else if (offset > ppOffset) { } else if ((offset + ((ASTNode) node).getLength() < commentNodeLocation.getNodeOffset())) {
status = ASTVisitor.PROCESS_ABORT; status = PROCESS_SKIP;
} else if (offset > statementOffset) {
status = PROCESS_ABORT;
} }
return status; return status;
} }
private boolean isCommentOnSameLine(IASTNode node) {
return commentNodeLocation.getStartingLineNumber() == node.getFileLocation()
.getEndingLineNumber();
}
@Override @Override
public int visit(ICPPASTBaseSpecifier baseSpecifier) { public int visit(ICPPASTBaseSpecifier baseSpecifier) {
return checkOffsets(baseSpecifier); return checkOffsets(baseSpecifier);
@ -168,141 +171,115 @@ public class ASTCommenter {
* Creates a NodeCommentMap for the given TranslationUnit. This is the only way * Creates a NodeCommentMap for the given TranslationUnit. This is the only way
* to get a NodeCommentMap which contains all the comments mapped against nodes. * to get a NodeCommentMap which contains all the comments mapped against nodes.
* *
* @param transUnit TranslationUnit * @param tu TranslationUnit
* @return NodeCommentMap * @return NodeCommentMap
*/ */
public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit transUnit){ public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit tu){
if (transUnit == null) { NodeCommentMap commentMap = new NodeCommentMap();
return new NodeCommentMap(); if (tu == null) {
return commentMap;
} }
List<IASTComment> comments = removeNotNeededComments(transUnit); IASTComment[] commentsArray = tu.getComments();
if (comments == null || comments.isEmpty()) { if (commentsArray == null) {
return new NodeCommentMap(); 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); * Note that passing an ArrayList (instead of just List or Collection) is required here, since this
if (comments == null || comments.isEmpty()) { * guarantees that the call to the remove-method on the list's iterator will not result in an
return null; * 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) { private static boolean isCommentDirectlyBeforePreprocessorStatement(IASTComment comment,
IASTComment[] comments = tu.getComments(); IASTPreprocessorStatement statement, IASTTranslationUnit tu) {
ArrayList<IASTComment> commentsInWorkspace = new ArrayList<IASTComment>(); if (tu == null || tu.getDeclarations().length == 0) {
if (comments == null || comments.length == 0) {
return null;
}
for (IASTComment comment : comments) {
if (isInWorkspace(comment)) {
commentsInWorkspace.add(comment);
}
}
return commentsInWorkspace;
}
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>>();
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());
}
}
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);
}
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; return true;
} }
IASTDeclaration decl = comment.getTranslationUnit().getDeclarations()[0]; IASTFileLocation commentLocation = comment.getFileLocation();
String commentFileName = comment.getFileLocation().getFileName(); int preprcessorOffset = statement.getFileLocation().getNodeOffset();
boolean sameFile = decl.getFileLocation().getFileName().equals(commentFileName); if (preprcessorOffset > commentLocation.getNodeOffset()) {
int commentNodeOffset = ((ASTNode)comment).getOffset(); PreprocessorRangeChecker vister = new PreprocessorRangeChecker(preprcessorOffset, commentLocation);
if (sameFile) { tu.accept(vister);
if (decl.getFileLocation().getNodeOffset() < commentNodeOffset) { return vister.isPreStatementComment;
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;
}
}
}
return false; return false;
} }
private static boolean isInWorkspace(IASTNode node) { public static boolean isInWorkspace(IASTNode node) {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); return node.isPartOfTranslationUnitFile();
IPath nodePath = new Path(node.getContainingFilename());
for (IProject project : projects) {
if (project.getLocation().isPrefixOf(nodePath)) return true;
}
return false;
} }
private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit rootNode, private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit tu,
List<IASTComment> comments){ ArrayList<IASTComment> comments){
NodeCommentMap commentMap = new NodeCommentMap(); NodeCommentMap commentMap = new NodeCommentMap();
CommentHandler commHandler = new CommentHandler(comments); CommentHandler commHandler = new CommentHandler(comments);
IASTDeclaration[] declarations = rootNode.getDeclarations(); assignPreprocessorComments(commentMap, comments, tu);
for (int i = 0; i < declarations.length; i++) { ASTCommenterVisitor commenter = new ASTCommenterVisitor(commHandler, commentMap);
if (isInWorkspace(declarations[i])) { tu.accept(commenter);
ASTCommenterVisitor commenter = new ASTCommenterVisitor(commHandler, commentMap); return commentMap;
declarations[i].accept(commenter); }
// Add the remaining comments to the last declaration to prevent comment loss. /**
if (i == declarations.length - 1) { * Note that passing an ArrayList (instead of just List or Collection) is required here, since this
commenter.addRemainingComments(declarations[i]); * 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);
if (preprocessorStatements.isEmpty() || comments.isEmpty()) {
return;
}
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 commentMap; }
}
private static <T extends IASTNode> T getNextNodeInTu(Iterator<T> iter) {
if (!iter.hasNext()) {
return null;
}
T next = iter.next();
return next.isPartOfTranslationUnitFile() ? next : getNextNodeInTu(iter);
}
} }

View file

@ -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.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName; 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.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; 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.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -43,6 +43,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
protected NodeCommentMap commentMap; protected NodeCommentMap commentMap;
private NodeCommenter nodeCommenter; private NodeCommenter nodeCommenter;
private IASTDeclaration lastDecl;
{ {
shouldVisitBaseSpecifiers = true; shouldVisitBaseSpecifiers = true;
@ -57,6 +58,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
shouldVisitStatements = true; shouldVisitStatements = true;
shouldVisitTemplateParameters = true; shouldVisitTemplateParameters = true;
shouldVisitTypeIds = true; shouldVisitTypeIds = true;
shouldVisitTranslationUnit = true;
} }
public ASTCommenterVisitor(CommentHandler commHandler, NodeCommentMap commentMap) { public ASTCommenterVisitor(CommentHandler commHandler, NodeCommentMap commentMap) {
@ -69,10 +71,6 @@ public class ASTCommenterVisitor extends ASTVisitor {
nodeCommenter = new NodeCommenter(this, commHandler, commentMap); nodeCommenter = new NodeCommenter(this, commHandler, commentMap);
} }
public void addRemainingComments(IASTDeclaration declaration) {
nodeCommenter.appendRemainingComments(declaration);
}
@Override @Override
public int visit(IASTName name) { public int visit(IASTName name) {
return nodeCommenter.appendComments((ASTNode) name); return nodeCommenter.appendComments((ASTNode) name);
@ -100,7 +98,10 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override @Override
public int visit(IASTDeclaration declaration) { public int visit(IASTDeclaration declaration) {
return nodeCommenter.appendComments((ASTNode) declaration); if (ASTCommenter.isInWorkspace(declaration)) {
return nodeCommenter.appendComments((ASTNode) declaration);
}
return PROCESS_SKIP;
} }
@Override @Override
@ -131,9 +132,13 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override @Override
public int leave(IASTTranslationUnit tu) { public int leave(IASTTranslationUnit tu) {
nodeCommenter.appendComments((ASTNode) tu); nodeCommenter.appendComments((ASTNode) tu);
if (lastDecl != null) {
nodeCommenter.appendRemainingComments(lastDecl);
}
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
} }
@Override @Override
public int leave(IASTName name) { public int leave(IASTName name) {
nodeCommenter.appendComments((ASTNode) name); nodeCommenter.appendComments((ASTNode) name);
@ -142,6 +147,7 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override @Override
public int leave(IASTDeclaration declaration) { public int leave(IASTDeclaration declaration) {
lastDecl = declaration;
nodeCommenter.appendComments((ASTNode) declaration); nodeCommenter.appendComments((ASTNode) declaration);
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
} }
@ -215,5 +221,5 @@ public class ASTCommenterVisitor extends ASTVisitor {
public int leave( IASTComment comment){ public int leave( IASTComment comment){
nodeCommenter.appendComments((ASTNode) comment); nodeCommenter.appendComments((ASTNode) comment);
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
} }
} }