DFS: Terminate traversal if node handler returns false

This commit is contained in:
Alexey Sedunov
2014-06-23 19:26:41 +04:00
parent e5ce5b7127
commit 96557e6d3f
4 changed files with 45 additions and 9 deletions
@@ -540,6 +540,38 @@ public class OverridingUtil {
); );
} }
public static boolean traverseOverridenDescriptors(
@NotNull CallableDescriptor originalDescriptor,
@NotNull final Function1<CallableDescriptor, Boolean> handler
) {
return DFS.dfs(
Collections.singletonList(originalDescriptor),
new DFS.Neighbors<CallableDescriptor>() {
@NotNull
@Override
public Iterable<? extends CallableDescriptor> getNeighbors(CallableDescriptor current) {
return current.getOverriddenDescriptors();
}
},
new DFS.AbstractNodeHandler<CallableDescriptor, Boolean>() {
private boolean result = true;
@Override
public boolean beforeChildren(CallableDescriptor current) {
if (!handler.invoke(current)) {
result = false;
}
return result;
}
@Override
public Boolean result() {
return result;
}
}
);
}
public interface DescriptorSink { public interface DescriptorSink {
void addToScope(@NotNull CallableMemberDescriptor fakeOverride); void addToScope(@NotNull CallableMemberDescriptor fakeOverride);
@@ -147,13 +147,15 @@ public class DescriptorSubstitutor {
}, },
new DFS.NodeHandlerWithListResult<JetType, TypeParameterDescriptor>() { new DFS.NodeHandlerWithListResult<JetType, TypeParameterDescriptor>() {
@Override @Override
public void beforeChildren(JetType current) { public boolean beforeChildren(JetType current) {
ClassifierDescriptor declarationDescriptor = current.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor declarationDescriptor = current.getConstructor().getDeclarationDescriptor();
// typeParameters in a list, but it contains very few elements, so it's fine to call contains() on it // typeParameters in a list, but it contains very few elements, so it's fine to call contains() on it
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
if (typeParameters.contains(declarationDescriptor)) { if (typeParameters.contains(declarationDescriptor)) {
result.add((TypeParameterDescriptor) declarationDescriptor); result.add((TypeParameterDescriptor) declarationDescriptor);
} }
return true;
} }
} }
); );
@@ -634,7 +634,7 @@ public class TypeUtils {
}, },
new DFS.NodeHandlerWithListResult<JetType, TypeConstructor>() { new DFS.NodeHandlerWithListResult<JetType, TypeConstructor>() {
@Override @Override
public void beforeChildren(JetType current) { public boolean beforeChildren(JetType current) {
TypeConstructor constructor = current.getConstructor(); TypeConstructor constructor = current.getConstructor();
Set<JetType> instances = constructorToAllInstances.get(constructor); Set<JetType> instances = constructorToAllInstances.get(constructor);
@@ -643,6 +643,8 @@ public class TypeUtils {
constructorToAllInstances.put(constructor, instances); constructorToAllInstances.put(constructor, instances);
} }
instances.add(current); instances.add(current);
return true;
} }
@Override @Override
@@ -68,10 +68,9 @@ public class DFS {
} }
private static <N> void doDfs(@NotNull N current, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, ?> handler) { private static <N> void doDfs(@NotNull N current, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, ?> handler) {
if (!visited.checkAndMarkVisited(current)) { if (!visited.checkAndMarkVisited(current)) return;
return; if (!handler.beforeChildren(current)) return;
}
handler.beforeChildren(current);
for (N neighbor : neighbors.getNeighbors(current)) { for (N neighbor : neighbors.getNeighbors(current)) {
doDfs(neighbor, neighbors, visited, handler); doDfs(neighbor, neighbors, visited, handler);
} }
@@ -79,8 +78,8 @@ public class DFS {
} }
public interface NodeHandler<N, R> { public interface NodeHandler<N, R> {
@KotlinSignature("fun beforeChildren(current: N): Unit") @KotlinSignature("fun beforeChildren(current: N): Boolean")
void beforeChildren(N current); boolean beforeChildren(N current);
@KotlinSignature("fun afterChildren(current: N): Unit") @KotlinSignature("fun afterChildren(current: N): Unit")
void afterChildren(N current); void afterChildren(N current);
@@ -100,7 +99,8 @@ public class DFS {
public static abstract class AbstractNodeHandler<N, R> implements NodeHandler<N, R> { public static abstract class AbstractNodeHandler<N, R> implements NodeHandler<N, R> {
@Override @Override
public void beforeChildren(N current) { public boolean beforeChildren(N current) {
return true;
} }
@Override @Override