3232 * @author Tim Lange
3333 */
3434public final class ReadOnlyListViewAnalysis {
35+ private static final int MAX_DEPTH = 12 ;
36+
3537 private final LoadingCache <UnitGraph , SimpleLocalUses > graphToUses = IDESolver .DEFAULT_CACHE_BUILDER
3638 .build (new CacheLoader <UnitGraph , SimpleLocalUses >() {
3739 @ Override
@@ -117,7 +119,9 @@ public boolean isReadOnlyIterator(Unit unit) {
117119 return true ;
118120
119121 UnitGraph ug = (UnitGraph ) icfg .getOrCreateUnitGraph (icfg .getMethodOf (unit ));
120- return isReadOnlyIteratorInternal (graphToUses .getUnchecked (ug ), (AssignStmt ) unit );
122+ Set <Unit > seen = new HashSet <>();
123+ seen .add (unit );
124+ return isReadOnlyIteratorInternal (graphToUses .getUnchecked (ug ), (AssignStmt ) unit , seen , 0 );
121125 }
122126
123127 private boolean isSupportedClass (Type type ) {
@@ -129,7 +133,10 @@ private boolean isSupportedClass(Type type) {
129133 return false ;
130134 }
131135
132- private boolean isReadOnlyIteratorInternal (SimpleLocalUses du , AssignStmt assign ) {
136+ private boolean isReadOnlyIteratorInternal (SimpleLocalUses du , AssignStmt assign , Set <Unit > seen , int depth ) {
137+ if (depth > MAX_DEPTH )
138+ // Assume the worst
139+ return false ;
133140 for (UnitValueBoxPair uv : du .getUsesOf (assign )) {
134141 Stmt stmt = (Stmt ) uv .getUnit ();
135142 Value use = uv .getValueBox ().getValue ();
@@ -169,7 +176,7 @@ private boolean isReadOnlyIteratorInternal(SimpleLocalUses du, AssignStmt assign
169176
170177 // All e = it.next() will be caught by the previous case s.t.
171178 // here we should only see assignments or casts
172- if (!isReadOnlyIteratorInternal (du , (AssignStmt ) stmt ))
179+ if (seen . add ( stmt ) && !isReadOnlyIteratorInternal (du , (AssignStmt ) stmt , seen , depth + 1 ))
173180 return false ;
174181 }
175182 }
0 commit comments