From 163df7dbadf3c177d8e8194625d32b6de22a28d2 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sat, 30 Mar 2013 17:41:54 -0700 Subject: [PATCH] Bug 45203. Improved loop detection. --- .../refactoring/includes/IncludeMapTest.java | 4 +- .../ui/refactoring/includes/IncludeMap.java | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/IncludeMapTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/IncludeMapTest.java index 9a37c6bc8f1..c58fec48aac 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/IncludeMapTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/includes/IncludeMapTest.java @@ -32,9 +32,9 @@ public class IncludeMapTest extends TestCase { }); map.transitivelyClose(); IncludeMap expected = new IncludeMap(false, false, new String[] { - "a", "c", "a", "b", "a", "d", + "a", "c", "b", "d", "b", "c", "c", "d", @@ -54,7 +54,7 @@ public class IncludeMapTest extends TestCase { }); map.transitivelyClose(); IncludeMap expected = new IncludeMap(true, false, new String[] { - "a", "c", + "a", "b", "c", "b", "d", "b", }); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeMap.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeMap.java index 9587a99b4cb..9acb3a56c40 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeMap.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeMap.java @@ -25,6 +25,9 @@ import org.eclipse.ui.IMemento; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.XMLMemento; +/** + * A set of header file substitution rules. + */ public class IncludeMap { private static final String TAG_CPP_ONLY = "cpp_only"; //$NON-NLS-1$ private static final String TAG_FORCED_REPLACEMENT = "forced_replacement"; //$NON-NLS-1$ @@ -195,43 +198,45 @@ public class IncludeMap { List targets = entry.getValue(); ArrayDeque queue = new ArrayDeque(targets); targets.clear(); - HashSet seen = new HashSet(); + HashSet processed = new HashSet(); if (!forcedReplacement) - seen.add(source); // Don't allow mapping to itself. - int iterationsWithoutProgress = 0; + processed.add(source); // Don't allow mapping to itself. + HashSet seenTargets = new HashSet(); IncludeInfo target; queueLoop: while ((target = queue.pollFirst()) != null) { - if (seen.contains(target)) + if (processed.contains(target)) continue; List newTargets = map.get(target); if (newTargets != null) { queue.addFirst(target); boolean added = false; - for (int i = newTargets.size(); --i >=0;) { - IncludeInfo newTarget = newTargets.get(i); - if (!seen.contains(newTarget)) { - if (forcedReplacement && newTarget.equals(source)) { - break queueLoop; // Leave the mapping empty. + // Check if we saw the same target earlier to protect against an infinite loop. + if (seenTargets.add(target)) { + for (int i = newTargets.size(); --i >=0;) { + IncludeInfo newTarget = newTargets.get(i); + if (!processed.contains(newTarget)) { + if (forcedReplacement && newTarget.equals(source)) { + break queueLoop; // Leave the mapping empty. + } + queue.addFirst(newTarget); + added = true; } - queue.addFirst(newTarget); - added = true; } } - // The second condition protects against an infinite loop. - if (!added || ++iterationsWithoutProgress >= map.size()) { + if (!added) { target = queue.pollFirst(); targets.add(target); if (forcedReplacement) break; - seen.add(target); - iterationsWithoutProgress = 0; + processed.add(target); + seenTargets.clear(); } } else { targets.add(target); if (forcedReplacement) break; - seen.add(target); - iterationsWithoutProgress = 0; + processed.add(target); + seenTargets.clear(); } } }