View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.dfa;
5   
6   import java.util.ArrayList;
7   import java.util.List;
8   import java.util.logging.Logger;
9   import java.util.Stack;
10  
11  import net.sourceforge.pmd.lang.DataFlowHandler;
12  import net.sourceforge.pmd.lang.ast.Node;
13  
14  /**
15   * @author raik
16   *         <p/>
17   *         Structure contains only raw data. A set of nodes which represent a data flow
18   *         and 2 stacks to link the nodes to each other.
19   */
20  public class Structure {
21      private final static Logger LOGGER = Logger.getLogger(Structure.class.getName()); 
22  
23      private final DataFlowHandler dataFlowHandler;
24      private List<DataFlowNode> dataFlow = new ArrayList<DataFlowNode>();
25      private Stack<StackObject> braceStack = new Stack<StackObject>();
26      private Stack<StackObject> continueBreakReturnStack = new Stack<StackObject>();
27      
28      public Structure(DataFlowHandler dataFlowHandler) {
29  	this.dataFlowHandler = dataFlowHandler;
30      }
31  
32      /**
33       * This class encapsulates the access to the DataFlowNode class. Is this worthwhile?
34       * TODO I think it's too confusing to have the DataFlowNode constructor
35       * add the created instance to the List.  I think it'd be clearer if we did
36       * that more "procedurally", i.e., create the object, then add it to the list.
37       */
38      public DataFlowNode createNewNode(Node node) {
39  	return dataFlowHandler.createDataFlowNode(dataFlow, node);
40      }
41  
42      public DataFlowNode createStartNode(int line) {
43  	return new StartOrEndDataFlowNode(this.dataFlow, line, true);
44      }
45  
46      public DataFlowNode createEndNode(int line) {
47  	return new StartOrEndDataFlowNode(this.dataFlow, line, false);
48      }
49  
50      public DataFlowNode getLast() {
51  	return this.dataFlow.get(this.dataFlow.size() - 1);
52      }
53  
54      public DataFlowNode getFirst() {
55  	return this.dataFlow.get(0);
56      }
57  
58      //  ----------------------------------------------------------------------------
59      //	STACK FUNCTIONS
60  
61      /**
62       * The braceStack contains all nodes which are important to link the data
63       * flow nodes. The cbrStack contains continue, break, and return nodes.
64       * There are 2 Stacks because the have to process differently.
65       */
66      public void pushOnStack(int type, DataFlowNode node) {
67  	StackObject obj = new StackObject(type, node);
68  	if (type == NodeType.RETURN_STATEMENT || type == NodeType.BREAK_STATEMENT
69  		|| type == NodeType.CONTINUE_STATEMENT || type == NodeType.THROW_STATEMENT) {
70  	    // ugly solution - stores the type information in two ways
71  	    continueBreakReturnStack.push(obj);
72              LOGGER.finest("continueBreakReturnStack: line " + node.getNode().getBeginLine() 
73                            + ", column " + node.getNode().getBeginColumn() 
74                            +" - " + node.toString()
75                           );
76  	} else {
77  	    braceStack.push(obj);
78              LOGGER.finest("braceStack: line " + node.getNode().getBeginLine() 
79                            + ", column " + node.getNode().getBeginColumn() 
80                            +" - " + node.toString()
81                           );
82  	}
83  	node.setType(type);
84      }
85  
86      public List<StackObject> getBraceStack() {
87  	return braceStack;
88      }
89  
90      public List<StackObject> getContinueBreakReturnStack() {
91  	return continueBreakReturnStack;
92      }
93  
94      /**
95       * 
96       * @return formatted dump of the DFA Structure's  
97       */
98      public String dump() {
99        StringBuilder stringDump = new StringBuilder() ; 
100       stringDump.append ("Data Flow Analysis Structure:\n");
101       stringDump.append ("    Edge Nodes (ContinueBraceReturn) :");
102       for (StackObject stackObject  : continueBreakReturnStack )
103       {
104 	stringDump.append("\nCBR => ").append(stackObject.toString());
105       }
106       stringDump.append ("\n    Scope Nodes:");
107       for (StackObject stackObject  : braceStack )
108       {
109 	stringDump.append("\nBraces => ").append(stackObject.toString());
110       }
111       return stringDump.toString();
112     }
113 
114 }