-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Fix binary search in findNodeByOffset
to match linear search result
#8143
Conversation
This comment has been minimized.
This comment has been minimized.
I have a few questions about the contracts on parse nodes:
Additionally, I have a question about the contracts on When a position is adjacent to two nodes (the end position of the previous node is equal to the start position of the current node), which node does It seems like we need to understand some of the contracts on the parse tree/node structure before deciding how to fix the current issue. |
Sorry for the slow response, just noticed this PR. @heejaechang, to answer your questions, search for |
It returns the "previous node" because it always prefers the first sibling that overlaps (as in |
@erictraut, could you review this PR? As I mentioned in the PR description, I'm happy to remove the tests if you don't think they're worthwhile, or rework them if you see a better approach. |
This change shouldn't affect core type checking; it's used only by language server code. If you've confirmed that it's working with the existing LS providers, then I'm fine with it. |
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Address microsoft/pylance-release#5775
Fixes several issues related to the binary search optimization in
findNodeByOffset
:findNodeByOffset
andgetIndexContaining
had different rules about when an offset is within aParseNode
.findNodeByOffset
usesTextRange.overlaps
(includes end offset), whereasgetIndexContaining
usesTextRange.contains
(excludes end offset). Given that that was apparently an intentional difference and has been that way for almost 5 years, I'm not interested in changing it. Fixed by allowing callers to provide a matching algorithm as an optional parameter ongetIndexContaining
.findNonNullElement
was incrementing/decrementing an array index, but it didn't actually use that index for anything -- it always used theposition
that was passed in. So ifarr[position]
wasundefined
,findNonNullElement
would always returnundefined
.findNonNullElement
, if the resulting element was a match (contains the offset), we would always returnmid
, but ifarr[mid]
isundefined
, that's the wrong index to return -- we should return the index of the element thatfindNonNullElement
found.I'm torn on the usefullness of the tests and would be fine removing them if you'd prefer, or to change how they work if you have better ideas. We clearly have poor test coverage on this code, but I worry that future changes to the parser could cause these tests to no longer test what they're supposed to be testing (esp. "findNodeByOffset with binary search choose earliest match"). A change to the number of nodes generated would change the binary search's path through the nodes.