From c558463abee55727d9c47c4e776899af89887d95 Mon Sep 17 00:00:00 2001 From: Lukas Felber Date: Mon, 10 Feb 2014 16:28:28 +0100 Subject: [PATCH] Bug 427002. [ast rewrite] Comments originating from other translation units are now automatically taken into consideration when rewriting. Change-Id: If535ab6cdd1ec293a0d95a6f726d848f6348f0ed Signed-off-by: Lukas Felber Reviewed-on: https://git.eclipse.org/r/21761 Reviewed-by: Thomas Corbat IP-Clean: Thomas Corbat Tested-by: Thomas Corbat --- .../comenthandler/CommentHandlingTest.java | 14 ++--- .../CommentHandlingTestSuite.java | 8 +-- .../CommentHandlingWithRewriteTest.java | 61 +++++++++++++++++++ .../CommentHandlingWithRewriteTest.rts | 21 +++++++ .../cdt/core/dom/rewrite/ASTRewrite.java | 1 + .../rewrite/commenthandler/ASTCommenter.java | 19 +++++- .../commenthandler/NodeCommentMap.java | 17 ++++++ 7 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingWithRewriteTest.java create mode 100644 core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingWithRewriteTest.rts diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTest.java index 2846fdcb38c..b9e79c222d0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTest.java @@ -97,15 +97,15 @@ public class CommentHandlingTest extends RewriteBaseTest { for (String fileName : fileMap.keySet()) { TestSourceFile file = fileMap.get(fileName); - NodeCommentMap nodeMap = ASTCommenter.getCommentedNodeMap(getUnit(fileName)); - - StringBuilder expectedResultBuilder = buildExpectedResult(file); - StringBuilder actualResultBuilder = buildActualResult(nodeMap); - - assertEquals(expectedResultBuilder.toString(), actualResultBuilder.toString()); + NodeCommentMap nodeMap = getNodeMapForFile(fileName); + assertEquals(buildExpectedResult(file).toString(), buildActualResult(nodeMap).toString()); } } + protected NodeCommentMap getNodeMapForFile(String fileName) throws Exception { + return ASTCommenter.getCommentedNodeMap(getUnit(fileName)); + } + private StringBuilder buildExpectedResult(TestSourceFile file) { Matcher matcher = Pattern.compile(CommentHandlingTest.getSeparatingRegexp(), Pattern.MULTILINE | Pattern.DOTALL).matcher(file.getExpectedSource()); @@ -177,7 +177,7 @@ public class CommentHandlingTest extends RewriteBaseTest { ANY_CHAR_REGEXP + FREESTANDING_COMMENT_SEPARATOR + ANY_CHAR_REGEXP; } - private IASTTranslationUnit getUnit(String fileName) throws CoreException { + protected IASTTranslationUnit getUnit(String fileName) throws CoreException { ITranslationUnit tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create( project.getFile(fileName)); return tu.getAST(); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTestSuite.java index 409ff7bfe14..cdedf69aa53 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2014 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -20,11 +20,11 @@ import org.eclipse.cdt.core.parser.tests.rewrite.RewriteTester; * @author Guido Zgraggen IFS */ public class CommentHandlingTestSuite extends TestSuite { - + public static Test suite() throws Exception { TestSuite suite = new TestSuite(CommentHandlingTestSuite.class.getName()); - suite.addTest(RewriteTester.suite("CommentTests", - "resources/rewrite/CommentHandlingTestSource.rts")); //$NON-NLS-1$ + suite.addTest(RewriteTester.suite("CommentTests", "resources/rewrite/CommentHandlingTestSource.rts")); //$NON-NLS-1$ + suite.addTest(RewriteTester.suite("CommentMultiFileTests", "resources/rewrite/CommentHandlingWithRewriteTest.rts")); //$NON-NLS-1$ suite.addTestSuite(NodeCommentMapTest.class); return suite; } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingWithRewriteTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingWithRewriteTest.java new file mode 100644 index 00000000000..bc58ca8281d --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/comenthandler/CommentHandlingWithRewriteTest.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2014 Institute for Software. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Lukas Felber (IFS) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.rewrite.comenthandler; + +import java.lang.reflect.Field; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.parser.tests.rewrite.TestSourceFile; +import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; +import org.eclipse.text.edits.TextEditGroup; + +public class CommentHandlingWithRewriteTest extends CommentHandlingTest { + private ASTRewrite newRewrite; + + public CommentHandlingWithRewriteTest(String name, List files) { + super(name, files); + } + + @Override + protected void runTest() throws Throwable { + IASTTranslationUnit tu = getUnit("main.cpp"); + IASTTranslationUnit otherTu = getUnit("other.cpp"); + + IASTNodeSelector selector = tu.getNodeSelector(null); + IASTNodeSelector otherSelector = otherTu.getNodeSelector(null); + + IASTNode fooBody = selector.findNode(11, 27); + IASTNode iNode = selector.findEnclosingNode(26, 10).getParent(); + IASTNode jNode = otherSelector.findNode(20, 10); + + ASTRewrite rewrite = ASTRewrite.create(tu); + newRewrite = rewrite.insertBefore(fooBody, iNode, jNode, new TextEditGroup("test group")); + super.runTest(); + } + + @Override + protected NodeCommentMap getNodeMapForFile(String fileName) throws Exception { + if (fileName.equals("main.cpp")) { + return getNodeMapFromRewrite(newRewrite); + } + return super.getNodeMapForFile(fileName); + } + + private NodeCommentMap getNodeMapFromRewrite(ASTRewrite rewrite) throws Exception { + Field commentMapField = rewrite.getClass().getDeclaredField("fCommentMap"); + commentMapField.setAccessible(true); + return (NodeCommentMap) commentMapField.get(rewrite); + } +} diff --git a/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingWithRewriteTest.rts b/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingWithRewriteTest.rts new file mode 100644 index 00000000000..bbac106fb64 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/rewrite/CommentHandlingWithRewriteTest.rts @@ -0,0 +1,21 @@ +//!Comment Handling Test - Rewrite with otherTu node +//#org.eclipse.cdt.core.parser.tests.rewrite.comenthandler.CommentHandlingWithRewriteTest +//@main.cpp +void foo() { + //comment1 + int i = 0; +} +//= +=>leading +int j = 1; = //other.cpp comment +int i = 0; = //comment1 +=>trailing +=>freestanding +//@other.cpp +//other.cpp comment +int j = 1; +//= +=>leading +int j = 1; = //other.cpp comment +=>trailing +=>freestanding diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/ASTRewrite.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/ASTRewrite.java index 99086ee473e..d785fd422e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/ASTRewrite.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/ASTRewrite.java @@ -188,6 +188,7 @@ public final class ASTRewrite { } mod= new ASTModification(ModificationKind.INSERT_BEFORE, insertionPoint, newNode, editGroup); } + ASTCommenter.addCommentsToMap(newNode.getTranslationUnit(), fCommentMap); fModificationStore.storeModification(fParentMod, mod); return new ASTRewrite(newNode, fModificationStore, mod, fCommentMap); } 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 8fc605eee4f..9fd70e52f6f 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 @@ -179,6 +179,23 @@ public class ASTCommenter { if (ast == null) { return commentMap; } + addCommentsToMap(ast, commentMap); + return commentMap; + } + + /** + * Adds all comments given in {@code ast} to the {@code commentMap}. Calling this twice will have no + * effect. + * + * @param ast + * the AST which contains the comments to add + * @param commentMap + * the comment map to which the comments are added to + */ + public static void addCommentsToMap(IASTTranslationUnit ast, NodeCommentMap commentMap) { + if (ast == null || commentMap.isASTCovered(ast)) { + return; + } IASTComment[] commentsArray = ast.getComments(); List comments = new ArrayList(commentsArray.length); for (IASTComment comment : commentsArray) { @@ -189,8 +206,8 @@ public class ASTCommenter { assignPreprocessorComments(commentMap, comments, ast); CommentHandler commentHandler = new CommentHandler(comments); ASTCommenterVisitor commenter = new ASTCommenterVisitor(commentHandler, commentMap); + commentMap.setASTCovered(ast); ast.accept(commenter); - return commentMap; } private static boolean isCommentDirectlyBeforePreprocessorStatement(IASTComment comment, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/NodeCommentMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/NodeCommentMap.java index 74303f4def3..63a9c471141 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/NodeCommentMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/commenthandler/NodeCommentMap.java @@ -19,6 +19,7 @@ import java.util.Map; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes; /** @@ -32,6 +33,7 @@ public class NodeCommentMap { protected final Map> leadingMap = new HashMap>(); protected final Map> trailingMap = new HashMap>(); protected final Map> freestandingMap = new HashMap>(); + protected final List coveredUnits = new ArrayList(); /** * Add a comment to the map with the trailing comments. @@ -188,4 +190,19 @@ public class NodeCommentMap { } return endOffset; } + + /** + * Makes this comment map aware that comments of the given {@code ast} are already contained in the map. + * This can be used to make sure no-one accidentally tries to re-add already contained comments. + */ + public void setASTCovered(IASTTranslationUnit ast) { + coveredUnits.add(ast); + } + + /** + * Checks whether comments of the {@code ast} are already present in the map. + */ + public boolean isASTCovered(IASTTranslationUnit ast) { + return coveredUnits.contains(ast); + } }