001: /*
002: * Created on 11.07.2004
003: */
004: package net.sourceforge.pmd.dfa;
005:
006: import net.sourceforge.pmd.ast.*;
007:
008: /**
009: * @author raik
010: * <p/>
011: * Sublayer of DataFlowFacade. Finds all data flow nodes and stores the
012: * type information (@see StackObject). At last it uses this information to
013: * link the nodes.
014: */
015: public class StatementAndBraceFinder extends JavaParserVisitorAdapter {
016:
017: private Structure dataFlow;
018:
019: public void buildDataFlowFor(SimpleJavaNode node) {
020: if (!(node instanceof ASTMethodDeclaration)
021: && !(node instanceof ASTConstructorDeclaration)) {
022: throw new RuntimeException(
023: "Can't build a data flow for anything other than a method or a constructor");
024: }
025:
026: this .dataFlow = new Structure();
027: this .dataFlow.createStartNode(node.getBeginLine());
028: this .dataFlow.createNewNode(node);
029:
030: node.jjtAccept(this , dataFlow);
031:
032: this .dataFlow.createEndNode(node.getEndLine());
033:
034: Linker linker = new Linker(dataFlow.getBraceStack(), dataFlow
035: .getContinueBreakReturnStack());
036: try {
037: linker.computePaths();
038: } catch (LinkerException e) {
039: e.printStackTrace();
040: } catch (SequenceException e) {
041: e.printStackTrace();
042: }
043: }
044:
045: public Object visit(ASTStatementExpression node, Object data) {
046: if (!(data instanceof Structure)) {
047: return data;
048: }
049: Structure dataFlow = (Structure) data;
050: dataFlow.createNewNode(node);
051: return super .visit(node, data);
052: }
053:
054: public Object visit(ASTVariableDeclarator node, Object data) {
055: if (!(data instanceof Structure)) {
056: return data;
057: }
058: Structure dataFlow = (Structure) data;
059: dataFlow.createNewNode(node);
060: return super .visit(node, data);
061: }
062:
063: public Object visit(ASTExpression node, Object data) {
064: if (!(data instanceof Structure)) {
065: return data;
066: }
067: Structure dataFlow = (Structure) data;
068:
069: // TODO what about throw stmts?
070: if (node.jjtGetParent() instanceof ASTIfStatement) {
071: dataFlow.createNewNode(node); // START IF
072: dataFlow.pushOnStack(NodeType.IF_EXPR, dataFlow.getLast());
073: } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
074: dataFlow.createNewNode(node); // START WHILE
075: dataFlow.pushOnStack(NodeType.WHILE_EXPR, dataFlow
076: .getLast());
077: } else if (node.jjtGetParent() instanceof ASTSwitchStatement) {
078: dataFlow.createNewNode(node); // START SWITCH
079: dataFlow.pushOnStack(NodeType.SWITCH_START, dataFlow
080: .getLast());
081: } else if (node.jjtGetParent() instanceof ASTForStatement) {
082: dataFlow.createNewNode(node); // FOR EXPR
083: dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
084: } else if (node.jjtGetParent() instanceof ASTDoStatement) {
085: dataFlow.createNewNode(node); // DO EXPR
086: dataFlow.pushOnStack(NodeType.DO_EXPR, dataFlow.getLast());
087: }
088:
089: return super .visit(node, data);
090: }
091:
092: public Object visit(ASTForInit node, Object data) {
093: if (!(data instanceof Structure)) {
094: return data;
095: }
096: Structure dataFlow = (Structure) data;
097: super .visit(node, data);
098: dataFlow.pushOnStack(NodeType.FOR_INIT, dataFlow.getLast());
099: this .addForExpressionNode(node, dataFlow);
100: return data;
101: }
102:
103: public Object visit(ASTLabeledStatement node, Object data) {
104: dataFlow.createNewNode(node);
105: dataFlow.pushOnStack(NodeType.LABEL_STATEMENT, dataFlow
106: .getLast());
107: return super .visit(node, data);
108: }
109:
110: public Object visit(ASTForUpdate node, Object data) {
111: if (!(data instanceof Structure)) {
112: return data;
113: }
114: Structure dataFlow = (Structure) data;
115: this .addForExpressionNode(node, dataFlow);
116: super .visit(node, data);
117: dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
118: return data;
119: }
120:
121: // ----------------------------------------------------------------------------
122: // BRANCH OUT
123:
124: public Object visit(ASTStatement node, Object data) {
125: if (!(data instanceof Structure)) {
126: return data;
127: }
128: Structure dataFlow = (Structure) data;
129:
130: if (node.jjtGetParent() instanceof ASTForStatement) {
131: this .addForExpressionNode(node, dataFlow);
132: dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT,
133: dataFlow.getLast());
134: } else if (node.jjtGetParent() instanceof ASTDoStatement) {
135: dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT,
136: dataFlow.getLast());
137: dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
138: }
139:
140: super .visit(node, data);
141:
142: if (node.jjtGetParent() instanceof ASTIfStatement) {
143: ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
144: if (!st.hasElse()) {
145: dataFlow.pushOnStack(
146: NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE,
147: dataFlow.getLast());
148: } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
149: dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT,
150: dataFlow.getLast());
151: } else {
152: dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT,
153: dataFlow.getLast());
154: }
155: } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
156: dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT,
157: dataFlow.getLast());
158: } else if (node.jjtGetParent() instanceof ASTForStatement) {
159: dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
160: } else if (node.jjtGetParent() instanceof ASTLabeledStatement) {
161: dataFlow.pushOnStack(NodeType.LABEL_LAST_STATEMENT,
162: dataFlow.getLast());
163: }
164: return data;
165: }
166:
167: public Object visit(ASTSwitchStatement node, Object data) {
168: if (!(data instanceof Structure)) {
169: return data;
170: }
171: Structure dataFlow = (Structure) data;
172: super .visit(node, data);
173: dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
174: return data;
175: }
176:
177: public Object visit(ASTSwitchLabel node, Object data) {
178: if (!(data instanceof Structure)) {
179: return data;
180: }
181: Structure dataFlow = (Structure) data;
182: //super.visit(node, data);
183: if (node.jjtGetNumChildren() == 0) {
184: dataFlow.pushOnStack(
185: NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow
186: .getLast());
187: } else {
188: dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow
189: .getLast());
190: }
191: return data;
192: }
193:
194: public Object visit(ASTBreakStatement node, Object data) {
195: if (!(data instanceof Structure)) {
196: return data;
197: }
198: Structure dataFlow = (Structure) data;
199: dataFlow.createNewNode(node);
200: dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow
201: .getLast());
202: return super .visit(node, data);
203: }
204:
205: public Object visit(ASTContinueStatement node, Object data) {
206: if (!(data instanceof Structure)) {
207: return data;
208: }
209: Structure dataFlow = (Structure) data;
210: dataFlow.createNewNode(node);
211: dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow
212: .getLast());
213: return super .visit(node, data);
214: }
215:
216: public Object visit(ASTReturnStatement node, Object data) {
217: if (!(data instanceof Structure)) {
218: return data;
219: }
220: Structure dataFlow = (Structure) data;
221: dataFlow.createNewNode(node);
222: dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow
223: .getLast());
224: return super .visit(node, data);
225: }
226:
227: public Object visit(ASTThrowStatement node, Object data) {
228: if (!(data instanceof Structure)) {
229: return data;
230: }
231: Structure dataFlow = (Structure) data;
232: dataFlow.createNewNode(node);
233: dataFlow.pushOnStack(NodeType.THROW_STATEMENT, dataFlow
234: .getLast());
235: return super .visit(node, data);
236: }
237:
238: /*
239: * The method handles the special "for" loop. It creates always an
240: * expression node even if the loop looks like for(;;).
241: * */
242: private void addForExpressionNode(SimpleNode node,
243: Structure dataFlow) {
244: ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
245: boolean hasExpressionChild = false;
246: boolean hasForInitNode = false;
247: boolean hasForUpdateNode = false;
248:
249: for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
250: if (parent.jjtGetChild(i) instanceof ASTExpression)
251: hasExpressionChild = true;
252: else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
253: hasForUpdateNode = true;
254: else if (parent.jjtGetChild(i) instanceof ASTForInit)
255: hasForInitNode = true;
256: }
257: if (!hasExpressionChild) {
258: if (node instanceof ASTForInit) {
259: dataFlow.createNewNode(node);
260: dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow
261: .getLast());
262: } else if (node instanceof ASTForUpdate) {
263: if (!hasForInitNode) {
264: dataFlow.createNewNode(node);
265: dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow
266: .getLast());
267: }
268: } else if (node instanceof ASTStatement) {
269: if (!hasForInitNode && !hasForUpdateNode) {
270: dataFlow.createNewNode(node);
271: dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow
272: .getLast());
273: }
274: }
275: }
276: }
277: }
|