Skip to content

Commit f6e500d

Browse files
committed
[Parser] Go back to parsing macro expansions as expressions where possible
The change to eagerly parsing macro expansions as declarations rather than expressions caused a regression for expressions that start with a macro expansion, e.g., `#fileID == "Module/filename.swift"`. Rather than perform extensive lookahead to disambiguate, go back to parsing as a macro expansion expression except in places where only a declaration is allowed (e.g., a member list). To accommodate this for freestanding macro implementations, generalize the `CodeItemMacro` and `DeclarationMacro` expansion operations to deal with an arbitrary `FreestandingMacroExpansionSyntax`, as we had already done for `ExpressionMacro`. Fixes #1292.
1 parent f7667e1 commit f6e500d

File tree

9 files changed

+36
-23
lines changed

9 files changed

+36
-23
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ extension TokenConsumer {
3232
mutating func atStartOfDeclaration(
3333
isAtTopLevel: Bool = false,
3434
allowInitDecl: Bool = true,
35-
allowRecovery: Bool = false,
36-
preferPoundAsExpression: Bool = false
35+
allowRecovery: Bool = false
3736
) -> Bool {
3837
if self.at(anyIn: PoundDeclarationStart.self) != nil {
39-
// If we are in a context where we prefer # to be an expression,
40-
// treat it as one if it's not at the start of the line.
41-
if preferPoundAsExpression && self.at(.pound) && !self.currentToken.isAtStartOfLine {
38+
// Don't treat freestanding macro expansions as declarations. They'll be
39+
// parsed as expressions.
40+
if self.at(.pound) {
4241
return false
4342
}
4443

Sources/SwiftParser/Statements.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ extension Parser {
959959
.poundIfKeyword, .poundEndifKeyword, .poundElseKeyword,
960960
.poundElseifKeyword,
961961
])
962-
&& !self.atStartOfStatement() && !self.atStartOfDeclaration(preferPoundAsExpression: true)
962+
&& !self.atStartOfStatement() && !self.atStartOfDeclaration()
963963
{
964964
let parsedExpr = self.parseExpression()
965965
if hasMisplacedTry && !parsedExpr.is(RawTryExprSyntax.self) {

Sources/SwiftSyntaxMacros/MacroProtocols/CodeItemMacro.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ import SwiftSyntax
1313
public protocol CodeItemMacro: FreestandingMacro {
1414
/// Expand a macro described by the given freestanding macro expansion
1515
/// declaration within the given context to produce a set of declarations.
16-
static func expansion<Context: MacroExpansionContext>(
17-
of node: MacroExpansionDeclSyntax,
16+
static func expansion<
17+
Node: FreestandingMacroExpansionSyntax,
18+
Context: MacroExpansionContext
19+
>(
20+
of node: Node,
1821
in context: Context
1922
) throws -> [CodeBlockItemSyntax]
2023
}

Sources/SwiftSyntaxMacros/MacroProtocols/DeclarationMacro.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ public protocol DeclarationMacro: FreestandingMacro {
1414
/// Expand a macro described by the given freestanding macro expansion
1515
/// declaration within the given context to produce a set of declarations.
1616
static func expansion<
17+
Node: FreestandingMacroExpansionSyntax,
1718
Context: MacroExpansionContext
1819
>(
19-
of node: MacroExpansionDeclSyntax,
20+
of node: Node,
2021
in context: Context
2122
) throws -> [DeclSyntax]
2223
}

Sources/SwiftSyntaxMacros/MacroSystem.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,14 @@ class MacroApplication<Context: MacroExpansionContext>: 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 .decl(declItem) = item.item,
131-
let declExpansion = declItem.as(MacroExpansionDeclSyntax.self),
132-
let macro = macroSystem.macros[declExpansion.macro.text]
130+
if case let .expr(exprItem) = item.item,
131+
let exprExpansion = exprItem.as(MacroExpansionExprSyntax.self),
132+
let macro = macroSystem.macros[exprExpansion.macro.text]
133133
{
134134
do {
135135
if let macro = macro as? DeclarationMacro.Type {
136136
let expandedItemList = try macro.expansion(
137-
of: declExpansion,
137+
of: exprExpansion,
138138
in: context
139139
)
140140
newItems.append(
@@ -144,7 +144,7 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
144144
)
145145
} else if let macro = macro as? ExpressionMacro.Type {
146146
let expandedExpr = try macro.expansion(
147-
of: declExpansion,
147+
of: exprExpansion,
148148
in: context
149149
)
150150
newItems.append(CodeBlockItemSyntax(item: .init(expandedExpr)))

Tests/SwiftParserTest/ExpressionTests.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ final class ExpressionTests: XCTestCase {
749749
"#keyPath((b:1️⃣)2️⃣",
750750
diagnostics: [
751751
DiagnosticSpec(locationMarker: "1️⃣", message: "expected value in tuple"),
752-
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end macro expansion"),
752+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' to end macro expansion expression"),
753753
]
754754
)
755755
}
@@ -896,6 +896,10 @@ final class ExpressionTests: XCTestCase {
896896
}
897897

898898
func testMacroExpansionExpression() {
899+
AssertParse(
900+
#"#file == $0.path"#
901+
)
902+
899903
AssertParse(
900904
#"let a = #embed("filename.txt")"#
901905
)

Tests/SwiftParserTest/translated/MultilinePoundDiagnosticArgRdar41154797Tests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class MultilinePoundDiagnosticArgRdar41154797Tests: XCTestCase {
2222
"""##,
2323
diagnostics: [
2424
DiagnosticSpec(message: #"expected '"""' to end string literal"#),
25-
DiagnosticSpec(message: "expected ')' to end macro expansion"),
25+
DiagnosticSpec(message: "expected ')' to end macro expansion expression"),
2626
]
2727
)
2828
}

Tests/SwiftParserTest/translated/PoundAssertTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ final class PoundAssertTests: XCTestCase {
4949
#assert(1️⃣, "error message")
5050
"""#,
5151
diagnostics: [
52-
DiagnosticSpec(message: "expected value in macro expansion")
52+
DiagnosticSpec(message: "expected value in macro expansion expression")
5353
]
5454
)
5555
}
@@ -63,7 +63,7 @@ final class PoundAssertTests: XCTestCase {
6363
""",
6464
diagnostics: [
6565
DiagnosticSpec(
66-
message: "expected ')' to end macro expansion",
66+
message: "expected ')' to end macro expansion expression",
6767
notes: [
6868
NoteSpec(message: "to match this opening '('")
6969
]
@@ -81,7 +81,7 @@ final class PoundAssertTests: XCTestCase {
8181
"""#,
8282
diagnostics: [
8383
DiagnosticSpec(
84-
message: "expected ')' to end macro expansion",
84+
message: "expected ')' to end macro expansion expression",
8585
notes: [
8686
NoteSpec(message: "to match this opening '('")
8787
]

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,11 @@ extension SimpleDiagnosticMessage: FixItMessage {
198198
}
199199

200200
public struct ErrorMacro: DeclarationMacro {
201-
public static func expansion<Context: MacroExpansionContext>(
202-
of node: MacroExpansionDeclSyntax,
201+
public static func expansion<
202+
Node: FreestandingMacroExpansionSyntax,
203+
Context: MacroExpansionContext
204+
>(
205+
of node: Node,
203206
in context: Context
204207
) throws -> [DeclSyntax] {
205208
guard let firstElement = node.argumentList.first,
@@ -227,8 +230,11 @@ public struct ErrorMacro: DeclarationMacro {
227230
}
228231

229232
struct DefineBitwidthNumberedStructsMacro: DeclarationMacro {
230-
static func expansion<Context: MacroExpansionContext>(
231-
of node: MacroExpansionDeclSyntax,
233+
static func expansion<
234+
Node: FreestandingMacroExpansionSyntax,
235+
Context: MacroExpansionContext
236+
>(
237+
of node: Node,
232238
in context: Context
233239
) throws -> [DeclSyntax] {
234240
guard let firstElement = node.argumentList.first,

0 commit comments

Comments
 (0)