1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 04:15:35 +02:00

Javadoc for the ast-rewrite facility, by Emanuel Graf, bug 226239.

This commit is contained in:
Markus Schorn 2008-04-09 11:46:22 +00:00
parent b5ad408a60
commit e4ae8a89a7
20 changed files with 371 additions and 147 deletions

View file

@ -14,11 +14,19 @@ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationStore;
import org.eclipse.cdt.internal.core.dom.rewrite.changegenerator.ChangeGeneratorWriterVisitor;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
*
* ASTWriter main class. Generates source code from <code>IASTNode</code>. Uses a
* <codeC>hangeGeneratorWriterVisitor</code> to generate the code for the given
* nodes.
*
* @see ChangeGeneratorWriterVisitor
*
* @author Emanuel Graf
*
*
*/
public class ASTWriter {
@ -27,19 +35,47 @@ public class ASTWriter {
private String givenIndentation = ""; //$NON-NLS-1$
/**
* Creates a <code>ASTWriter</code>.
*/
public ASTWriter() {
super();
}
/**
* Creates a <code>ASTWriter</code> that indents the code.
*
* @param givenIndentation The indention added to each line
*/
public ASTWriter(String givenIndentation) {
super();
this.givenIndentation = givenIndentation;
}
/**
*
* Genereates the source code representing this node.
*
* @param rootNode Node to write.
* @return A <code>String</code> representing the source code for the node.
* @throws ProblemRuntimeException if the node or one of it's children is a <code>IASTProblemNode</code>.
*/
public String write(IASTNode rootNode) throws ProblemRuntimeException {
return write(rootNode, null, new NodeCommentMap());
}
/**
*
* Genereates the source code representing this node including comments.
*
* @param rootNode Node to write.
* @param fileScope
* @param commentMap Node Comment Map <code>ASTCommenter</code>
* @return A <code>String</code> representing the source code for the node.
* @throws ProblemRuntimeException if the node or one of it's children is a <code>IASTProblemNode</code>.
*
* @see ASTCommenter#getCommentedNodeMap(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit)
*/
public String write(IASTNode rootNode, String fileScope, NodeCommentMap commentMap) throws ProblemRuntimeException {
transformationVisitor = new ChangeGeneratorWriterVisitor(modificationStore, givenIndentation, fileScope, commentMap);
rootNode.accept(transformationVisitor);

View file

@ -30,6 +30,17 @@ import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
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 CPPASTVisitor {
protected Scribe scribe = new Scribe();

View file

@ -20,9 +20,15 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
/**
* @author Emanuel Graf
*
*
* This class serves as a container to pass several nodes to the
* <code>ASTWriter</code>. This container is used if source code for several sibling nodes but
* for their common parent node should be generated.
*
* @author Emanuel Graf IFS
*
*/
public class ContainerNode extends ASTNode {

View file

@ -35,9 +35,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of declaration specifier nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTDeclSpecifier
* @author Emanuel Graf IFS
*
*/
public class DeclSpecWriter extends NodeWriter {
private static final String MUTABLE = "mutable "; //$NON-NLS-1$
@ -76,16 +83,15 @@ public class DeclSpecWriter extends NodeWriter {
int type = simpDeclSpec.getType();
if(type <= IASTSimpleDeclSpecifier.t_last) {
return getASTSimpleDecSpecifier(type);
}else {
switch (type) {
case ICPPASTSimpleDeclSpecifier.t_bool:
return CPP_BOOL;
case ICPPASTSimpleDeclSpecifier.t_wchar_t:
return WCHAR_T;
default:
System.err.println("Unknow Specifiertype: " + type); //$NON-NLS-1$
throw new IllegalArgumentException("Unknow Specifiertype: " + type); //$NON-NLS-1$
}
}
switch (type) {
case ICPPASTSimpleDeclSpecifier.t_bool:
return CPP_BOOL;
case ICPPASTSimpleDeclSpecifier.t_wchar_t:
return WCHAR_T;
default:
System.err.println("Unknow Specifiertype: " + type); //$NON-NLS-1$
throw new IllegalArgumentException("Unknow Specifiertype: " + type); //$NON-NLS-1$
}
}
@ -93,14 +99,13 @@ public class DeclSpecWriter extends NodeWriter {
int type = simpDeclSpec.getType();
if(type <= IASTSimpleDeclSpecifier.t_last) {
return getASTSimpleDecSpecifier(type);
}else {
switch (type) {
case ICASTSimpleDeclSpecifier.t_Bool:
return _BOOL;
default:
System.err.println("Unknow Specifiertype: " + type); //$NON-NLS-1$
throw new IllegalArgumentException("Unknow Specifiertype: " + type); //$NON-NLS-1$
}
}
switch (type) {
case ICASTSimpleDeclSpecifier.t_Bool:
return _BOOL;
default:
System.err.println("Unknow Specifiertype: " + type); //$NON-NLS-1$
throw new IllegalArgumentException("Unknow Specifiertype: " + type); //$NON-NLS-1$
}
}

View file

@ -38,9 +38,16 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.IASTDeclarationAmbiguity;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of declaration nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTDeclaration
* @author Emanuel Graf IFS
*
*/
public class DeclarationWriter extends NodeWriter{

View file

@ -35,9 +35,16 @@ import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of declarator nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTDeclarator
* @author Emanuel Graf IFS
*
*/
public class DeclaratorWriter extends NodeWriter {

View file

@ -41,9 +41,16 @@ import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of expression nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTExpression
* @author Emanuel Graf IFS
*
*/
public class ExpressionWriter extends NodeWriter{
@ -243,23 +250,22 @@ public class ExpressionWriter extends NodeWriter{
default:
return false;
}
}else {
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_throw:
case ICPPASTUnaryExpression.op_typeid:
return true;
default:
return false;
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return true;
default:
return false;
}
}
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_throw:
case ICPPASTUnaryExpression.op_typeid:
return true;
default:
return false;
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return true;
default:
return false;
}
}
return false;
@ -278,17 +284,16 @@ public class ExpressionWriter extends NodeWriter{
default:
return false;
}
}else {
if (unExp instanceof ICPPASTUnaryExpression) {
return unaryExpressionType == ICPPASTUnaryExpression.op_typeid;
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return true;
default:
return false;
}
}
if (unExp instanceof ICPPASTUnaryExpression) {
return unaryExpressionType == ICPPASTUnaryExpression.op_typeid;
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return true;
default:
return false;
}
}
return false;
@ -322,27 +327,26 @@ public class ExpressionWriter extends NodeWriter{
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
}
}else {
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_throw:
return THROW;
case ICPPASTUnaryExpression.op_typeid:
return TYPEID_OP;
default:
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
return ALIGNOF_OP;
case IGNUASTUnaryExpression.op_typeof:
return TYPEOF_OP;
default:
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
}
}
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_throw:
return THROW;
case ICPPASTUnaryExpression.op_typeid:
return TYPEID_OP;
default:
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
return ALIGNOF_OP;
case IGNUASTUnaryExpression.op_typeof:
return TYPEOF_OP;
default:
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
}
}
System.err.println("Unkwown unaryExpressionType: " + unaryExpressionType); //$NON-NLS-1$
@ -363,24 +367,23 @@ public class ExpressionWriter extends NodeWriter{
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
}
}else {
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_typeid:
return CLOSING_BRACKET_OP;
default:
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return CLOSING_BRACKET_OP;
default:
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
}
}
if (unExp instanceof ICPPASTUnaryExpression) {
switch (unaryExpressionType) {
case ICPPASTUnaryExpression.op_typeid:
return CLOSING_BRACKET_OP;
default:
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
}
}else if (unExp instanceof IGNUASTUnaryExpression) {
switch (unaryExpressionType) {
case IGNUASTUnaryExpression.op_alignOf:
case IGNUASTUnaryExpression.op_typeof:
return CLOSING_BRACKET_OP;
default:
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
throw new IllegalArgumentException("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$
}
}
System.err.println("Unkwown unaryExpressionType " + unaryExpressionType); //$NON-NLS-1$

View file

@ -23,9 +23,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of initializer nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTInitializer
* @author Emanuel Graf IFS
*
*/
public class InitializerWriter extends NodeWriter{

View file

@ -16,6 +16,13 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
/**
*
* Recognizes nodes that are the result of an macro expansion and replaces them
* with a suitable macro call.
* @author Emanuel Graf IFS
*
*/
public class MacroExpansionHandler {
private int lastMacroExpOffset;
@ -61,13 +68,12 @@ public class MacroExpansionHandler {
if (macroNode.asFileLocation().getNodeOffset() == lastMacroExpOffset) {
return true;
} else {
if (write) {
lastMacroExpOffset = macroNode.asFileLocation().getNodeOffset();
scribe.print(node.getRawSignature());
}
return true;
}
if (write) {
lastMacroExpOffset = macroNode.asFileLocation().getNodeOffset();
scribe.print(node.getRawSignature());
}
return true;
}
}

View file

@ -21,9 +21,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of name nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTName
* @author Emanuel Graf IFS
*
*/
public class NameWriter extends NodeWriter {
@ -97,15 +104,13 @@ public class NameWriter extends NodeWriter {
ICPPASTTemplateId tempId, int i) {
if(i <= 0){
return false;
}else{
if (qname.getNames()[i-1] instanceof ICPPASTTemplateId) {
return true;
}else{
IBinding binding = qname.getNames()[i-1].resolveBinding();
if (binding instanceof CPPTemplateTypeParameter) {
return true;
}
}
}
if (qname.getNames()[i-1] instanceof ICPPASTTemplateId) {
return true;
}
IBinding binding = qname.getNames()[i-1].resolveBinding();
if (binding instanceof CPPTemplateTypeParameter) {
return true;
}
return isDependentName(qname, tempId, i-1);
}

View file

@ -16,6 +16,14 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
*
* Base class for node writers. This class contains methods and string constants
* used by multiple node writers.
*
* @author Emanuel Graf IFS
*
*/
public class NodeWriter {
protected Scribe scribe;

View file

@ -11,8 +11,18 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemHolder;
/**
*
* This exception is thrown if a problem nod is passed to the astwriter. The Exception
* contains the <code>IASTProblemHolder</code> that was passed to the writer.
*
* @see IASTProblem
* @author Emanuel Graf IFS
*
*/
public class ProblemRuntimeException extends RuntimeException {
private static final long serialVersionUID = -3661425564246498786L;

View file

@ -11,6 +11,15 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
/**
*
* This class is responsible for the string concatination and the management of
* the indentations.
*
* @since 5.0
* @author Emanuel Graf IFS
*
*/
public class Scribe {

View file

@ -45,6 +45,16 @@ import org.eclipse.cdt.internal.core.dom.rewrite.util.FileContentHelper;
import org.eclipse.cdt.internal.core.dom.rewrite.util.FileHelper;
import org.eclipse.core.resources.IFile;
/**
*
* Generates source code of statement nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see IASTStatement
* @author Emanuel Graf IFS
*
*/
public class StatementWriter extends NodeWriter{
private static final String DEFAULT = "default:"; //$NON-NLS-1$

View file

@ -19,9 +19,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
/**
* @author Emanuel Graf
*
*
* Generates source code of template parameter nodes. The actual string operations are delegated
* to the <code>Scribe</code> class.
*
* @see Scribe
* @see ICPPASTTemplateParameter
* @author Emanuel Graf IFS
*
*/
public class TemplateParameterWriter extends NodeWriter {

View file

@ -22,11 +22,25 @@ import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
/**
* @author Guido Zgraggen IFS
*
* This is the startpoint of the whole comment handling process. The creation of the
* NodeCommentMap is based on the IASTTranslationUnit. From this TranslationUnit the comments
* are extracted and skipped if they belong not to the same workspace. An ASTCommenterVisitor
* is initialized with this collection of comments. And the visit process can start.
*
* @see org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommenter
* @see org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap
*
* @author Guido Zgraggen IFS
*/
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
* @return NodeCommentMap
*/
public static NodeCommentMap getCommentedNodeMap(IASTTranslationUnit transUnit){
if(transUnit== null) {
return new NodeCommentMap();

View file

@ -32,8 +32,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompositeTypeSpecifier
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompoundStatement;
/**
* @author Guido Zgraggen IFS
* A visitor for the comments. Calls the NodeCommenter to assign the comments.
*
* @see org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommenter
*
* @author Guido Zgraggen IFS
*/
public class ASTCommenterVisitor extends CPPASTVisitor {

View file

@ -16,8 +16,11 @@ import java.util.Vector;
import org.eclipse.cdt.core.dom.ast.IASTComment;
/**
* @author Guido Zgraggen IFS
* The CommentHandler is initialized with all the comment which should be processed.
* During the process of comment assignment this comment collection is work through one
* after another until no more comments are left.
*
* @author Guido Zgraggen IFS
*/
public class CommentHandler {

View file

@ -18,14 +18,22 @@ import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* The NodeCommentMap is the map where all the comments are assigned to a node. For better
* performance the comments are stored in three different maps which have the same name as
* the relative position of the comment.
*
* @author Guido Zgraggen IFS
*
*/
public class NodeCommentMap {
protected final HashMap<IASTNode, ArrayList<IASTComment>> leadingMap = new HashMap<IASTNode, ArrayList<IASTComment>>();
protected final HashMap<IASTNode, ArrayList<IASTComment>> trailingMap = new HashMap<IASTNode, ArrayList<IASTComment>>();
protected final HashMap<IASTNode, ArrayList<IASTComment>> freestandingMap = new HashMap<IASTNode, ArrayList<IASTComment>>();
/**
* Add a comment to the map with the trailing comments.
* @param node The node is the key.
* @param comment The comment is the value
*/
public void addTrailingCommentToNode(IASTNode node, IASTComment comment){
ArrayList<IASTComment> comments = trailingMap.get(node);
if(comments == null){
@ -35,6 +43,13 @@ public class NodeCommentMap {
trailingMap.put(node, comments);
}
/**
* Returns an ArrayList for the given node. This ArrayList contains all the comments
* which are assigned to this specific node. If no comments are available an empty
* ArrayList is returned.
* @param node The key to fetch the associated comments.
* @return ArrayList
*/
public ArrayList<IASTComment> getTrailingCommentsForNode(IASTNode node){
if(trailingMap.get(node) == null) {
return new ArrayList<IASTComment>();
@ -42,6 +57,11 @@ public class NodeCommentMap {
return trailingMap.get(node);
}
/**
* Add a comment to the map with the leading comments.
* @param node The node is the key.
* @param comment The comment is the value
*/
public void addLeadingCommentToNode(IASTNode node, IASTComment comment){
ArrayList<IASTComment> comments = leadingMap.get(node);
if(comments == null){
@ -51,6 +71,13 @@ public class NodeCommentMap {
leadingMap.put(node, comments);
}
/**
* Returns an ArrayList for the given node. This ArrayList contains all the comments
* which are assigned to this specific node. If no comments are available an empty
* ArrayList is returned.
* @param node The key to fetch the associated comments.
* @return ArrayList
*/
public ArrayList<IASTComment> getLeadingCommentsForNode(IASTNode node){
if(leadingMap.get(node) == null) {
return new ArrayList<IASTComment>();
@ -58,6 +85,11 @@ public class NodeCommentMap {
return leadingMap.get(node);
}
/**
* Add a comment to the map with the freestanding comments.
* @param node The node is the key.
* @param comment The comment is the value
*/
public void addFreestandingCommentToNode(IASTNode node, IASTComment comment){
ArrayList<IASTComment> comments = freestandingMap.get(node);
if(comments == null){
@ -67,6 +99,13 @@ public class NodeCommentMap {
freestandingMap.put(node, comments);
}
/**
* Returns an ArrayList for the given node. This ArrayList contains all the comments
* which are assigned to this specific node. If no comments are available an empty
* ArrayList is returned.
* @param node The key to fetch the associated comments.
* @return ArrayList
*/
public ArrayList<IASTComment> getFreestandingCommentsForNode(IASTNode node){
if(freestandingMap.get(node) == null) {
return new ArrayList<IASTComment>();
@ -74,15 +113,26 @@ public class NodeCommentMap {
return freestandingMap.get(node);
}
/**
* Returns the HashMap with all leading maps. Used only for test purpose
* @return HashMap of all leading comments
*/
public HashMap<IASTNode, ArrayList<IASTComment>> getLeadingMap() {
return leadingMap;
}
/**
* Returns the HashMap with all trailing maps. Used only for test purpose
* @return HashMap of all trailing comments
*/
public HashMap<IASTNode, ArrayList<IASTComment>> getTrailingMap() {
return trailingMap;
}
/**
* Returns the HashMap with all freestanding maps. Used only for test purpose
* @return HashMap of all freestanding comments
*/
public HashMap<IASTNode, ArrayList<IASTComment>> getFreestandingMap() {
return freestandingMap;
}
}

View file

@ -41,8 +41,27 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* @author Guido Zgraggen IFS
* The NodeCommenter contains all the logic that is needed for the ASTCommentVisitor to assign the comments
* to the suitable node. Together with the ASTCommenterVisitor it fills all the comments with the correspondent
* node into the NodeCommentMap.
*
* Following, a little explanation of the assignment logic. It is only a loose illustration a detailed description
* would include a combined explanation of ASTCommenterVisitor and NodeCommenter.<br>
* To understand the logic we define the three types of comments:<br>
* leading comments - Comments before a statement, declaration, or definition.<br>
* trailing comments - Comments right after the AST node on the same line.<br>
* freestanding comments - Comments before a closing brace such as they occur in
* namespace-, class- and method-definitions or at the end of a file.<br>
*
* The first comment is fetched and the position of it is compared to the position of the actual node. If
* the position of the comment is smaller than the comment is added to the node as leading. If it is behind the node
* but on the same line it is added as trailing. If one of these possibilities match the next comment is fetched for
* the same check. If it doesn't match the same procedure is done for all the child nodes. After checking the sub nodes
* the actual node is checked again if the comment is trailing. Then there is also the possibility that this comment is
* freestanding. This is the case when the comment is not added to any child node but the position is smaller den
* the end position of the node.
*
* @author Guido Zgraggen IFS
*/
public class NodeCommenter {
@ -130,31 +149,29 @@ public class NodeCommenter {
if(OffsetHelper.getNodeOffset(com) < OffsetHelper.getNodeEndPoint(node) + 2) {
return true;
}
else {
IPath path = new Path(node.getContainingFilename());
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
IPath path = new Path(node.getContainingFilename());
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
//XXX HSR Guido: Possible Performance Issue (File access)
try {
InputStream is = file.getContents();
//XXX HSR Guido: Possible Performance Issue (File access)
try {
InputStream is = file.getContents();
int length = OffsetHelper.getNodeOffset(com)-OffsetHelper.getNodeEndPoint(node);
byte[] b = new byte[length];
int length = OffsetHelper.getNodeOffset(com)-OffsetHelper.getNodeEndPoint(node);
byte[] b = new byte[length];
is.skip(OffsetHelper.getNodeEndPoint(node));
is.read(b, 0, length);
is.skip(OffsetHelper.getNodeEndPoint(node));
is.read(b, 0, length);
for(byte bb : b) {
if(!Character.isWhitespace(bb)) {
is.close();
return false;
}
}
is.close();
return true;
} catch (Exception e) {
return false;
}
for(byte bb : b) {
if(!Character.isWhitespace(bb)) {
is.close();
return false;
}
}
is.close();
return true;
} catch (Exception e) {
return false;
}
}