-
-
Notifications
You must be signed in to change notification settings - Fork 781
feat(ast): add a dummy node_id field to all visitable AST types.
#5775
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
feat(ast): add a dummy node_id field to all visitable AST types.
#5775
Conversation
Your org has enabled the Graphite merge queue for merging into mainAdd the label “0-merge” to the PR and Graphite will automatically add it to the merge queue when it’s ready to merge. Or use the label “hotfix” to add to the merge queue as a hot fix. You must have a Graphite account and log in to Graphite in order to use the merge queue. Sign up using this link. |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
CodSpeed Performance ReportMerging #5775 will degrade performances by 3.87%Comparing Summary
Benchmarks breakdown
|
Not bad!! |
| let (head, tail) = match &mut input { | ||
| syn::Item::Enum(enum_) => (enum_repr(enum_), assert_generated_derives(&enum_.attrs)), | ||
| syn::Item::Struct(struct_) => { | ||
| // HACK: temperorary measure to speed up the initial implementation of `node_id`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
| // HACK: temperorary measure to speed up the initial implementation of `node_id`. | |
| // HACK: temporary measure to speed up the initial implementation of `node_id`. |
| if let syn::Fields::Named(fields) = &mut struct_.fields { | ||
| fields | ||
| .named | ||
| .insert(0, parse_quote!(pub node_id: ::oxc_syntax::node::NodeId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest we don't make node_id field public. We can make it harder to end up with the same NodeId appearing in AST twice, by making it impossible to set node_id for a node, except when creating a new node via AstBuilder.
(that would also remove the need for #[non_exhaustive])
We'll need to transition all AST node creation to via AstBuilder first, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The field needs to be Cell<NodeId>. Semantic will be setting these fields, and it only has an immutable AST.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're going to need to do #5888 first (or make node_id fields pub initially), so as not to break Rolldown.
| { | ||
| let args = TokenStream2::from(args); | ||
| if args.into_iter().next().is_some_and( | ||
| |tk| matches!(tk, proc_macro2::TokenTree::Ident(id) if id == "visit" ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're missing out some nodes which I think should have IDs. e.g. JSXOpeningFragment and JSXClosingFragment. On the other hand, we're correctly not adding NodeIds for TemplateElementValue, RegExp and EmptyObject.
I think criteria for whether a struct should have a node_id field is whether it has a span field or not. But that may be incorrect too.
Maybe we should indicate to macro/ast tools when a type should not have a NodeId with #[ast(no_id)]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think criteria for whether a struct should have a node_id field is whether it has a span field or not. But that may be incorrect too.
Maybe we should indicate to macro/ast tools when a type should not have a NodeId with #[ast(no_id)]?
Let's get rid of this macro shenanigans, I was going to use it to make the process easier but this seems like a lot of work.
We should write them manually anyway, So let's start with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What a pain! But, yes, I'd forgotten that we'll need to do it manually in the end anyway.
We should also add #[serde(skip)] to all node_id fields.
| #[cfg(feature = "serialize")] | ||
| use serde::{Serialize, Serializer}; | ||
|
|
||
| #[ast] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this get an #[ast] attr? ScopeId, SymbolId and ReferenceId don't have one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should be, Previously they were defined via the define_index_type macro and we couldn't add them to our schema because we don't support macro expansions - other than inherit ones.
Sorry I wasn't aware of this stack of PRs #4468
| type Cloned = BooleanLiteral; | ||
| fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned { | ||
| BooleanLiteral { | ||
| node_id: CloneIn::clone_in(&self.node_id, allocator), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. We'll need to work out what to do with CloneIn. We can leave that question until later, but just flagging that it's something we need to consider.
We can win most of this perf back if we optimize field layouts later on. |
ea1c733 to
e8f8409
Compare

Part of #5689
A few places are creating these nodes without
AstBuilder; For now I've assigned them directly but should be taken care of as part of making typesnon_exhaustive.