Given the following data structure:
public struct Test {
var trueKey: Bool = true
var falseKey = false
}
if we go through the abstract syntax tree var trueKey: Bool = true returns, among other things the TypeAnnotationSyntax as follow:
├─bindingSpecifier: keyword(SwiftSyntax.Keyword.var)
╰─bindings: PatternBindingListSyntax
╰─[0]: PatternBindingSyntax
├─pattern: IdentifierPatternSyntax
│ ╰─identifier: identifier("trueKey")
├─typeAnnotation: TypeAnnotationSyntax
│ ├─colon: colon
│ ╰─type: IdentifierTypeSyntax
│ ╰─name: identifier("Bool")
╰─initializer: InitializerClauseSyntax
├─equal: equal
╰─value: BooleanLiteralExprSyntax
╰─literal: keyword(SwiftSyntax.Keyword.true)
whereas var falseKey = false does not include the TypeAnnotationSyntax type as it's inferred and returns:
VariableDeclSyntax
├─bindingSpecifier: keyword(SwiftSyntax.Keyword.var)
╰─bindings: PatternBindingListSyntax
╰─[0]: PatternBindingSyntax
├─pattern: IdentifierPatternSyntax
│ ╰─identifier: identifier("falseKey")
╰─initializer: InitializerClauseSyntax
├─equal: equal
╰─value: BooleanLiteralExprSyntax
╰─literal: keyword(SwiftSyntax.Keyword.false)
Is there a reason for that? Moreover is there a way to extract the type in a generic way?
allevato
(Tony Allevato)
2
SwiftSyntax only represents the actual syntax present in the file, so this isn't possible. Types aren't inferred until later on during semantic analysis.
You can try to make a best guess when the value being assigned is a literal, but code like this will always be a problem:
var x = someFunction()
4 Likes
You can eventually pass the type as parameter to the macro (not ideal, but that what i got) and eventually enforce that only when the syntax tree doesn't have it with a diagnostic
Yeah no I am aware of the alternatives, it just seemed weird given that the AST has an initializer.value type that can lead to extracting the type - and I can do that manually for more straightforward types (like bool, string and Int) -, but as @allevato explained this is done at a later stage.
Thanks to both on the feedback :)
I wrote an advanced macro that will generate an initialiser even parse all standard inferred data types
young
(rtSwift)
6
What’s the reason for such a macro? Isn’t what it generates is what the compiler generates aside from default values.
@young And it’s public by default. I work a lot on SDKs. And their data models tend to be public so I have to explicitly write the initialiser every time as by default it’s internal. So that’s a lot of unnecessary lines of code.
2 Likes