Skip to content

Update CodeGeneration to use new convenience initializers #1019

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

Merged
merged 1 commit into from
Oct 26, 2022

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Oct 25, 2022

Update CodeGeneration to take advantage of #1012

@ahoppen ahoppen requested a review from fwcd October 25, 2022 16:02
Copy link
Member

@fwcd fwcd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor comment, otherwise I'd say this looks good!

Comment on lines 29 to 32
StructDecl(
attributes: [CustomAttribute(trailingTrivia: .newline, attributeName: Type("resultBuilder"))],
attributes: [.customAttribute(CustomAttribute(trailingTrivia: .newline, attributeName: Type("resultBuilder")))],
modifiers: [DeclModifier(name: .public)],
identifier: "\(type.syntaxKind)Builder") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use the parsing initializer here too, i.e. something along the lines of

StructDecl("@resultBuilder public struct \(type.syntaxKind)Builder") {
  ...
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I just missed that.

@evnik
Copy link
Contributor

evnik commented Oct 26, 2022

TBH I don't like where does it go with that new feature. Instead of clear calls structure it now just bunch of interpolated strings. Why bother with different statements if it could be just several strings for the whole file, like writeToFile("import Foundation\nclass \(className) { func \(funcName)() { } }")

@ahoppen
Copy link
Member Author

ahoppen commented Oct 26, 2022

TBH I don't like where does it go with that new feature. Instead of clear calls structure it now just bunch of interpolated strings. Why bother with different statements if it could be just several strings for the whole file, like writeToFile("import Foundation\nclass \(className) { func \(funcName)() { } }")

That’s very interesting because I very much prefer the new design because it’s IMO a lot easier to read. My idea for SwiftSyntaxBuilder currently was that you use the parser integration (aka string literals) for all the boilerplate that is mostly statically known while still being able to use result builder and the tree structure of the SwiftSyntax tree to

  • stamp out loops and
  • implement complex code generation where e.g. one node gets wrapped in another.

But that’s just my take. Going back to the example that @fwcd pointed out above, did you prefer

    StructDecl(
      attributes: [.customAttribute(CustomAttribute(trailingTrivia: .newline, attributeName: Type("resultBuilder")))],
      modifiers: [DeclModifier(name: .public)],
      identifier: "\(type.syntaxKind)Builder") {

over

StructDecl("@resultBuilder public struct \(type.syntaxKind)Builder") {

If yes, I would be very interested to hear the reasons.

@ahoppen ahoppen force-pushed the ahoppen/udpate-codegen branch from 033cbdf to 2c04f34 Compare October 26, 2022 08:25
@ahoppen
Copy link
Member Author

ahoppen commented Oct 26, 2022

@swift-ci Please test

@fwcd
Copy link
Member

fwcd commented Oct 26, 2022

I can kind of see the point of @evnik, we're basically trading compile-time type-safety (to a degree) for convenience/conciseness/readability. E.g. things like FunctionDecl("let x = 4") will now error at run-time first, rather than at compile-time. For this particular application this is probably fine, since we usually run the generator in tandem with compilation, but it does e.g. have the IDE catch fewer errors. The advantage over plain copy-pasting is that the parser will still catch syntax errors earlier than in the generated file (I think?), but I agree that it feels a bit less "structured" than before.

@ahoppen
Copy link
Member Author

ahoppen commented Oct 26, 2022

That is correct, we are trading some of the compile-time safety for generation-time safety (the parser will catch the same kind of issues that would previously have been caught while compiling the generation files but as @fwcd mentioned you very rarely compile the generation files without running them, so I think it doesn’t actually make a huge difference.

IMO the real benefits of the new APIs are that

  1. You can copy paste methods templates from a normal Swift file into a generation template
  2. You don’t need to know the entire structure of the syntax tree for structures that are usually static (like variable initializers)
  3. It’s also a lot easier to understand what’s being generated IMO because the information is denser.

@ahoppen
Copy link
Member Author

ahoppen commented Oct 26, 2022

Since this is “just” the update of CodeGeneration for an API that already exists, I’m going to merge. I would still like to continue the discussion.

@ahoppen ahoppen merged commit 79c8e55 into swiftlang:main Oct 26, 2022
@ahoppen ahoppen deleted the ahoppen/udpate-codegen branch October 26, 2022 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants