/******************************************************************************* * Copyright (c) 2008 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 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Institute for Software - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.core.parser.tests.rewrite.comenthandler; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.TreeSet; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.tests.rewrite.RewriteBaseTest; import org.eclipse.cdt.core.parser.tests.rewrite.TestSourceFile; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; import org.eclipse.core.runtime.CoreException; /** * This test tests the behavoir of the class ASTCommenter. It checks if the ASTCommenter assigns the comments contained in an AST to the right ASTNodes.<br> * The source for the CommentHandling tests is located at /resources/rewrite/CommentHandlingTestSource.rts.<br> * This file contains the source code and the expected output for all the tests. Following a little example how such a test looks like:<br><br> * * <code><pre> * //!NameOfTheTest - will be used as JUnit test name * //#org.eclipse.cdt.core.parser.tests.rewrite.comenthandler.CommentHandlingTest * //@NameOfASourceFile.h * class myTestClass * { * //myLeadingComment * void aMethod(); //myTrailingComment * //myFreestandingComment * //myFreestandingComment2 * }; * * //= * =>leading * void aMethod(); = //myLeadingComment * * =>trailing * void aMethod(); = //myTrailingComment * * =>freestanding * void aMethod(); = //myFreestandingComment , //myFreestandingComment2 * </pre></code> * * The second line (//#org.eclipse.cdt...) indicates the test class (in this case this class).<br> * The "//=" indicates the beginning of the expected test result.<br> * The test result contains three sections (separated by "=>leading", "=>trailing" and "=>freestanding").<br> * Each section contains the raw signature of the node to which a comment is assigned plus " = " and the comment. If there are several comments * assigned to the same node they are concatenated with a " , ". * * @author Guido Zgraggen IFS, Lukas Felber IFS * */ public class CommentHandlingTest extends RewriteBaseTest { private static final String ANY_CHAR_REGEXP = "(.*)"; //$NON-NLS-1$ private static final String SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ private static final String LEADING_COMMENT_SEPARATOR = "=>leading"; //$NON-NLS-1$ private static final String TRAILING_COMMENT_SEPARATOR = "=>trailing"; //$NON-NLS-1$ private static final String FREESTANDING_COMMENT_SEPARATOR = "=>freestanding"; //$NON-NLS-1$ private static final String LEADING_COMMENT_TITLE = "<<<=== Leading Comment Test Section ===>>>"; //$NON-NLS-1$ private static final String TRAILING_COMMENT_TITLE = "<<<=== Trailing Comment Test Section ===>>>"; //$NON-NLS-1$ private static final String FREESTANDING_COMMENT_TITLE = "<<<=== Freestanding Comment Test Section ===>>>"; //$NON-NLS-1$ public CommentHandlingTest(String name, Vector<TestSourceFile> files) { super(name, files); } @Override protected void runTest() throws Throwable { if (fileMap.size() == 0) { fail("No file for testing"); //$NON-NLS-1$ } 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()); } } private StringBuilder buildExpectedResult(TestSourceFile file) { Matcher matcher = Pattern.compile(CommentHandlingTest.getSeparatingRegexp(), Pattern.MULTILINE | Pattern.DOTALL).matcher(file.getExpectedSource()); if (!matcher.find()) { fail("Missing expected section. Expected result code must be of the following format:\n\"=>leading\n...\n=>trailing\n...\n=>freestanding\""); //$NON-NLS-1$ } StringBuilder expectedResultBuilder = new StringBuilder(); String leadingResult = matcher.group(1); String trailingResult = matcher.group(2); String freestandingResult = matcher.group(3); appendLineTrimmed(expectedResultBuilder, LEADING_COMMENT_TITLE); appendLineTrimmed(expectedResultBuilder, leadingResult); appendLineTrimmed(expectedResultBuilder, TRAILING_COMMENT_TITLE); appendLineTrimmed(expectedResultBuilder, trailingResult); appendLineTrimmed(expectedResultBuilder, FREESTANDING_COMMENT_TITLE); appendLineTrimmed(expectedResultBuilder, freestandingResult); return expectedResultBuilder; } private StringBuilder buildActualResult(NodeCommentMap nodeMap) { StringBuilder actualResultBuilder = new StringBuilder(); appendLineTrimmed(actualResultBuilder, LEADING_COMMENT_TITLE); appendLineTrimmed(actualResultBuilder, getCommentMapResult(nodeMap.getLeadingMap())); appendLineTrimmed(actualResultBuilder, TRAILING_COMMENT_TITLE); appendLineTrimmed(actualResultBuilder, getCommentMapResult(nodeMap.getTrailingMap())); appendLineTrimmed(actualResultBuilder, FREESTANDING_COMMENT_TITLE); appendLineTrimmed(actualResultBuilder, getCommentMapResult(nodeMap.getFreestandingMap())); return actualResultBuilder; } private String getCommentMapResult(HashMap<IASTNode, ArrayList<IASTComment>> map) { TreeSet<IASTNode> keyTree = new TreeSet<IASTNode>(new NodeOffsetComparator()); keyTree.addAll(map.keySet()); StringBuilder output = new StringBuilder(); for (IASTNode actNode : keyTree) { ArrayList<IASTComment> comments = map.get(actNode); output.append(getSignature(actNode) + " = "); //$NON-NLS-1$ boolean first = true; for (IASTComment actComment : comments) { if (!first) { output.append(" , "); //$NON-NLS-1$ } output.append(actComment.getRawSignature()); first = false; } output.append(SEPARATOR); } return output.toString().trim(); } private String getSignature(IASTNode actNode) { if (actNode instanceof IASTCompositeTypeSpecifier) { IASTCompositeTypeSpecifier comp = (IASTCompositeTypeSpecifier) actNode; return comp.getName().toString(); } else if (actNode instanceof IASTEnumerationSpecifier) { IASTEnumerationSpecifier comp = (IASTEnumerationSpecifier) actNode; return comp.getName().toString(); } return actNode.getRawSignature(); } private static String getSeparatingRegexp() { return LEADING_COMMENT_SEPARATOR + ANY_CHAR_REGEXP + TRAILING_COMMENT_SEPARATOR + ANY_CHAR_REGEXP + FREESTANDING_COMMENT_SEPARATOR + ANY_CHAR_REGEXP; } private IASTTranslationUnit getUnit(String fileName) throws CoreException { ITranslationUnit tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create(project.getFile(fileName)); return tu.getAST(); } private final class NodeOffsetComparator implements Comparator<IASTNode> { public int compare(IASTNode o1, IASTNode o2) { int offDif = o1.getFileLocation().getNodeOffset() - o2.getFileLocation().getNodeOffset(); if (offDif == 0) { return o1.getFileLocation().getNodeLength() - o2.getFileLocation().getNodeLength(); } return offDif; } } private void appendLineTrimmed(StringBuilder builderToAppendTo, String line) { builderToAppendTo.append(line.trim()); builderToAppendTo.append(SEPARATOR); } }