/******************************************************************************* * Copyright (c) 2008, 2011 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 * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; import java.util.ArrayList; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTCopyLocation; 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.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; 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.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.internal.core.dom.rewrite.ASTLiteralNode; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; /** * Visits all nodes, prints leading comments and handles macro expansions. The * source code generation is delegated to severals <code>NodeWriters</code>. * * @see NodeWriter * @see MacroExpansionHandler * * @author Emanuel Graf IFS */ public class ASTWriterVisitor extends ASTVisitor { protected Scribe scribe = new Scribe(); protected NodeCommentMap commentMap; protected ExpressionWriter expWriter; protected DeclSpecWriter declSpecWriter; protected StatementWriter statementWriter; protected DeclaratorWriter declaratorWriter; protected DeclarationWriter declarationWriter; protected InitializerWriter initializerWriter; protected NameWriter nameWriter; protected TemplateParameterWriter tempParameterWriter; protected MacroExpansionHandler macroHandler; { shouldVisitExpressions = true; shouldVisitStatements = true; shouldVisitNames = true; shouldVisitDeclarations = true; shouldVisitDeclSpecifiers = true; shouldVisitDeclarators = true; shouldVisitArrayModifiers= true; shouldVisitInitializers = true; shouldVisitBaseSpecifiers = true; shouldVisitNamespaces = true; shouldVisitTemplateParameters = true; shouldVisitParameterDeclarations = true; shouldVisitTranslationUnit = true; } public ASTWriterVisitor(NodeCommentMap commentMap) { this("", commentMap); //$NON-NLS-1$ } public ASTWriterVisitor(String givenIndentation, NodeCommentMap commentMap) { super(); scribe.setGivenIndentation(givenIndentation); init(commentMap); this.commentMap = commentMap; } private void init(NodeCommentMap commentMap) { macroHandler = new MacroExpansionHandler(scribe); statementWriter = new StatementWriter(scribe, this, commentMap); declaratorWriter = new DeclaratorWriter(scribe, this, commentMap); declarationWriter = new DeclarationWriter(scribe, this, commentMap); declSpecWriter = new DeclSpecWriter(scribe, this, commentMap); expWriter = new ExpressionWriter(scribe, this, macroHandler, commentMap); initializerWriter = new InitializerWriter (scribe, this, commentMap); // ppStmtWriter = new PreprocessorStatementWriter(scribe, this, commentMap); nameWriter = new NameWriter(scribe, this, commentMap); tempParameterWriter = new TemplateParameterWriter(scribe, this, commentMap); } @Override public String toString() { return scribe.toString(); } @Override public int leave(IASTTranslationUnit tu) { for (IASTComment comment : commentMap.getFreestandingCommentsForNode(tu)) { scribe.print(comment.getComment()); scribe.newLine(); } return super.leave(tu); } private void writeLeadingComments(IASTNode node) { for (IASTComment comment : getLeadingComments(node)) { scribe.print(comment.getComment()); scribe.newLine(); } } private ArrayList<IASTComment> getLeadingComments(IASTNode node) { ArrayList<IASTComment> leadingComments = commentMap.getLeadingCommentsForNode(node); IASTNodeLocation[] locs = node.getNodeLocations(); if (locs != null && locs.length > 0 && locs[0] instanceof IASTCopyLocation) { IASTCopyLocation copyLoc = (IASTCopyLocation) locs[0]; leadingComments.addAll(commentMap.getLeadingCommentsForNode(copyLoc.getOriginalNode())); } return leadingComments; } public void visit(ASTLiteralNode lit) { scribe.print(lit.getRawSignature()); } @Override public int visit(IASTName name) { writeLeadingComments(name); if (!macroHandler.checkisMacroExpansionNode(name)) { nameWriter.writeName(name); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTDeclSpecifier declSpec) { writeLeadingComments(declSpec); declSpecWriter.writeDelcSpec(declSpec); return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTExpression expression) { writeLeadingComments(expression); if (!macroHandler.checkisMacroExpansionNode(expression)) { if (expression instanceof IGNUASTCompoundStatementExpression) { IGNUASTCompoundStatementExpression gnuCompStmtExp = (IGNUASTCompoundStatementExpression) expression; gnuCompStmtExp.getCompoundStatement().accept(this); } else { expWriter.writeExpression(expression); } } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTStatement statement) { writeLeadingComments(statement); if (macroHandler.isStatementWithMixedLocation(statement) && !(statement instanceof IASTCompoundStatement)) { return statementWriter.writeMixedStatement(statement); } if (macroHandler.checkisMacroExpansionNode(statement)) { return ASTVisitor.PROCESS_SKIP; } return statementWriter.writeStatement(statement, true); } @Override public int visit(IASTDeclaration declaration) { writeLeadingComments(declaration); if (!macroHandler.checkisMacroExpansionNode(declaration)) { declarationWriter.writeDeclaration(declaration); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTDeclarator declarator) { writeLeadingComments(declarator); if (!macroHandler.checkisMacroExpansionNode(declarator)) { declaratorWriter.writeDeclarator(declarator); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTArrayModifier amod) { if (!macroHandler.checkisMacroExpansionNode(amod)) { declaratorWriter.writeArrayModifier(amod); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTInitializer initializer) { writeLeadingComments(initializer); if (!macroHandler.checkisMacroExpansionNode(initializer)) { initializerWriter.writeInitializer(initializer); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(IASTParameterDeclaration parameterDeclaration) { writeLeadingComments(parameterDeclaration); if (!macroHandler.checkisMacroExpansionNode(parameterDeclaration)) { parameterDeclaration.getDeclSpecifier().accept(this); IASTDeclarator declarator = getParameterDeclarator(parameterDeclaration); if (getParameterName(declarator).toString().length() != 0) { scribe.printSpaces(1); } declarator.accept(this); } return ASTVisitor.PROCESS_SKIP; } protected IASTName getParameterName(IASTDeclarator declarator) { return declarator.getName(); } protected IASTDeclarator getParameterDeclarator(IASTParameterDeclaration parameterDeclaration) { return parameterDeclaration.getDeclarator(); } @Override public int visit(ICPPASTNamespaceDefinition namespace) { writeLeadingComments(namespace); if (!macroHandler.checkisMacroExpansionNode(namespace)) { declarationWriter.writeDeclaration(namespace); } return ASTVisitor.PROCESS_SKIP; } @Override public int visit(ICPPASTTemplateParameter parameter) { writeLeadingComments(parameter); if (!macroHandler.checkisMacroExpansionNode(parameter)) { tempParameterWriter.writeTemplateParameter(parameter); } return ASTVisitor.PROCESS_SKIP; } public void cleanCache() { scribe.cleanCache(); macroHandler.reset(); } }