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