-
Notifications
You must be signed in to change notification settings - Fork 439
Add handwritten convenience initializers #291
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
Add handwritten convenience initializers #291
Conversation
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.
Nice. This is looking great!
@swift-ci Please test |
@ahoppen thanks! Any good ideas? 😁 |
So, I have finally managed to play around with this and tried to create a struct with a few variables as members. What I think would have been nice would have been something like this: Struct("MyStruct") {
Variable(.let, name: "myFirstVar", type: "Int")
Variable(.var, name: "myOtherVar", type: "String")
} (disclaimer: It doesn’t have to be exactly this syntax, it’s just what I would have loved but I really wouldn’t mind if the syntax looked a little different). Instead, I had to write this: 1 | StructDecl(identifier: "TestStruct", members: MemberDeclBlock(membersBuilder: {
2 | MemberDeclListItem(decl:
3 | VariableDecl(letOrVarKeyword: Tokens.let) {
4 | PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("myFirstVar")),
5 | typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("Int")))
6 | }
7 | )
8 | MemberDeclListItem(decl:
9 | VariableDecl(letOrVarKeyword: Tokens.let) {
10 | PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("myOtherVar")),
11 | typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("String")))
12 | }
13 | )
14 | })
15 | ) So, here’s my wish list by line number since you were asking ;-) 1a. The types should strip the 1b. A 1c. I should be able to write the 2a. I shouldn’t need to wrap the protocol ExpressibleAsMemberDeclListItem {
func createMemberDeclListItem() -> MemberDeclListItem
} and that extension MemberDeclListItem: ExpressibleAsMemberDeclListItem {
func createMemberDeclListItem() -> MemberDeclListItem { return self }
}
extension DeclBuildable: ExpressibleAsMemberDeclListItem {
func createMemberDeclListItem() -> MemberDeclListItem { return MemberDeclListItem(decl: self) }
} The same approach would probably also work for all other result builders and would give us the flexibility to avoid these boilderplate conversions for other types (e.g. 3a. I think a manually written convenience initializer to create variables would be a good idea. The current syntax is just gross. 3b. If the 4a. If any of these don’t make sense to you, please ask! In any case, thanks again so much for working on this! 🙏 |
I have tried to generate without the We get some clashes with types like Any suggestions @ahoppen ?
I have tried to generate with all result builder at the end. extension VariableDecl {
public init(
letOrVarKeyword: TokenSyntax,
@AttributeListBuilder attributesBuilder: () -> AttributeList? = { nil },
@ModifierListBuilder modifiersBuilder: () -> ModifierList? = { nil },
@PatternBindingListBuilder bindingsBuilder: () -> PatternBindingList = { .empty }
) {
self.init(
attributes: attributesBuilder(),
modifiers: modifiersBuilder(),
letOrVarKeyword: letOrVarKeyword,
bindings: bindingsBuilder()
)
}
} But test case let buildable = VariableDecl(letOrVarKeyword: Tokens.var) {
PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("number")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("Int")),
initializer: InitializerClause(value: IntegerLiteralExpr(digits: Tokens.integerLiteral("123"))))
} Gives a warning We could add a let buildable = VariableDecl(letOrVarKeyword: Tokens.let, {
PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("color")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("UIColor")))
})
I'm not sure on this? extension TokenSyntax: ExpressibleByStringLiteral {
public init(stringLiteral value: Int) {
self.init(value)
}
} |
Ah, I didn’t consider that. In that case maybe it’s best to just leave the suffixes there for the moment.
Hmm. That’s a bit unfortunate. Still, I think it would be beneficial to have the result builders at the end because:
That’s what I was thinking. Why do you have doubts? |
And we try again @ahoppen 😄
I have added some handwritten convenience initializers.
Is there more you could think of, that would make it easier?