-
Notifications
You must be signed in to change notification settings - Fork 440
Model Syntax nodes as structs #155
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
\cc @allevato |
97a0cdf
to
672d4ef
Compare
672d4ef
to
6184faf
Compare
@swift-ci Please test |
Build failed |
a6390cb
to
6f03210
Compare
@swift-ci Please test |
Build failed |
Avoid the overhead of existentials by modelling the entire syntax node hierarchy using structs with custom casting functions. This results in a major performance gain for SyntaxRewriter.
Improve the performance of SyntaxRewriter by avoiding unnecessary casts, reusing the SyntaxBox and eliminating .enumerated()
Refactor the implementation to match SyntaxRewriter, thereby gaining the same performance benefits.
6f03210
to
5a654ca
Compare
Otherwise it requires a lot of boilerplate to return the Syntax node's type in the lit-test-helper.
5a654ca
to
4ea7f87
Compare
@swift-ci Please test |
Build failed |
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'm happy with these changes—the is
/as
methods and initializer-based conversions are an improvement over the original property-based forms, and should make client code cleaner. The performance improvements will be great for swift-format too.
Can you update the API Example in your PR description to use the new version of the APIs? It looks like it's still based on the original version of this PR; having it up-to-date will be helpful for future readers who stumble upon this change.
@allevato Thanks for the review. Sorry, I totally missed to update the code example. It’s updated now. |
Don't propagate the diagnostic engine when formatting.
While investigating performance problems with SwiftSyntax, in particular the SyntaxRewriter, we have noticed that a considerable time was spent dealing with existentials that result from the way we model the syntax hierarchy using protocols. In an effort to reduce this problem, I have restructured the entire syntax layout to eliminate protocols and be entirely struct-based. As this has some major implications to SwiftSyntax’s API, I’d like to get some feedback on whether we should use it or not.
API Change
The main idea of this PR is to model each syntax node as a
struct
and allow casting between those structs either through initializers or designatedas(TargetType.self)
casting methods.Furthermore there exist protocols
SyntaxProtocol
,ExprSyntaxProtocol
etc. to which all all corresponding syntax nodes conform. That way, additional methods can be added to all syntax nodes by conforming to the corresponding protocol.There is an enum
SyntaxEnum
that can be retrieved from asSyntax
node by callingasSyntaxEnum
and allows exhaustive switching over all enum kinds.Performance improvement
Performance measurements were done by running an empty
SyntaxRewriter
/SyntaxVisitor
on a Swift file with ~5000 lines of code. The baseline is the current performance of SwiftSyntax before #157 was merged.Highlights are a 10x performance increase in
SytnaxRewriter
performance. Performance ofSyntaxVisitor
is roughly the same right now but can be improved by 10% in #158 that models it as a class instead of a protocol.Empty
SyntaxRewriter
Empty
SyntaxVisitor
Empty
SyntaxAnyVisitor
API example