Skip to content

Commit deef247

Browse files
rxweiDougGregor
authored andcommitted
[Macros] Parse top-level macro expansion declarations
Parse freestanding macro expansions as declarations rather than expressions when it's not part of a statement or expression (i.e. "top-level").
1 parent 0283ae6 commit deef247

File tree

5 files changed

+46
-25
lines changed

5 files changed

+46
-25
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,12 @@ extension Parser {
192192
return RawDeclSyntax(directive)
193193
case (.poundWarningKeyword, _)?, (.poundErrorKeyword, _)?:
194194
return self.parsePoundDiagnosticDeclaration()
195-
case nil:
196-
break
197-
}
198-
199-
if (self.at(.pound)) {
195+
case (.pound, _)?:
200196
// FIXME: If we can have attributes for macro expansions, handle this
201197
// via DeclarationStart.
202198
return RawDeclSyntax(self.parseMacroExpansionDeclaration())
199+
case nil:
200+
break
203201
}
204202

205203
let attrs = DeclAttributes(

Sources/SwiftParser/RawTokenKindSubset.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,12 +513,14 @@ enum PoundDeclarationStart: RawTokenKindSubset {
513513
case poundIfKeyword
514514
case poundWarningKeyword
515515
case poundErrorKeyword
516+
case pound
516517

517518
init?(lexeme: Lexer.Lexeme) {
518519
switch lexeme.rawTokenKind {
519520
case .poundIfKeyword: self = .poundIfKeyword
520521
case .poundWarningKeyword: self = .poundWarningKeyword
521522
case .poundErrorKeyword: self = .poundErrorKeyword
523+
case .pound: self = .pound
522524
default: return nil
523525
}
524526
}
@@ -528,6 +530,7 @@ enum PoundDeclarationStart: RawTokenKindSubset {
528530
case .poundIfKeyword: return .poundIfKeyword
529531
case .poundWarningKeyword: return .poundWarningKeyword
530532
case .poundErrorKeyword: return .poundErrorKeyword
533+
case .pound: return .pound
531534
}
532535
}
533536
}

Sources/_SwiftSyntaxMacros/MacroSystem.swift

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,28 @@ class MacroApplication: SyntaxRewriter {
127127
for item in node {
128128
// Expand declaration macros that were parsed as macro expansion
129129
// expressions in this context.
130-
if case let .expr(exprItem) = item.item,
131-
let exprExpansion = exprItem.as(MacroExpansionExprSyntax.self),
132-
let macro = macroSystem.macros[exprExpansion.macro.text],
133-
let freestandingMacro = macro as? DeclarationMacro.Type
130+
if case let .decl(declItem) = item.item,
131+
let declExpansion = declItem.as(MacroExpansionDeclSyntax.self),
132+
let macro = macroSystem.macros[declExpansion.macro.text]
134133
{
135134
do {
136-
let expandedDecls = try freestandingMacro.expansion(
137-
of: exprExpansion.asMacroExpansionDecl(),
138-
in: &context
139-
)
140-
141-
newItems.append(
142-
contentsOf: expandedDecls.map { decl in
143-
CodeBlockItemSyntax(item: .decl(decl))
144-
}
145-
)
135+
if let macro = macro as? DeclarationMacro.Type {
136+
let expandedItemList = try macro.expansion(
137+
of: declExpansion,
138+
in: &context
139+
)
140+
newItems.append(
141+
contentsOf: expandedItemList.map {
142+
CodeBlockItemSyntax(item: .decl($0))
143+
}
144+
)
145+
} else if let macro = macro as? ExpressionMacro.Type {
146+
let expandedExpr = try macro.expansion(
147+
of: declExpansion.asMacroExpansionExpr(),
148+
in: &context
149+
)
150+
newItems.append(CodeBlockItemSyntax(item: .init(expandedExpr)))
151+
}
146152
} catch {
147153
// Record the error
148154
context.diagnose(
@@ -183,14 +189,14 @@ class MacroApplication: SyntaxRewriter {
183189
let freestandingMacro = macro as? DeclarationMacro.Type
184190
{
185191
do {
186-
let expandedDecls = try freestandingMacro.expansion(
192+
let expandedList = try freestandingMacro.expansion(
187193
of: declExpansion,
188194
in: &context
189195
)
190196

191197
newItems.append(
192-
contentsOf: expandedDecls.map { decl in
193-
MemberDeclListItemSyntax(decl: decl)
198+
contentsOf: expandedList.map { decl in
199+
return MemberDeclListItemSyntax(decl: decl)
194200
}
195201
)
196202
} catch {

Sources/_SwiftSyntaxMacros/Syntax+MacroEvaluation.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ struct ThrownErrorDiagnostic: DiagnosticMessage {
2424
}
2525
}
2626

27-
extension MacroExpansionExprSyntax {
27+
extension MacroExpansionDeclSyntax {
2828
/// Macro expansion declarations are parsed in some positions where an
2929
/// expression is also warranted, so
30-
func asMacroExpansionDecl() -> MacroExpansionDeclSyntax {
31-
MacroExpansionDeclSyntax(
30+
public func asMacroExpansionExpr() -> MacroExpansionExprSyntax {
31+
MacroExpansionExprSyntax(
3232
unexpectedBeforePoundToken,
3333
poundToken: poundToken,
3434
unexpectedBetweenPoundTokenAndMacro,
@@ -47,7 +47,9 @@ extension MacroExpansionExprSyntax {
4747
unexpectedAfterAdditionalTrailingClosures
4848
)
4949
}
50+
}
5051

52+
extension MacroExpansionExprSyntax {
5153
/// Evaluate the given macro for this syntax node, producing the expanded
5254
/// result and (possibly) some diagnostics.
5355
func evaluateMacro(

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,18 @@ final class DeclarationTests: XCTestCase {
11621162
}
11631163
"""
11641164
)
1165+
AssertParse(
1166+
"""
1167+
#expand
1168+
""",
1169+
substructure: Syntax(
1170+
SourceFileSyntax(
1171+
CodeBlockItemListSyntax {
1172+
MacroExpansionDeclSyntax(macro: "expand")
1173+
}
1174+
)
1175+
)
1176+
)
11651177
}
11661178

11671179
func testVariableDeclWithGetSetButNoBrace() {

0 commit comments

Comments
 (0)