1 14 package org.eclipse.jdt.internal.corext.refactoring.code.flow; 15 16 import org.eclipse.core.runtime.Assert; 17 18 import org.eclipse.jface.text.IRegion; 19 20 import org.eclipse.jdt.core.dom.ASTNode; 21 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 22 import org.eclipse.jdt.core.dom.BodyDeclaration; 23 import org.eclipse.jdt.core.dom.ConditionalExpression; 24 import org.eclipse.jdt.core.dom.DoStatement; 25 import org.eclipse.jdt.core.dom.EnhancedForStatement; 26 import org.eclipse.jdt.core.dom.Expression; 27 import org.eclipse.jdt.core.dom.ForStatement; 28 import org.eclipse.jdt.core.dom.IfStatement; 29 import org.eclipse.jdt.core.dom.ReturnStatement; 30 import org.eclipse.jdt.core.dom.Statement; 31 import org.eclipse.jdt.core.dom.SwitchStatement; 32 import org.eclipse.jdt.core.dom.WhileStatement; 33 34 import org.eclipse.jdt.internal.corext.dom.Selection; 35 36 public class InputFlowAnalyzer extends FlowAnalyzer { 37 38 private static class LoopReentranceVisitor extends FlowAnalyzer { 39 private Selection fSelection; 40 private ASTNode fLoopNode; 41 public LoopReentranceVisitor(FlowContext context, Selection selection, ASTNode loopNode) { 42 super(context); 43 fSelection= selection; 44 fLoopNode= loopNode; 45 } 46 protected boolean traverseNode(ASTNode node) { 47 return true; } 49 protected boolean createReturnFlowInfo(ReturnStatement node) { 50 return node.getStartPosition() + node.getLength() <= fSelection.getExclusiveEnd(); 52 } 53 protected ASTNode getLoopNode() { 54 return fLoopNode; 55 } 56 public void process(ASTNode node) { 57 try { 58 fFlowContext.setLoopReentranceMode(true); 59 node.accept(this); 60 } finally { 61 fFlowContext.setLoopReentranceMode(false); 62 } 63 } 64 public void endVisit(DoStatement node) { 65 if (skipNode(node)) 66 return; 67 DoWhileFlowInfo info= createDoWhile(); 68 setFlowInfo(node, info); 69 info.mergeAction(getFlowInfo(node.getBody()), fFlowContext); 70 info.removeLabel(null); 72 } 73 public void endVisit(EnhancedForStatement node) { 74 if (skipNode(node)) 75 return; 76 FlowInfo paramInfo= getFlowInfo(node.getParameter()); 77 FlowInfo expressionInfo= getFlowInfo(node.getExpression()); 78 FlowInfo actionInfo= getFlowInfo(node.getBody()); 79 EnhancedForFlowInfo forInfo= createEnhancedFor(); 80 setFlowInfo(node, forInfo); 81 if (node == fLoopNode) { 84 forInfo.mergeAction(actionInfo, fFlowContext); 85 } else { 86 forInfo.mergeExpression(expressionInfo, fFlowContext); 89 forInfo.mergeParameter(paramInfo, fFlowContext); 90 forInfo.mergeAction(actionInfo, fFlowContext); 91 } 92 forInfo.removeLabel(null); 93 } 94 public void endVisit(ForStatement node) { 95 if (skipNode(node)) 96 return; 97 FlowInfo initInfo= createSequential(node.initializers()); 98 FlowInfo conditionInfo= getFlowInfo(node.getExpression()); 99 FlowInfo incrementInfo= createSequential(node.updaters()); 100 FlowInfo actionInfo= getFlowInfo(node.getBody()); 101 ForFlowInfo forInfo= createFor(); 102 setFlowInfo(node, forInfo); 103 if (node == fLoopNode) { 106 forInfo.mergeIncrement(incrementInfo, fFlowContext); 107 forInfo.mergeCondition(conditionInfo, fFlowContext); 108 forInfo.mergeAction(actionInfo, fFlowContext); 109 } else { 110 GenericConditionalFlowInfo initIncr= new GenericConditionalFlowInfo(); 117 initIncr.merge(initInfo, fFlowContext); 118 initIncr.merge(incrementInfo, fFlowContext); 119 forInfo.mergeAccessModeSequential(initIncr, fFlowContext); 120 forInfo.mergeCondition(conditionInfo, fFlowContext); 121 forInfo.mergeAction(actionInfo, fFlowContext); 122 } 123 forInfo.removeLabel(null); 124 } 125 } 126 127 private Selection fSelection; 128 private boolean fDoLoopReentrance; 129 private LoopReentranceVisitor fLoopReentranceVisitor; 130 131 public InputFlowAnalyzer(FlowContext context, Selection selection, boolean doLoopReentrance) { 132 super(context); 133 fSelection= selection; 134 Assert.isNotNull(fSelection); 135 fDoLoopReentrance= doLoopReentrance; 136 } 137 138 public FlowInfo perform(BodyDeclaration node) { 139 Assert.isTrue(!(node instanceof AbstractTypeDeclaration)); 140 node.accept(this); 141 return getFlowInfo(node); 142 } 143 144 protected boolean traverseNode(ASTNode node) { 145 return node.getStartPosition() + node.getLength() > fSelection.getInclusiveEnd(); 146 } 147 148 protected boolean createReturnFlowInfo(ReturnStatement node) { 149 return node.getStartPosition() >= fSelection.getInclusiveEnd(); 152 } 153 154 public boolean visit(DoStatement node) { 155 createLoopReentranceVisitor(node); 156 return super.visit(node); 157 } 158 159 public boolean visit(EnhancedForStatement node) { 160 createLoopReentranceVisitor(node); 161 return super.visit(node); 162 } 163 164 public boolean visit(ForStatement node) { 165 createLoopReentranceVisitor(node); 166 return super.visit(node); 167 } 168 169 public boolean visit(WhileStatement node) { 170 createLoopReentranceVisitor(node); 171 return super.visit(node); 172 } 173 174 private void createLoopReentranceVisitor(ASTNode node) { 175 if (fLoopReentranceVisitor == null && fDoLoopReentrance) 176 fLoopReentranceVisitor= new LoopReentranceVisitor(fFlowContext, fSelection, node); 177 } 178 179 public void endVisit(ConditionalExpression node) { 180 if (skipNode(node)) 181 return; 182 Expression thenPart= node.getThenExpression(); 183 Expression elsePart= node.getElseExpression(); 184 if ((thenPart != null && fSelection.coveredBy(thenPart)) || 185 (elsePart != null && fSelection.coveredBy(elsePart))) { 186 GenericSequentialFlowInfo info= createSequential(); 187 setFlowInfo(node, info); 188 endVisitConditional(info, node.getExpression(), new ASTNode[] {thenPart, elsePart}); 189 } else { 190 super.endVisit(node); 191 } 192 } 193 194 public void endVisit(DoStatement node) { 195 super.endVisit(node); 196 handleLoopReentrance(node); 197 } 198 199 public void endVisit(IfStatement node) { 200 if (skipNode(node)) 201 return; 202 Statement thenPart= node.getThenStatement(); 203 Statement elsePart= node.getElseStatement(); 204 if ((thenPart != null && fSelection.coveredBy(thenPart)) || 205 (elsePart != null && fSelection.coveredBy(elsePart))) { 206 GenericSequentialFlowInfo info= createSequential(); 207 setFlowInfo(node, info); 208 endVisitConditional(info, node.getExpression(), new ASTNode[] {thenPart, elsePart}); 209 } else { 210 super.endVisit(node); 211 } 212 } 213 214 public void endVisit(EnhancedForStatement node) { 215 super.endVisit(node); 216 handleLoopReentrance(node); 217 } 218 219 public void endVisit(ForStatement node) { 220 super.endVisit(node); 221 handleLoopReentrance(node); 222 } 223 224 public void endVisit(SwitchStatement node) { 225 if (skipNode(node)) 226 return; 227 SwitchData data= createSwitchData(node); 228 IRegion[] ranges= data.getRanges(); 229 for (int i= 0; i < ranges.length; i++) { 230 IRegion range= ranges[i]; 231 if (fSelection.coveredBy(range)) { 232 GenericSequentialFlowInfo info= createSequential(); 233 setFlowInfo(node, info); 234 info.merge(getFlowInfo(node.getExpression()), fFlowContext); 235 info.merge(data.getInfo(i), fFlowContext); 236 info.removeLabel(null); 237 return; 238 } 239 } 240 super.endVisit(node, data); 241 } 242 243 public void endVisit(WhileStatement node) { 244 super.endVisit(node); 245 handleLoopReentrance(node); 246 } 247 248 private void endVisitConditional(GenericSequentialFlowInfo info, ASTNode condition, ASTNode[] branches) { 249 info.merge(getFlowInfo(condition), fFlowContext); 250 for (int i= 0; i < branches.length; i++) { 251 ASTNode branch= branches[i]; 252 if (branch != null && fSelection.coveredBy(branch)) { 253 info.merge(getFlowInfo(branch), fFlowContext); 254 break; 255 } 256 } 257 } 258 259 private void handleLoopReentrance(ASTNode node) { 260 if (!fSelection.coveredBy(node) || fLoopReentranceVisitor == null || fLoopReentranceVisitor.getLoopNode() != node) 261 return; 262 263 fLoopReentranceVisitor.process(node); 264 GenericSequentialFlowInfo info= createSequential(); 265 info.merge(getFlowInfo(node), fFlowContext); 266 info.merge(fLoopReentranceVisitor.getFlowInfo(node), fFlowContext); 267 setFlowInfo(node, info); 268 } 269 } 270 | Popular Tags |