Skip to content

Commit c335d65

Browse files
committed
Extract header nodes from DeclGroups
This also involves changing Child.Refactoring to support a new kind of change: “extracted”, in which a group of adjacent children are moved into a new child node. Future commits will introduce clients that use the new *DeclHeaderSyntax nodes directly.
1 parent 2c57e11 commit c335d65

36 files changed

+4372
-1230
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 281 additions & 98 deletions
Large diffs are not rendered by default.

CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
2828
case accessorEffectSpecifiers
2929
case accessorParameters
3030
case actorDecl
31+
case actorDeclHeader
3132
case arrayElement
3233
case arrayElementList
3334
case arrayExpr
@@ -54,6 +55,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
5455
case catchItem
5556
case catchItemList
5657
case classDecl
58+
case classDeclHeader
5759
case classRestrictionType
5860
case closureCapture
5961
case closureCaptureClause
@@ -121,13 +123,15 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
121123
case enumCaseParameterClause
122124
case enumCaseParameterList
123125
case enumDecl
126+
case enumDeclHeader
124127
case exposeAttributeArguments
125128
case expr
126129
case expressionPattern
127130
case expressionSegment
128131
case expressionStmt
129132
case exprList
130133
case extensionDecl
134+
case extensionDeclHeader
131135
case fallThroughStmt
132136
case floatLiteralExpr
133137
case forceUnwrapExpr
@@ -243,6 +247,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
243247
case primaryAssociatedTypeClause
244248
case primaryAssociatedTypeList
245249
case protocolDecl
250+
case protocolDeclHeader
246251
case regexLiteralExpr
247252
case repeatStmt
248253
case returnClause
@@ -262,6 +267,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
262267
case stringLiteralSegmentList
263268
case stringSegment
264269
case structDecl
270+
case structDeclHeader
265271
case subscriptCallExpr
266272
case subscriptDecl
267273
case superExpr

CodeGeneration/Sources/SyntaxSupport/Traits.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,18 @@ public let TRAITS: [Trait] = [
5353
traitName: "DeclGroup",
5454
baseKind: .decl,
5555
children: [
56-
Child(name: "attributes", kind: .node(kind: .attributeList)),
57-
Child(name: "modifiers", kind: .node(kind: .declModifierList)),
5856
Child(
59-
name: "introducer",
60-
kind: .token(choices: [
61-
.keyword(.actor), .keyword(.class), .keyword(.enum), .keyword(.extension), .keyword(.protocol),
62-
.keyword(.struct),
63-
]),
64-
documentation: "The token that introduces this declaration, eg. `class` for a class declaration."
65-
),
66-
Child(name: "inheritanceClause", kind: .node(kind: .inheritanceClause), isOptional: true),
67-
Child(
68-
name: "genericWhereClause",
69-
kind: .node(kind: .genericWhereClause),
57+
name: "header",
58+
kind: .node(kind: .declGroupHeader),
7059
documentation:
71-
"A `where` clause that places additional constraints on generic parameters like `where Element: Hashable`.",
72-
isOptional: true
60+
"The header of the declaration."
7361
),
7462
Child(name: "memberBlock", kind: .node(kind: .memberBlock)),
63+
],
64+
childHistory: [
65+
[
66+
"header": .extracted
67+
]
7568
]
7669
),
7770
Trait(
@@ -116,6 +109,13 @@ public let TRAITS: [Trait] = [
116109
Child(name: "name", kind: .token(choices: [.token(.identifier)]))
117110
]
118111
),
112+
Trait(
113+
traitName: "NamedDeclHeader",
114+
baseKind: .declGroupHeader,
115+
children: [
116+
Child(name: "name", kind: .token(choices: [.token(.identifier)]))
117+
]
118+
),
119119
Trait(
120120
traitName: "MissingNode",
121121
documentation: """

CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ class ValidateSyntaxNodes: XCTestCase {
736736
ValidationFailure(node: .attributedType, message: "child 'baseType' should not end with 'Type'"),
737737
ValidationFailure(node: .conformanceRequirement, message: "child 'leftType' should not end with 'Type'"),
738738
ValidationFailure(node: .conformanceRequirement, message: "child 'rightType' should not end with 'Type'"),
739-
ValidationFailure(node: .extensionDecl, message: "child 'extendedType' should not end with 'Type'"),
739+
ValidationFailure(node: .extensionDeclHeader, message: "child 'extendedType' should not end with 'Type'"),
740740
ValidationFailure(node: .genericParameter, message: "child 'inheritedType' should not end with 'Type'"),
741741
ValidationFailure(
742742
node: .implicitlyUnwrappedOptionalType,

Sources/SwiftParser/Declarations.swift

Lines changed: 167 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -226,32 +226,21 @@ extension Parser {
226226
}
227227

228228
switch recoveryResult {
229+
case (.group(let introducer), let handle)?:
230+
let (header, shouldContinueParsing) = parseHeaderForDeclarationGroup(
231+
attrs: attrs,
232+
introducer: introducer,
233+
introducerHandle: handle
234+
)
235+
return parseDeclarationGroup(for: header, shouldParseMemberBlock: shouldContinueParsing)
229236
case (.simple(.import), let handle)?:
230237
return RawDeclSyntax(self.parseImportDeclaration(attrs, handle))
231-
case (.group(.class), let handle)?:
232-
return RawDeclSyntax(
233-
self.parseNominalTypeDeclaration(for: RawClassDeclSyntax.self, attrs: attrs, introucerHandle: handle)
234-
)
235-
case (.group(.enum), let handle)?:
236-
return RawDeclSyntax(
237-
self.parseNominalTypeDeclaration(for: RawEnumDeclSyntax.self, attrs: attrs, introucerHandle: handle)
238-
)
239238
case (.simple(.case), let handle)?:
240239
return RawDeclSyntax(self.parseEnumCaseDeclaration(attrs, handle))
241-
case (.group(.struct), let handle)?:
242-
return RawDeclSyntax(
243-
self.parseNominalTypeDeclaration(for: RawStructDeclSyntax.self, attrs: attrs, introucerHandle: handle)
244-
)
245-
case (.group(.protocol), let handle)?:
246-
return RawDeclSyntax(
247-
self.parseNominalTypeDeclaration(for: RawProtocolDeclSyntax.self, attrs: attrs, introucerHandle: handle)
248-
)
249240
case (.simple(.associatedtype), let handle)?:
250241
return RawDeclSyntax(self.parseAssociatedTypeDeclaration(attrs, handle))
251242
case (.simple(.typealias), let handle)?:
252243
return RawDeclSyntax(self.parseTypealiasDeclaration(attrs, handle))
253-
case (.group(.extension), let handle)?:
254-
return RawDeclSyntax(self.parseExtensionDeclaration(attrs, handle))
255244
case (.simple(.func), let handle)?:
256245
return RawDeclSyntax(self.parseFuncDeclaration(attrs, handle))
257246
case (.simple(.subscript), let handle)?:
@@ -264,10 +253,6 @@ extension Parser {
264253
return RawDeclSyntax(self.parseOperatorDeclaration(attrs, handle))
265254
case (.simple(.precedencegroup), let handle)?:
266255
return RawDeclSyntax(self.parsePrecedenceGroupDeclaration(attrs, handle))
267-
case (.group(.actor), let handle)?:
268-
return RawDeclSyntax(
269-
self.parseNominalTypeDeclaration(for: RawActorDeclSyntax.self, attrs: attrs, introucerHandle: handle)
270-
)
271256
case (.simple(.macro), let handle)?:
272257
return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle))
273258
case (.simple(.pound), let handle)?:
@@ -418,7 +403,56 @@ extension Parser {
418403
introducer: DeclGroupHeaderSyntax.IntroducerOptions,
419404
introducerHandle: RecoveryConsumptionHandle
420405
) -> (RawDeclGroupHeaderSyntax, shouldContinueParsing: Bool) {
421-
fatalError("not yet implemented")
406+
func eraseToRawDeclGroupHeaderSyntax(
407+
_ result: (some RawDeclGroupHeaderSyntaxNodeProtocol, Bool)
408+
) -> (RawDeclGroupHeaderSyntax, shouldContinueParsing: Bool) {
409+
return (RawDeclGroupHeaderSyntax(result.0), result.1)
410+
}
411+
412+
switch introducer {
413+
case .class:
414+
return eraseToRawDeclGroupHeaderSyntax(
415+
self.parseNominalTypeDeclarationHeader(
416+
for: RawClassDeclHeaderSyntax.self,
417+
attrs: attrs,
418+
introducerHandle: introducerHandle
419+
)
420+
)
421+
case .enum:
422+
return eraseToRawDeclGroupHeaderSyntax(
423+
self.parseNominalTypeDeclarationHeader(
424+
for: RawEnumDeclHeaderSyntax.self,
425+
attrs: attrs,
426+
introducerHandle: introducerHandle
427+
)
428+
)
429+
case .struct:
430+
return eraseToRawDeclGroupHeaderSyntax(
431+
self.parseNominalTypeDeclarationHeader(
432+
for: RawStructDeclHeaderSyntax.self,
433+
attrs: attrs,
434+
introducerHandle: introducerHandle
435+
)
436+
)
437+
case .protocol:
438+
return eraseToRawDeclGroupHeaderSyntax(
439+
self.parseNominalTypeDeclarationHeader(
440+
for: RawProtocolDeclHeaderSyntax.self,
441+
attrs: attrs,
442+
introducerHandle: introducerHandle
443+
)
444+
)
445+
case .extension:
446+
return (RawDeclGroupHeaderSyntax(self.parseExtensionDeclarationHeader(attrs, introducerHandle)), true)
447+
case .actor:
448+
return eraseToRawDeclGroupHeaderSyntax(
449+
self.parseNominalTypeDeclarationHeader(
450+
for: RawActorDeclHeaderSyntax.self,
451+
attrs: attrs,
452+
introducerHandle: introducerHandle
453+
)
454+
)
455+
}
422456
}
423457

424458
/// Returns `true` if it looks like the parser is positioned at a function declaration that’s missing the `func` keyword.
@@ -483,12 +517,121 @@ extension Parser {
483517
}
484518
}
485519

520+
protocol DeclarationGroupHeaderTrait {
521+
var introducer: RawTokenSyntax { get }
522+
523+
associatedtype Declaration: RawDeclSyntaxNodeProtocol
524+
525+
func makeDeclaration(
526+
memberBlock: RawMemberBlockSyntax,
527+
arena: __shared SyntaxArena
528+
) -> Declaration
529+
}
530+
531+
extension RawExtensionDeclHeaderSyntax: DeclarationGroupHeaderTrait {
532+
var introducer: RawTokenSyntax {
533+
return self.extensionKeyword
534+
}
535+
536+
func makeDeclaration(memberBlock: RawMemberBlockSyntax, arena: SyntaxArena) -> RawExtensionDeclSyntax {
537+
RawExtensionDeclSyntax(extensionHeader: self, memberBlock: memberBlock, arena: arena)
538+
}
539+
}
540+
541+
extension RawMissingDeclHeaderSyntax: DeclarationGroupHeaderTrait {
542+
var introducer: RawTokenSyntax {
543+
return self.placeholder
544+
}
545+
546+
func makeDeclaration(memberBlock: RawMemberBlockSyntax, arena: SyntaxArena) -> RawMissingDeclSyntax {
547+
RawMissingDeclSyntax(
548+
self.unexpectedBeforeAttributes,
549+
attributes: self.attributes,
550+
self.unexpectedBetweenAttributesAndModifiers,
551+
modifiers: self.modifiers,
552+
self.unexpectedBetweenModifiersAndPlaceholder,
553+
placeholder: self.placeholder,
554+
RawUnexpectedNodesSyntax(
555+
combining: [
556+
self.unexpectedBetweenPlaceholderAndInheritanceClause,
557+
RawUnexpectedNodesSyntax([self.inheritanceClause], arena: arena),
558+
self.unexpectedBetweenInheritanceClauseAndGenericWhereClause,
559+
RawUnexpectedNodesSyntax([self.genericWhereClause], arena: arena),
560+
self.unexpectedAfterGenericWhereClause,
561+
],
562+
RawUnexpectedNodesSyntax([memberBlock], arena: arena)!,
563+
arena: arena
564+
),
565+
arena: arena
566+
)
567+
}
568+
}
569+
570+
extension RawDeclGroupHeaderSyntax: DeclarationGroupHeaderTrait {
571+
private typealias ConcreteExistentialSelf = RawSyntaxNodeProtocol & DeclarationGroupHeaderTrait
572+
private var asConcreteExistentialSelf: any ConcreteExistentialSelf {
573+
let subtypes: [any ConcreteExistentialSelf.Type] = [
574+
RawExtensionDeclHeaderSyntax.self,
575+
RawProtocolDeclHeaderSyntax.self,
576+
RawClassDeclHeaderSyntax.self,
577+
RawActorDeclHeaderSyntax.self,
578+
RawStructDeclHeaderSyntax.self,
579+
RawEnumDeclHeaderSyntax.self,
580+
RawMissingDeclHeaderSyntax.self,
581+
]
582+
583+
for subtype in subtypes {
584+
if let result = subtype.init(self) {
585+
return result
586+
}
587+
}
588+
589+
fatalError("Node \(self) does not have a known subtype")
590+
}
591+
592+
func makeDeclaration(memberBlock: RawMemberBlockSyntax, arena: SyntaxArena) -> RawDeclSyntax {
593+
return RawDeclSyntax(asConcreteExistentialSelf.makeDeclaration(memberBlock: memberBlock, arena: arena))
594+
}
595+
596+
var introducer: RawTokenSyntax {
597+
return asConcreteExistentialSelf.introducer
598+
}
599+
}
600+
486601
extension Parser {
602+
/// Parse a declaration group (class, struct, enum, actor, protocol, extension) body given its header.
603+
mutating func parseDeclarationGroup<T>(
604+
for header: T,
605+
shouldParseMemberBlock: Bool = true
606+
) -> T.Declaration where T: DeclarationGroupHeaderTrait {
607+
let memberBlock =
608+
if shouldParseMemberBlock {
609+
self.parseMemberBlock(introducer: header.introducer)
610+
} else {
611+
RawMemberBlockSyntax(
612+
leftBrace: missingToken(.leftBrace),
613+
members: RawMemberBlockItemListSyntax(elements: [], arena: self.arena),
614+
rightBrace: missingToken(.rightBrace),
615+
arena: self.arena
616+
)
617+
}
618+
return header.makeDeclaration(memberBlock: memberBlock, arena: self.arena)
619+
}
620+
487621
/// Parse an extension declaration.
488622
mutating func parseExtensionDeclaration(
489623
_ attrs: DeclAttributes,
490624
_ handle: RecoveryConsumptionHandle
491625
) -> RawExtensionDeclSyntax {
626+
let header = parseExtensionDeclarationHeader(attrs, handle)
627+
return parseDeclarationGroup(for: header)
628+
}
629+
630+
/// Parse the header of an extension declaration.
631+
mutating func parseExtensionDeclarationHeader(
632+
_ attrs: DeclAttributes,
633+
_ handle: RecoveryConsumptionHandle
634+
) -> RawExtensionDeclHeaderSyntax {
492635
let (unexpectedBeforeExtensionKeyword, extensionKeyword) = self.eat(handle)
493636
let type = self.parseType()
494637

@@ -505,16 +648,14 @@ extension Parser {
505648
} else {
506649
whereClause = nil
507650
}
508-
let memberBlock = self.parseMemberBlock(introducer: extensionKeyword)
509-
return RawExtensionDeclSyntax(
651+
return RawExtensionDeclHeaderSyntax(
510652
attributes: attrs.attributes,
511653
modifiers: attrs.modifiers,
512654
unexpectedBeforeExtensionKeyword,
513655
extensionKeyword: extensionKeyword,
514656
extendedType: type,
515657
inheritanceClause: inheritance,
516658
genericWhereClause: whereClause,
517-
memberBlock: memberBlock,
518659
arena: self.arena
519660
)
520661
}

0 commit comments

Comments
 (0)