1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 45203. Improved loop detection.

This commit is contained in:
Sergey Prigogin 2013-03-30 17:41:54 -07:00
parent a4ebf6ffa5
commit 163df7dbad
2 changed files with 24 additions and 19 deletions

View file

@ -32,9 +32,9 @@ public class IncludeMapTest extends TestCase {
}); });
map.transitivelyClose(); map.transitivelyClose();
IncludeMap expected = new IncludeMap(false, false, new String[] { IncludeMap expected = new IncludeMap(false, false, new String[] {
"a", "c",
"a", "b", "a", "b",
"a", "d", "a", "d",
"a", "c",
"b", "d", "b", "d",
"b", "c", "b", "c",
"c", "d", "c", "d",
@ -54,7 +54,7 @@ public class IncludeMapTest extends TestCase {
}); });
map.transitivelyClose(); map.transitivelyClose();
IncludeMap expected = new IncludeMap(true, false, new String[] { IncludeMap expected = new IncludeMap(true, false, new String[] {
"a", "c", "a", "b",
"c", "b", "c", "b",
"d", "b", "d", "b",
}); });

View file

@ -25,6 +25,9 @@ import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento; import org.eclipse.ui.XMLMemento;
/**
* A set of header file substitution rules.
*/
public class IncludeMap { public class IncludeMap {
private static final String TAG_CPP_ONLY = "cpp_only"; //$NON-NLS-1$ private static final String TAG_CPP_ONLY = "cpp_only"; //$NON-NLS-1$
private static final String TAG_FORCED_REPLACEMENT = "forced_replacement"; //$NON-NLS-1$ private static final String TAG_FORCED_REPLACEMENT = "forced_replacement"; //$NON-NLS-1$
@ -195,43 +198,45 @@ public class IncludeMap {
List<IncludeInfo> targets = entry.getValue(); List<IncludeInfo> targets = entry.getValue();
ArrayDeque<IncludeInfo> queue = new ArrayDeque<IncludeInfo>(targets); ArrayDeque<IncludeInfo> queue = new ArrayDeque<IncludeInfo>(targets);
targets.clear(); targets.clear();
HashSet<IncludeInfo> seen = new HashSet<IncludeInfo>(); HashSet<IncludeInfo> processed = new HashSet<IncludeInfo>();
if (!forcedReplacement) if (!forcedReplacement)
seen.add(source); // Don't allow mapping to itself. processed.add(source); // Don't allow mapping to itself.
int iterationsWithoutProgress = 0; HashSet<IncludeInfo> seenTargets = new HashSet<IncludeInfo>();
IncludeInfo target; IncludeInfo target;
queueLoop: while ((target = queue.pollFirst()) != null) { queueLoop: while ((target = queue.pollFirst()) != null) {
if (seen.contains(target)) if (processed.contains(target))
continue; continue;
List<IncludeInfo> newTargets = map.get(target); List<IncludeInfo> newTargets = map.get(target);
if (newTargets != null) { if (newTargets != null) {
queue.addFirst(target); queue.addFirst(target);
boolean added = false; boolean added = false;
for (int i = newTargets.size(); --i >=0;) { // Check if we saw the same target earlier to protect against an infinite loop.
IncludeInfo newTarget = newTargets.get(i); if (seenTargets.add(target)) {
if (!seen.contains(newTarget)) { for (int i = newTargets.size(); --i >=0;) {
if (forcedReplacement && newTarget.equals(source)) { IncludeInfo newTarget = newTargets.get(i);
break queueLoop; // Leave the mapping empty. 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) {
if (!added || ++iterationsWithoutProgress >= map.size()) {
target = queue.pollFirst(); target = queue.pollFirst();
targets.add(target); targets.add(target);
if (forcedReplacement) if (forcedReplacement)
break; break;
seen.add(target); processed.add(target);
iterationsWithoutProgress = 0; seenTargets.clear();
} }
} else { } else {
targets.add(target); targets.add(target);
if (forcedReplacement) if (forcedReplacement)
break; break;
seen.add(target); processed.add(target);
iterationsWithoutProgress = 0; seenTargets.clear();
} }
} }
} }