:nth-child, :first-child, etc selecting multiple nodes while used with direct children
In the code:
interface I<T=any>{
m(i: number, g: (aParameter1: number)=>void)
}
I expect that InterfaceDeclaration > :nth-child(1) to match only one node (since any node cannot have more than one child that is the first one) but is matching 3 nodes. The same happens with all :first-child, :last-child, etc.
Another example, in the code:
function f(){
var a = 1
function g(){var a=1}
}
This selector SourceFile>FunctionDeclaration:has([name="f"])>Block>*>*>*>*>VariableDeclaration matches only one child as expected, but this one (just replace VariableDeclaration with :first-child) matches 2 nodes.
It's like whenever you use :first-child or cia, the previous '>' (direct child ) is not taking in account and replaced by " " (ancestor)
I would like to know if this is the expected behavior and if not if you would accept a PR for this (supposing is simple to fix) ?
Thanks, keep it up!
I think this is intended behaviour, but I'm not super sure on that.
If we look at your InterfaceDeclaration example, which child would you expect to select?
It could have an array of decorators, members, typeParameters, etc., etc.
Those are easily clarified by saying InterfaceDeclaration > TypeParameter:first-child (for example).
What do you think it should do? One alternative could be to order them by string position, and then select the first?
which child would you expect to select?
Depending on which method the library use to obtain children, I would expect InterfaceKeyword (if it uses node.getChildren) or the Identifier I (if it uses ts.forEachChild). I think it uses node.getChildren() right ?
But always, I would expect 0 or 1 matches because a Node can only have 0 or 1 "first direct children".
Also I think InterfaceDeclaration > TypeParameter:first-child should not match anything because TypeParameter is not the first direct children of InterfaceDeclaration. Or am I missing something regarding :first-child semantics ?
In an analogy, in this document document.querySelectorAll('body>:first-child') returns only one element that's the first direct child of body. Contrarily, document.querySelectorAll('body :first-child') will return a lot.
What do you think it should do?
If you use node.getChildren() to extract children, just return the first match in the array, or node.. For example previousMatchedNode.getChildren()[0]. Just make sure it doesn't return more than once. Also if you are merging children SyntaxList with the node's children, make sure those don't take precedence over the "real" children. I guess...
One alternative could be to order them by string position, and then select the first?
That should work.
Sorry I didn't have the time to take a look at the implementation. Will try to make some time to investigate. Thanks, keep it up!