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
#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

View file

@ -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;
}
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) {
private static boolean isCommentDirectlyBeforePreprocessorStatement(IASTComment comment,
IASTPreprocessorStatement statement, IASTTranslationUnit tu) {
if (tu == null || tu.getDeclarations().length == 0) {
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;
}
}
}
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;
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 false;
}
private static NodeCommentMap addCommentsToCommentMap(IASTTranslationUnit rootNode,
List<IASTComment> comments){
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);
IASTDeclaration[] declarations = rootNode.getDeclarations();
for (int i = 0; i < declarations.length; i++) {
if (isInWorkspace(declarations[i])) {
assignPreprocessorComments(commentMap, comments, tu);
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]);
}
}
}
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);
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);
}
}
}
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.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,8 +98,11 @@ public class ASTCommenterVisitor extends ASTVisitor {
@Override
public int visit(IASTDeclaration declaration) {
if (ASTCommenter.isInWorkspace(declaration)) {
return nodeCommenter.appendComments((ASTNode) declaration);
}
return PROCESS_SKIP;
}
@Override
public int visit(IASTDeclarator declarator) {
@ -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;
}