DFS: Terminate traversal if node handler returns false
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user