New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
get Subtree through iteration #270
Comments
Right, |
ah ok. I was hopping I was missing something. Could it be possible to do this: type EnterFunc<T> = (tree: SubTree) => T | false | undefined instead of doing this: type EnterFunc<T> = (type: NodeType, start: number, end: number) => T | false | undefined It will change a bit the method |
Constructing all those objects would make iteration a lot more expensive, so no, not really. |
ok got it. But it could also be possible to create another iteration function that is dedicated to iterate through a Tree by manipulating only the tree node and not other value like the position. With a warning saying this iteration is more expensive than the other one and it should be used cautiously. Another possibility: what about passing the child in the type EnterFunc<T> = (type: NodeType, start: number, end: number, child: Tree | TreeBuffer ) => T | false | undefined Then like that it should be possible to call the constructor of the |
Or even simpler, instead of having a generic |
Just in case if someone would like to do the same things, I implemented the workaround you suggested @marijnh and it works. So here is the code that do that: export function walkThrough(node: Subtree, ...path: (number | string)[]): Subtree | undefined | null {
let i = 0;
// Somehow, the first type is always the given node.
// So we have to manually move forward before considering the given path.
// A way to achieve that is to manually add the given node in the path
path.unshift(node.type.id);
return node.iterate<Subtree | null>({
enter: (type, start) => {
if (type.id === path[i] || type.name === path[i]) {
i++;
if (i >= path.length) {
// We reached the last node. We should return it then.
// First get the first node resolved at the `start` position.
let result: Subtree | null = node.resolve(start, -1);
if (result.type.id === type.id && result.start === start) {
return result;
}
// In case the first node returned is not the one expected,
// then go to the deepest node at the `start` position and walk backward.
// Note: workaround suggested here: https://github.com/codemirror/codemirror.next/issues/270#issuecomment-674855519
result = node.resolve(start, 1);
while (result && result.type.id !== type.id) {
result = result.parent;
}
return result;
}
// continue to loop on this node
return undefined;
}
// go to the next node
return false;
},
});
} Note the comments at the beginning of the method. I think that's a bit weird that the iteration method doesn't iterate over the children. |
I don't understand what you mean by this. Can you elaborate? |
So imagine you have the following tree:
So now I'm starting to iterate at the node
When it will enter for the first time in the method So that's why I'm saying it doesn't iterate at first over the children. It will but after the 2nd occurrence |
@Nexucis If I understand correctly, you are surprised by the tree iteration containing the root node itself before iterating down to the children? To me, this is the expected behavior of any tree iteration, the root node should always be included... or am I missing something? |
yes that's exactly what I mean. It is certainly the standard, it's just a bit surprising when you are using it. Specially when you are not at the root of the tree but in the middle. |
Actually sometimes the workaround described above doesn't work every time. For example, I have the following tree:
that is matching this expression: I'm starting the iteration with the node When it finds the node I don't get what happen :/ and at this point, I have no idea how to resolve it. |
(As a note, I'm working on overhauling the tree iteration interface to be a bit more flexible, using an external iterator (stateful object instead of method that calls a callback). That'll make it a lot easier to get a subtree at a given iteration position.) |
The |
nice ! |
Hi,
When using the method
iterate
on aSubTree
, for some cases I'm not able to get the correspondingSubTree
where the iteration stopped.For example, I have the following tree:
which matched the following expression:
For this example,
FunctionCallBody
,FunctionCallArgs
,Expr
andMetricIdentifier
are started at the same position.I have the following iteration method:
the idea is to give the path to follow thanks to the array
subChildChained
to the iteration method.Then if the last node is found, it returns the associated
Subtree
.Unfortunately, so far I didn't find how to get it. I tried by using
node.resolve
ornode.childBefore
ornode.childAfter
but since I have multiple node started at the same position, I'm not able to get theSubtree
for the nodeMetricIdentifier
but only for the nodeFunctionCallBody
.Is there a way to get exactly the node where I stopped the iteration ?
The text was updated successfully, but these errors were encountered: