2525import com .google .common .collect .ImmutableSet ;
2626import com .google .common .collect .Iterables ;
2727import com .google .common .collect .Lists ;
28- import com .google .common .collect .Maps ;
2928import org .slf4j .Logger ;
3029import org .slf4j .LoggerFactory ;
3130import org .sonar .java .cfg .CFG ;
5958import org .sonar .plugins .java .api .tree .WhileStatementTree ;
6059
6160import javax .annotation .Nullable ;
61+
6262import java .util .ArrayList ;
6363import java .util .Deque ;
6464import java .util .LinkedList ;
6565import java .util .List ;
66- import java .util .Map ;
6766import java .util .Set ;
6867
6968public class ExplodedGraphWalker extends BaseTreeVisitor {
@@ -176,7 +175,7 @@ private Iterable<ProgramState> startingStates(MethodTree tree, ProgramState ps)
176175 startingStates = Iterables .transform (startingStates , new Function <ProgramState , ProgramState >() {
177176 @ Override
178177 public ProgramState apply (ProgramState input ) {
179- return ProgramState .put (input , variableTree .symbol (), sv );
178+ return input .put (variableTree .symbol (), sv );
180179 }
181180 });
182181
@@ -245,14 +244,14 @@ private void handleBranch(CFG.Block programPosition, Tree condition, boolean che
245244 Pair <List <ProgramState >, List <ProgramState >> pair = constraintManager .assumeDual (programState );
246245 for (ProgramState state : pair .a ) {
247246 // enqueue false-branch, if feasible
248- ProgramState ps = ProgramState .stackValue (state , SymbolicValue .FALSE_LITERAL );
247+ ProgramState ps = state .stackValue (SymbolicValue .FALSE_LITERAL );
249248 enqueue (new ExplodedGraph .ProgramPoint (programPosition .falseBlock (), 0 ), ps );
250249 if (checkPath ) {
251250 alwaysTrueOrFalseChecker .evaluatedToFalse (condition );
252251 }
253252 }
254253 for (ProgramState state : pair .b ) {
255- ProgramState ps = ProgramState .stackValue (state , SymbolicValue .TRUE_LITERAL );
254+ ProgramState ps = state .stackValue (SymbolicValue .TRUE_LITERAL );
256255 // enqueue true-branch, if feasible
257256 enqueue (new ExplodedGraph .ProgramPoint (programPosition .trueBlock (), 0 ), ps );
258257 if (checkPath ) {
@@ -272,9 +271,10 @@ private void visit(Tree tree, @Nullable Tree terminator) {
272271 MethodInvocationTree mit = (MethodInvocationTree ) tree ;
273272 setSymbolicValueOnFields (mit );
274273 // unstack arguments and method identifier
275- programState = ProgramState .unstack (programState , mit .arguments ().size () + 1 ).a ;
274+
275+ programState = programState .unstackValue (mit .arguments ().size () + 1 ).a ;
276276 logState (mit );
277- programState = ProgramState .stackValue (programState , constraintManager .createSymbolicValue (mit ));
277+ programState = programState .stackValue (constraintManager .createSymbolicValue (mit ));
278278 break ;
279279 case LABELED_STATEMENT :
280280 case SWITCH_STATEMENT :
@@ -294,53 +294,59 @@ private void visit(Tree tree, @Nullable Tree terminator) {
294294 sv = SymbolicValue .NULL_LITERAL ;
295295 }
296296 if (sv != null ) {
297- programState = ProgramState .put (programState , variableTree .symbol (), sv );
297+ programState = programState .put (variableTree .symbol (), sv );
298298 }
299299 } else {
300- Pair <ProgramState , List <SymbolicValue >> unstack = ProgramState .unstack (programState , 1 );
300+
301+ Pair <ProgramState , List <SymbolicValue >> unstack = programState .unstackValue (1 );
301302 programState = unstack .a ;
302- programState = ProgramState .put (programState , variableTree .symbol (), unstack .b .get (0 ));
303+ programState = programState .put (variableTree .symbol (), unstack .b .get (0 ));
303304 }
304305 break ;
305306 case TYPE_CAST :
306307 TypeCastTree typeCast = (TypeCastTree ) tree ;
307308 Type type = typeCast .type ().symbolType ();
308309 if (type .isPrimitive ()) {
309- Pair <ProgramState , List <SymbolicValue >> unstack = ProgramState .unstack (programState , 1 );
310+
311+ Pair <ProgramState , List <SymbolicValue >> unstack = programState .unstackValue (1 );
310312 programState = unstack .a ;
311- programState = ProgramState .stackValue (programState , constraintManager .createSymbolicValue (typeCast .expression ()));
313+ programState = programState .stackValue (constraintManager .createSymbolicValue (typeCast .expression ()));
312314 }
313315 break ;
314316 case ASSIGNMENT :
315317 ExpressionTree variable = ((AssignmentExpressionTree ) tree ).variable ();
316318 if (variable .is (Tree .Kind .IDENTIFIER )) {
317319 // FIXME restricted to identifiers for now.
318- Pair <ProgramState , List <SymbolicValue >> unstack = ProgramState .unstack (programState , 2 );
320+
321+ Pair <ProgramState , List <SymbolicValue >> unstack = programState .unstackValue (2 );
319322 SymbolicValue value = unstack .b .get (1 );
320323 programState = unstack .a ;
321- programState = ProgramState .put (programState , ((IdentifierTree ) variable ).symbol (), value );
322- programState = ProgramState .stackValue (programState , value );
324+ programState = programState .put (((IdentifierTree ) variable ).symbol (), value );
325+ programState = programState .stackValue (value );
323326 }
324327 break ;
325328 case ARRAY_ACCESS_EXPRESSION :
326329 ArrayAccessExpressionTree arrayAccessExpressionTree = (ArrayAccessExpressionTree ) tree ;
327330 // unstack expression and dimension
328- Pair <ProgramState , List <SymbolicValue >> unstack = ProgramState .unstack (programState , 2 );
331+
332+ Pair <ProgramState , List <SymbolicValue >> unstack = programState .unstackValue (2 );
329333 programState = unstack .a ;
330- programState = ProgramState .stackValue (programState , constraintManager .createSymbolicValue (arrayAccessExpressionTree ));
334+ programState = programState .stackValue (constraintManager .createSymbolicValue (arrayAccessExpressionTree ));
331335 break ;
332336 case NEW_ARRAY :
333337 NewArrayTree newArrayTree = (NewArrayTree ) tree ;
334- programState = ProgramState .unstack (programState , newArrayTree .initializers ().size ()).a ;
338+
339+ programState = programState .unstackValue (newArrayTree .initializers ().size ()).a ;
335340 SymbolicValue svNewArray = constraintManager .createSymbolicValue (newArrayTree );
336- programState = ProgramState .stackValue (programState , svNewArray );
341+ programState = programState .stackValue (svNewArray );
337342 programState = svNewArray .setSingleConstraint (programState , NullConstraint .NOT_NULL );
338343 break ;
339344 case NEW_CLASS :
340345 NewClassTree newClassTree = (NewClassTree ) tree ;
341- programState = ProgramState .unstack (programState , newClassTree .arguments ().size ()).a ;
346+
347+ programState = programState .unstackValue (newClassTree .arguments ().size ()).a ;
342348 SymbolicValue svNewClass = constraintManager .createSymbolicValue (newClassTree );
343- programState = ProgramState .stackValue (programState , svNewClass );
349+ programState = programState .stackValue (svNewClass );
344350 programState = svNewClass .setSingleConstraint (programState , NullConstraint .NOT_NULL );
345351 break ;
346352 case MULTIPLY :
@@ -361,11 +367,12 @@ private void visit(Tree tree, @Nullable Tree terminator) {
361367 case EQUAL_TO :
362368 case NOT_EQUAL_TO :
363369 // Consume two and produce one SV.
364- Pair <ProgramState , List <SymbolicValue >> unstackBinary = ProgramState .unstack (programState , 2 );
370+
371+ Pair <ProgramState , List <SymbolicValue >> unstackBinary = programState .unstackValue (2 );
365372 programState = unstackBinary .a ;
366373 SymbolicValue symbolicValue = constraintManager .createSymbolicValue (tree );
367374 symbolicValue .computedFrom (unstackBinary .b );
368- programState = ProgramState .stackValue (programState , symbolicValue );
375+ programState = programState .stackValue (symbolicValue );
369376 break ;
370377 case POSTFIX_INCREMENT :
371378 case POSTFIX_DECREMENT :
@@ -377,29 +384,31 @@ private void visit(Tree tree, @Nullable Tree terminator) {
377384 case LOGICAL_COMPLEMENT :
378385 case INSTANCE_OF :
379386 // consume one and produce one
380- Pair <ProgramState , List <SymbolicValue >> unstackUnary = ProgramState .unstack (programState , 1 );
387+
388+ Pair <ProgramState , List <SymbolicValue >> unstackUnary = programState .unstackValue (1 );
381389 programState = unstackUnary .a ;
382390 SymbolicValue unarySymbolicValue = constraintManager .createSymbolicValue (tree );
383391 unarySymbolicValue .computedFrom (unstackUnary .b );
384- programState = ProgramState .stackValue (programState , unarySymbolicValue );
392+ programState = programState .stackValue (unarySymbolicValue );
385393 break ;
386394 case IDENTIFIER :
387395 Symbol symbol = ((IdentifierTree ) tree ).symbol ();
388- SymbolicValue value = programState .values . get (symbol );
396+ SymbolicValue value = programState .getValue (symbol );
389397 if (value == null ) {
390398 value = constraintManager .createSymbolicValue (tree );
391- programState = ProgramState .put (programState , symbol , value );
399+ programState = programState .put (symbol , value );
392400 }
393- programState = ProgramState .stackValue (programState , value );
401+ programState = programState .stackValue (value );
394402 break ;
395403 case MEMBER_SELECT :
396404 MemberSelectExpressionTree mse = (MemberSelectExpressionTree ) tree ;
397405 if (!"class" .equals (mse .identifier ().name ())) {
398- Pair <ProgramState , List <SymbolicValue >> unstackMSE = ProgramState .unstack (programState , 1 );
406+
407+ Pair <ProgramState , List <SymbolicValue >> unstackMSE = programState .unstackValue (1 );
399408 programState = unstackMSE .a ;
400409 }
401410 SymbolicValue mseValue = constraintManager .createSymbolicValue (tree );
402- programState = ProgramState .stackValue (programState , mseValue );
411+ programState = programState .stackValue (mseValue );
403412 break ;
404413 case INT_LITERAL :
405414 case LONG_LITERAL :
@@ -410,11 +419,11 @@ private void visit(Tree tree, @Nullable Tree terminator) {
410419 case STRING_LITERAL :
411420 case NULL_LITERAL :
412421 SymbolicValue val = constraintManager .evalLiteral ((LiteralTree ) tree );
413- programState = ProgramState .stackValue (programState , val );
422+ programState = programState .stackValue (val );
414423 break ;
415424 case LAMBDA_EXPRESSION :
416425 case METHOD_REFERENCE :
417- programState = ProgramState .stackValue (programState , constraintManager .createSymbolicValue (tree ));
426+ programState = programState .stackValue (constraintManager .createSymbolicValue (tree ));
418427 break ;
419428 default :
420429 }
@@ -425,7 +434,7 @@ private void visit(Tree tree, @Nullable Tree terminator) {
425434
426435 public void clearStack (Tree tree ) {
427436 if (tree .parent ().is (Tree .Kind .EXPRESSION_STATEMENT )) {
428- programState = ProgramState . unstack ( programState , programState . stack . size ()). a ;
437+ programState = programState . clearStack () ;
429438 }
430439 }
431440
@@ -451,26 +460,7 @@ private static boolean isLocalMethodInvocation(MethodInvocationTree tree) {
451460 }
452461
453462 private void resetFieldValues () {
454- boolean changed = false ;
455- Map <Symbol , SymbolicValue > values = Maps .newHashMap (programState .values );
456- for (Map .Entry <Symbol , SymbolicValue > entry : values .entrySet ()) {
457- Symbol symbol = entry .getKey ();
458- if (isField (symbol )) {
459- VariableTree variable = ((Symbol .VariableSymbol ) symbol ).declaration ();
460- if (variable != null ) {
461- changed = true ;
462- SymbolicValue nonNullValue = constraintManager .supersedeSymbolicValue (variable );
463- values .put (symbol , nonNullValue );
464- }
465- }
466- }
467- if (changed ) {
468- programState = new ProgramState (values , programState .constraints , programState .visitedPoints , programState .stack );
469- }
470- }
471-
472- private static boolean isField (Symbol symbol ) {
473- return symbol .isVariableSymbol () && !symbol .owner ().isMethodSymbol ();
463+ programState = programState .resetFieldValues (constraintManager );
474464 }
475465
476466 private void logState (MethodInvocationTree mit ) {
@@ -495,8 +485,7 @@ public void enqueue(ExplodedGraph.ProgramPoint programPoint, ProgramState progra
495485 throw new ExplodedGraphTooBigException ("Program state constraints are too big : stopping Symbolic Execution for method "
496486 + methodTree .simpleName ().name () + "in class " + methodTree .symbol ().owner ().name ());
497487 }
498- ExplodedGraph .Node cachedNode = explodedGraph .getNode (programPoint ,
499- new ProgramState (programState .values , programState .constraints , programState .visitedPoints .put (programPoint , nbOfExecution +1 ), programState .stack ));
488+ ExplodedGraph .Node cachedNode = explodedGraph .getNode (programPoint , programState .visitingPoint (programPoint ));
500489 if (!cachedNode .isNew ) {
501490 // has been enqueued earlier
502491 return ;
@@ -506,7 +495,7 @@ public void enqueue(ExplodedGraph.ProgramPoint programPoint, ProgramState progra
506495
507496 private boolean isExplodedGraphTooBig (ProgramState programState ) {
508497 // Arbitrary formula to avoid out of memory errors.
509- return steps + workList .size () > MAX_STEPS / 2 && programState .constraints . size () > 75 ;
498+ return steps + workList .size () > MAX_STEPS / 2 && programState .constraintsSize () > 75 ;
510499 }
511500
512501}
0 commit comments