Skip to content

Commit bbfec76

Browse files
committed
Don’t automaticaly conform all decl/stmt/etc. nodes to ExpressibleByStringLiteral
This removes the implicit expressibility by string literals for all decl/stmt/... nodes, which parsed the node as a decl/stmt/... and then cast it to the expected type. rdar://104090218
1 parent 3ca3c0b commit bbfec76

22 files changed

+210
-638
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntaxbuilder/SyntaxExpressibleByStringInterpolationConformancesFile.swift

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,38 +35,8 @@ let syntaxExpressibleByStringInterpolationConformancesFile = SourceFileSyntax {
3535
""")
3636
}
3737

38-
for node in SYNTAX_NODES {
39-
if node.isBase {
40-
ExtensionDeclSyntax("extension \(raw: node.name)Protocol") {
41-
InitializerDeclSyntax(
42-
"""
43-
public init(stringInterpolationOrThrow stringInterpolation: SyntaxStringInterpolation) throws {
44-
self = try performParse(source: stringInterpolation.sourceText, parse: { parser in
45-
let node = \(raw: node.name).parse(from: &parser)
46-
guard let result = node.as(Self.self) else {
47-
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualType: node.kind.syntaxNodeType)
48-
}
49-
return result
50-
})
51-
}
52-
""")
53-
}
54-
}
55-
56-
if node.parserFunction != nil {
57-
ExtensionDeclSyntax("extension \(raw: node.name): SyntaxExpressibleByStringInterpolation") {
58-
InitializerDeclSyntax(
59-
"""
60-
public init(stringInterpolationOrThrow stringInterpolation: SyntaxStringInterpolation) throws {
61-
self = try performParse(source: stringInterpolation.sourceText, parse: { parser in
62-
return Self.parse(from: &parser)
63-
})
64-
}
65-
""")
66-
}
67-
} else if !node.isMissing && node.baseType.baseName != "Syntax" && node.baseType.baseName != "SyntaxCollection" {
68-
ExtensionDeclSyntax("extension \(raw: node.name): SyntaxExpressibleByStringInterpolation { }")
69-
}
38+
for node in SYNTAX_NODES where node.parserFunction != nil {
39+
ExtensionDeclSyntax("extension \(raw: node.name): SyntaxExpressibleByStringInterpolation {}")
7040
}
7141

7242
FunctionDeclSyntax(

Examples/CodeGenerationUsingSwiftSyntaxBuilder.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ struct Main {
4848
let source = SourceFileSyntax {
4949
StructDeclSyntax(identifier: "Person") {
5050
for (propertyName, propertyType) in properties {
51-
VariableDeclSyntax("var \(raw: propertyName): \(raw: propertyType)")
51+
DeclSyntax("var \(raw: propertyName): \(raw: propertyType)")
5252

53-
FunctionDeclSyntax("""
53+
DeclSyntax("""
5454
func with\(raw: propertyName.withFirstLetterUppercased())(_ \(raw: propertyName): \(raw: propertyType)) -> Person {
5555
var result = self
5656
result.\(raw: propertyName) = \(raw: propertyName)

Sources/SwiftSyntaxBuilder/ConvenienceInitializers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ extension VariableDeclSyntax {
408408
attributes: AttributeListSyntax? = nil,
409409
modifiers: ModifierListSyntax? = nil,
410410
_ letOrVarKeyword: Keyword,
411-
name: IdentifierPatternSyntax,
411+
name: PatternSyntax,
412412
type: TypeAnnotationSyntax? = nil,
413413
initializer: InitializerClauseSyntax? = nil
414414
) {
@@ -431,7 +431,7 @@ extension VariableDeclSyntax {
431431
leadingTrivia: Trivia = [],
432432
attributes: AttributeListSyntax? = nil,
433433
modifiers: ModifierListSyntax? = nil,
434-
name: IdentifierPatternSyntax,
434+
name: PatternSyntax,
435435
type: TypeAnnotationSyntax,
436436
@CodeBlockItemListBuilder accessor: () -> CodeBlockItemListSyntax
437437
) {

Sources/SwiftSyntaxBuilder/Syntax+StringInterpolation.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ enum SyntaxStringInterpolationError: Error, CustomStringConvertible {
150150
case producedInvalidNodeType(expectedType: SyntaxProtocol.Type, actualType: SyntaxProtocol.Type)
151151
case diagnostics([Diagnostic], tree: Syntax)
152152

153+
static func producedInvalidNodeType<S: SyntaxProtocol>(expectedType: SyntaxProtocol.Type, actualNode: S) -> Self {
154+
return .producedInvalidNodeType(expectedType: expectedType, actualType: type(of: actualNode))
155+
}
156+
153157
var description: String {
154158
switch self {
155159
case .producedInvalidNodeType(expectedType: let expectedType, actualType: let actualType):

Sources/SwiftSyntaxBuilder/SyntaxNodeWithBody.swift

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,27 @@ extension SyntaxStringInterpolation {
3939

4040
public protocol HasTrailingCodeBlock {
4141
var body: CodeBlockSyntax { get set }
42+
43+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) throws
4244
}
4345

44-
public extension HasTrailingCodeBlock where Self: SyntaxExpressibleByStringInterpolation {
45-
init(_ signature: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) {
46-
self = "\(signature) {}"
46+
public extension HasTrailingCodeBlock where Self: StmtSyntaxProtocol {
47+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) throws {
48+
let stmt = StmtSyntax("\(header) {}")
49+
guard let castedStmt = stmt.as(Self.self) else {
50+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: stmt)
51+
}
52+
self = castedStmt
4753
self.body = CodeBlockSyntax(statements: bodyBuilder())
4854
}
4955
}
5056

51-
extension CatchClauseSyntax: HasTrailingCodeBlock {}
57+
extension CatchClauseSyntax: HasTrailingCodeBlock {
58+
public init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) throws {
59+
self = CatchClauseSyntax("\(header) {}")
60+
self.body = CodeBlockSyntax(statements: bodyBuilder())
61+
}
62+
}
5263
extension DeferStmtSyntax: HasTrailingCodeBlock {}
5364
extension DoStmtSyntax: HasTrailingCodeBlock {}
5465
extension ForInStmtSyntax: HasTrailingCodeBlock {}
@@ -59,11 +70,17 @@ extension WhileStmtSyntax: HasTrailingCodeBlock {}
5970

6071
public protocol HasTrailingOptionalCodeBlock {
6172
var body: CodeBlockSyntax? { get set }
73+
74+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) throws
6275
}
6376

64-
public extension HasTrailingOptionalCodeBlock where Self: SyntaxExpressibleByStringInterpolation {
65-
init(_ signature: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) {
66-
self = "\(signature) {}"
77+
public extension HasTrailingOptionalCodeBlock where Self: DeclSyntaxProtocol {
78+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax) throws {
79+
let decl = DeclSyntax("\(header) {}")
80+
guard let castedDecl = decl.as(Self.self) else {
81+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: decl)
82+
}
83+
self = castedDecl
6784
self.body = CodeBlockSyntax(statements: bodyBuilder())
6885
}
6986
}
@@ -77,11 +94,17 @@ extension InitializerDeclSyntax: HasTrailingOptionalCodeBlock {}
7794

7895
public protocol HasTrailingMemberDeclBlock {
7996
var members: MemberDeclBlockSyntax { get set }
97+
98+
init(_ header: PartialSyntaxNodeString, @MemberDeclListBuilder membersBuilder: () -> MemberDeclListSyntax) throws
8099
}
81100

82-
public extension HasTrailingMemberDeclBlock where Self: SyntaxExpressibleByStringInterpolation {
83-
init(_ signature: PartialSyntaxNodeString, @MemberDeclListBuilder membersBuilder: () -> MemberDeclListSyntax) {
84-
self = "\(signature) {}"
101+
public extension HasTrailingMemberDeclBlock where Self: DeclSyntaxProtocol {
102+
init(_ header: PartialSyntaxNodeString, @MemberDeclListBuilder membersBuilder: () -> MemberDeclListSyntax) throws {
103+
let decl = DeclSyntax("\(header) {}")
104+
guard let castedDecl = decl.as(Self.self) else {
105+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: decl)
106+
}
107+
self = castedDecl
85108
self.members = MemberDeclBlockSyntax(members: membersBuilder())
86109
}
87110
}
@@ -98,15 +121,23 @@ extension StructDeclSyntax: HasTrailingMemberDeclBlock {}
98121
// So we cannot conform to `HasTrailingCodeBlock`
99122

100123
public extension IfStmtSyntax {
101-
init(_ signature: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax, @CodeBlockItemListBuilder `else` elseBuilder: () -> CodeBlockItemListSyntax? = { nil }) {
102-
self = "\(signature) {}"
124+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax, @CodeBlockItemListBuilder `else` elseBuilder: () -> CodeBlockItemListSyntax? = { nil }) throws {
125+
let stmt = StmtSyntax("\(header) {}")
126+
guard let ifStmt = stmt.as(IfStmtSyntax.self) else {
127+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: stmt)
128+
}
129+
self = ifStmt
103130
self.body = CodeBlockSyntax(statements: bodyBuilder())
104131
self.elseBody = elseBuilder().map { .codeBlock(CodeBlockSyntax(statements: $0)) }
105132
self.elseKeyword = elseBody != nil ? .keyword(.else) : nil
106133
}
107134

108-
init(_ signature: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax, elseIf: IfStmtSyntax) {
109-
self = "\(signature) {}"
135+
init(_ header: PartialSyntaxNodeString, @CodeBlockItemListBuilder bodyBuilder: () -> CodeBlockItemListSyntax, elseIf: IfStmtSyntax) throws {
136+
let stmt = StmtSyntax("\(header) {}")
137+
guard let ifStmt = stmt.as(IfStmtSyntax.self) else {
138+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: stmt)
139+
}
140+
self = ifStmt
110141
self.body = CodeBlockSyntax(statements: bodyBuilder())
111142
self.elseBody = .ifStmt(elseIf)
112143
self.elseKeyword = elseBody != nil ? .keyword(.else) : nil
@@ -118,8 +149,12 @@ public extension IfStmtSyntax {
118149
// So we cannot conform to `HasTrailingCodeBlock` or `HasTrailingMemberDeclBlock`
119150

120151
public extension SwitchStmtSyntax {
121-
init(_ signature: PartialSyntaxNodeString, @SwitchCaseListBuilder casesBuilder: () -> SwitchCaseListSyntax = { SwitchCaseListSyntax([]) }) {
122-
self = "\(signature) {}"
152+
init(_ header: PartialSyntaxNodeString, @SwitchCaseListBuilder casesBuilder: () -> SwitchCaseListSyntax = { SwitchCaseListSyntax([]) }) throws {
153+
let stmt = StmtSyntax("\(header) {}")
154+
guard let castedStmt = stmt.as(Self.self) else {
155+
throw SyntaxStringInterpolationError.producedInvalidNodeType(expectedType: Self.self, actualNode: stmt)
156+
}
157+
self = castedStmt
123158
self.cases = casesBuilder()
124159
}
125160
}

0 commit comments

Comments
 (0)