Skip to content

Commit 45eb057

Browse files
committed
[Parser] Attributes on MacroExpansionDeclSyntax
* Add `attributes` and `modifiers` to `MacroExpansionDeclSyntax` * Diagnose whitespaces between # and the macro name * Attach attributes to MacroExpansionDeclSyntax rdar://107386648 (cherry picked from commit fd89876)
1 parent a63faab commit 45eb057

File tree

11 files changed

+513
-107
lines changed

11 files changed

+513
-107
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,18 @@ public let DECL_NODES: [Node] = [
11941194
"FreestandingMacroExpansion"
11951195
],
11961196
children: [
1197+
Child(
1198+
name: "Attributes",
1199+
kind: .collection(kind: "AttributeList", collectionElementName: "Attribute"),
1200+
nameForDiagnostics: "attributes",
1201+
isOptional: true
1202+
),
1203+
Child(
1204+
name: "Modifiers",
1205+
kind: .collection(kind: "ModifierList", collectionElementName: "Modifier"),
1206+
nameForDiagnostics: "modifiers",
1207+
isOptional: true
1208+
),
11971209
Child(
11981210
name: "PoundToken",
11991211
kind: .token(choices: [.token(tokenKind: "PoundToken")]),

Sources/SwiftParser/Declarations.swift

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,25 @@ extension DeclarationModifier {
2929
}
3030

3131
extension TokenConsumer {
32+
mutating func atStartOfFreestandingMacroExpansion() -> Bool {
33+
if !self.at(.pound) {
34+
return false
35+
}
36+
if self.peek().rawTokenKind != .identifier && !self.peek().isLexerClassifiedKeyword {
37+
return false
38+
}
39+
if self.currentToken.trailingTriviaByteLength != 0 || self.peek().leadingTriviaByteLength != 0 {
40+
return false
41+
}
42+
return true
43+
}
44+
3245
mutating func atStartOfDeclaration(
3346
isAtTopLevel: Bool = false,
3447
allowInitDecl: Bool = true,
3548
allowRecovery: Bool = false
3649
) -> Bool {
3750
if self.at(anyIn: PoundDeclarationStart.self) != nil {
38-
// Don't treat freestanding macro expansions as declarations. They'll be
39-
// parsed as expressions.
40-
if self.at(.pound) {
41-
return false
42-
}
43-
4451
return true
4552
}
4653

@@ -53,12 +60,14 @@ extension TokenConsumer {
5360
_ = subparser.consumeAttributeList()
5461
}
5562

63+
var hasModifier = false
5664
if subparser.currentToken.isLexerClassifiedKeyword || subparser.currentToken.rawTokenKind == .identifier {
5765
var modifierProgress = LoopProgressCondition()
5866
while let (modifierKind, handle) = subparser.at(anyIn: DeclarationModifier.self),
5967
modifierKind != .class,
6068
modifierProgress.evaluate(subparser.currentToken)
6169
{
70+
hasModifier = true
6271
subparser.eat(handle)
6372
if modifierKind != .open && subparser.at(.leftParen) && modifierKind.canHaveParenthesizedArgument {
6473
// When determining whether we are at a declaration, don't consume anything in parentheses after 'open'
@@ -113,6 +122,16 @@ extension TokenConsumer {
113122
case .macroKeyword:
114123
// macro Foo ...
115124
return subparser.peek().rawTokenKind == .identifier
125+
case .pound:
126+
// Force parsing '#<identifier>' after attributes as a macro expansion decl.
127+
if hasAttribute || hasModifier {
128+
return true
129+
}
130+
131+
// Otherwise, parse it as a expression.
132+
// FIXME: C++ parser returns true if this is a top-level non-"script" files.
133+
// But we don't have "is library" flag.
134+
return false
116135
case .some(_):
117136
// All other decl start keywords unconditonally start a decl.
118137
return true
@@ -203,10 +222,6 @@ extension Parser {
203222
return .decls(RawMemberDeclListSyntax(elements: elements, arena: parser.arena))
204223
}
205224
return RawDeclSyntax(directive)
206-
case (.pound, _)?:
207-
// FIXME: If we can have attributes for macro expansions, handle this
208-
// via DeclarationStart.
209-
return RawDeclSyntax(self.parseMacroExpansionDeclaration())
210225
case nil:
211226
break
212227
}
@@ -258,6 +273,8 @@ extension Parser {
258273
return RawDeclSyntax(self.parseNominalTypeDeclaration(for: RawActorDeclSyntax.self, attrs: attrs, introucerHandle: handle))
259274
case (.macroKeyword, let handle)?:
260275
return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle))
276+
case (.pound, let handle)?:
277+
return RawDeclSyntax(self.parseMacroExpansionDeclaration(attrs, handle))
261278
case nil:
262279
if inMemberDeclList {
263280
let isProbablyVarDecl = self.at(.identifier, .wildcard) && self.peek().rawTokenKind.is(.colon, .equal, .comma)
@@ -2011,9 +2028,30 @@ extension Parser {
20112028
/// =======
20122029
///
20132030
/// macro-expansion-declaration → '#' identifier expr-call-suffix?
2014-
mutating func parseMacroExpansionDeclaration() -> RawMacroExpansionDeclSyntax {
2015-
let poundKeyword = self.consumeAnyToken()
2016-
let (unexpectedBeforeMacro, macro) = self.expectIdentifier()
2031+
mutating func parseMacroExpansionDeclaration(
2032+
_ attrs: DeclAttributes,
2033+
_ handle: RecoveryConsumptionHandle
2034+
) -> RawMacroExpansionDeclSyntax {
2035+
2036+
let (unexpectedBeforePound, poundKeyword) = self.eat(handle)
2037+
// Don't allow space between '#' and the macro name.
2038+
if poundKeyword.trailingTriviaByteLength != 0 || self.currentToken.leadingTriviaByteLength != 0 {
2039+
return RawMacroExpansionDeclSyntax(
2040+
attributes: attrs.attributes,
2041+
modifiers: attrs.modifiers,
2042+
unexpectedBeforePound,
2043+
poundToken: poundKeyword,
2044+
macro: self.missingToken(.identifier),
2045+
genericArguments: nil,
2046+
leftParen: nil,
2047+
argumentList: .init(elements: [], arena: self.arena),
2048+
rightParen: nil,
2049+
trailingClosure: nil,
2050+
additionalTrailingClosures: nil,
2051+
arena: self.arena
2052+
)
2053+
}
2054+
let (unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
20172055

20182056
// Parse the optional generic argument list.
20192057
let generics: RawGenericArgumentClauseSyntax?
@@ -2051,6 +2089,9 @@ extension Parser {
20512089
}
20522090

20532091
return RawMacroExpansionDeclSyntax(
2092+
attributes: attrs.attributes,
2093+
modifiers: attrs.modifiers,
2094+
unexpectedBeforePound,
20542095
poundToken: poundKeyword,
20552096
unexpectedBeforeMacro,
20562097
macro: macro,

Sources/SwiftParser/Expressions.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,8 +1346,21 @@ extension Parser {
13461346
pattern: PatternContext,
13471347
flavor: ExprFlavor
13481348
) -> RawMacroExpansionExprSyntax {
1349+
if !atStartOfFreestandingMacroExpansion() {
1350+
return RawMacroExpansionExprSyntax(
1351+
poundToken: self.consumeAnyToken(),
1352+
macro: self.missingToken(.identifier),
1353+
genericArguments: nil,
1354+
leftParen: nil,
1355+
argumentList: .init(elements: [], arena: self.arena),
1356+
rightParen: nil,
1357+
trailingClosure: nil,
1358+
additionalTrailingClosures: nil,
1359+
arena: self.arena
1360+
)
1361+
}
13491362
let poundKeyword = self.consumeAnyToken()
1350-
let (unexpectedBeforeMacro, macro) = self.expectIdentifier()
1363+
let (unexpectedBeforeMacro, macro) = self.expectIdentifier(keywordRecovery: true)
13511364

13521365
// Parse the optional generic argument list.
13531366
let generics: RawGenericArgumentClauseSyntax?

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ enum DeclarationStart: TokenSpecSet {
248248
case typealiasKeyword
249249
case varKeyword
250250
case inoutKeyword
251+
case pound
251252

252253
init?(lexeme: Lexer.Lexeme) {
253254
switch PrepareForKeywordMatch(lexeme) {
@@ -271,6 +272,7 @@ enum DeclarationStart: TokenSpecSet {
271272
case TokenSpec(.typealias): self = .typealiasKeyword
272273
case TokenSpec(.var): self = .varKeyword
273274
case TokenSpec(.inout): self = .inoutKeyword
275+
case TokenSpec(.pound): self = .pound
274276
default: return nil
275277
}
276278
}
@@ -297,6 +299,7 @@ enum DeclarationStart: TokenSpecSet {
297299
case .typealiasKeyword: return .keyword(.typealias)
298300
case .varKeyword: return .keyword(.var)
299301
case .inoutKeyword: return TokenSpec(.inout, recoveryPrecedence: .declKeyword)
302+
case .pound: return TokenSpec(.pound, recoveryPrecedence: .openingPoundIf)
300303
}
301304
}
302305
}
@@ -372,20 +375,17 @@ enum OperatorLike: TokenSpecSet {
372375

373376
enum PoundDeclarationStart: TokenSpecSet {
374377
case poundIfKeyword
375-
case pound
376378

377379
init?(lexeme: Lexer.Lexeme) {
378380
switch lexeme.rawTokenKind {
379381
case .poundIfKeyword: self = .poundIfKeyword
380-
case .pound: self = .pound
381382
default: return nil
382383
}
383384
}
384385

385386
var spec: TokenSpec {
386387
switch self {
387388
case .poundIfKeyword: return .poundIfKeyword
388-
case .pound: return .pound
389389
}
390390
}
391391
}

Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? {
236236
return "macro definition"
237237
case \MacroDeclSyntax.genericWhereClause:
238238
return "generic where clause"
239+
case \MacroExpansionDeclSyntax.attributes:
240+
return "attributes"
241+
case \MacroExpansionDeclSyntax.modifiers:
242+
return "modifiers"
239243
case \MemberAccessExprSyntax.base:
240244
return "base"
241245
case \MemberAccessExprSyntax.name:

Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,8 +1955,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? {
19551955
return "genericWhereClause"
19561956
case \MacroDeclSyntax.unexpectedAfterGenericWhereClause:
19571957
return "unexpectedAfterGenericWhereClause"
1958-
case \MacroExpansionDeclSyntax.unexpectedBeforePoundToken:
1959-
return "unexpectedBeforePoundToken"
1958+
case \MacroExpansionDeclSyntax.unexpectedBeforeAttributes:
1959+
return "unexpectedBeforeAttributes"
1960+
case \MacroExpansionDeclSyntax.attributes:
1961+
return "attributes"
1962+
case \MacroExpansionDeclSyntax.unexpectedBetweenAttributesAndModifiers:
1963+
return "unexpectedBetweenAttributesAndModifiers"
1964+
case \MacroExpansionDeclSyntax.modifiers:
1965+
return "modifiers"
1966+
case \MacroExpansionDeclSyntax.unexpectedBetweenModifiersAndPoundToken:
1967+
return "unexpectedBetweenModifiersAndPoundToken"
19601968
case \MacroExpansionDeclSyntax.poundToken:
19611969
return "poundToken"
19621970
case \MacroExpansionDeclSyntax.unexpectedBetweenPoundTokenAndMacro:

0 commit comments

Comments
 (0)