-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(typescript-estree): lazily compute loc #6542
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
Conversation
☁️ Nx Cloud ReportWe didn't find any information for the current pull request with the commit a79b7c6. Check the Nx Cloud Github Integration documentation for more information. Sent with 💌 from NxCloud. |
Thanks for the PR, @bradzacher! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
wdyt about changing that entire loc is a getter? that should save some time on declaring so many getters, we could make it, I don't think we have to worry about setter you also forgot to remove other calls to export function defineLocProperty<T extends { range?: [number, number] }>(
ast: ts.SourceFile,
node: T,
): T & { loc: TSESTree.SourceLocation } {
Object.defineProperty(node, 'loc', {
get(this: { range: [number, number] }) {
return {
start: getLineAndCharacterFor(this.range[0], ast),
end: getLineAndCharacterFor(this.range[1], ast),
};
},
});
return node as T & { loc: TSESTree.SourceLocation };
} |
@armano2 I actually went down that route first before moving down one layer. I think that
We do need a setter, sadly, as there's a few places during the conversion that we change the default location for a node (for example when separating out |
we actually don't need a setter for our uses, we can rely on example
|
Sorry, yes, what I meant is that we need a setter for the lower-level approach this PR currently represents. For a higher-level approach we can remove the setter. My first attempt (not captured in a commit) was using
I thought about maybe spreading objects to instead use the syntax, but this ofc incurs the cost of spreading - which won't be great at scale. I thought about declaring a few base classes for all our nodes like TS does so that we can have a getter declared on the prototype (i.e. declared exactly once) - and that may be a viable option! I just did not explore it yet as it's quite a large change. |
PR Checklist
Overview
This PR changes our AST conversion to lazily compute the
.loc
for all nodes, comments, and tokens.TS does not compute node location during the parsing sequence. This means that in order to calculate the location, we need to ask TS to convert the range to a location - which involves doing a binary search of the line:range mapping.
Ideally TS would calculate and store these as it goes - but understandably they don't because TS doesn't need the information for the most part!
Perf Result
This change reduces time spent in
getLineAndCharacterFor
in our codebase from 231ms to 68ms, however the time spent inastConverter
was mostly a neutral change - suggesting that just declaring the getters and setters cost the same as the time saved.I'm really surprised that accessors are so expensive to define. Really sad that this is a dead end. I'm putting this up and closing it immediately just so there's a clear log of things for people to see.
Here are the cpu profiles for the change:
Archive.zip