Skip to content

Commit d7dfd94

Browse files
committed
Parse an extended type as part of a nominal type declaration's name.
These are parser changes necessary for automatic extension synthesis that would allow users to write ```swift struct Outer.Inner {} ``` instead of ```swift extension Outer { struct Inner {} } ```
1 parent fd232f9 commit d7dfd94

25 files changed

+1349
-402
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

+66
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@ public let DECL_NODES: [Node] = [
206206
kind: .token(choices: [.keyword(.actor)]),
207207
documentation: "The `actor` keyword."
208208
),
209+
Child(
210+
name: "extendedType",
211+
kind: .node(kind: .type),
212+
documentation: "The `type` in which this actor is nested.",
213+
isOptional: true
214+
),
215+
Child(
216+
name: "period",
217+
kind: .token(choices: [.token(.period)]),
218+
isOptional: true
219+
),
209220
Child(
210221
name: "name",
211222
kind: .token(choices: [.token(.identifier)]),
@@ -386,6 +397,17 @@ public let DECL_NODES: [Node] = [
386397
kind: .token(choices: [.keyword(.class)]),
387398
documentation: "The `class` keyword for this declaration."
388399
),
400+
Child(
401+
name: "extendedType",
402+
kind: .node(kind: .type),
403+
documentation: "The `type` in which this class is nested.",
404+
isOptional: true
405+
),
406+
Child(
407+
name: "period",
408+
kind: .token(choices: [.token(.period)]),
409+
isOptional: true
410+
),
389411
Child(
390412
name: "name",
391413
kind: .token(choices: [.token(.identifier)]),
@@ -830,6 +852,17 @@ public let DECL_NODES: [Node] = [
830852
kind: .token(choices: [.keyword(.enum)]),
831853
documentation: "The `enum` keyword for this declaration."
832854
),
855+
Child(
856+
name: "extendedType",
857+
kind: .node(kind: .type),
858+
documentation: "The `type` in which this enum declaration is nested.",
859+
isOptional: true
860+
),
861+
Child(
862+
name: "period",
863+
kind: .token(choices: [.token(.period)]),
864+
isOptional: true
865+
),
833866
Child(
834867
name: "name",
835868
kind: .token(choices: [.token(.identifier)]),
@@ -2085,6 +2118,17 @@ public let DECL_NODES: [Node] = [
20852118
kind: .token(choices: [.keyword(.protocol)]),
20862119
documentation: "The `protocol` keyword for this declaration."
20872120
),
2121+
Child(
2122+
name: "extendedType",
2123+
kind: .node(kind: .type),
2124+
documentation: "The `type` in which this protocol is nested.",
2125+
isOptional: true
2126+
),
2127+
Child(
2128+
name: "period",
2129+
kind: .token(choices: [.token(.period)]),
2130+
isOptional: true
2131+
),
20882132
Child(
20892133
name: "name",
20902134
kind: .token(choices: [.token(.identifier)]),
@@ -2265,6 +2309,17 @@ public let DECL_NODES: [Node] = [
22652309
kind: .token(choices: [.keyword(.struct)]),
22662310
documentation: "The `struct` keyword for this declaration."
22672311
),
2312+
Child(
2313+
name: "extendedType",
2314+
kind: .node(kind: .type),
2315+
documentation: "The `type` in which this struct is nested.",
2316+
isOptional: true
2317+
),
2318+
Child(
2319+
name: "period",
2320+
kind: .token(choices: [.token(.period)]),
2321+
isOptional: true
2322+
),
22682323
Child(
22692324
name: "name",
22702325
kind: .token(choices: [.token(.identifier)]),
@@ -2432,6 +2487,17 @@ public let DECL_NODES: [Node] = [
24322487
name: "typealiasKeyword",
24332488
kind: .token(choices: [.keyword(.typealias)])
24342489
),
2490+
Child(
2491+
name: "extendedType",
2492+
kind: .node(kind: .type),
2493+
documentation: "The `type` in which this type alias is nested.",
2494+
isOptional: true
2495+
),
2496+
Child(
2497+
name: "period",
2498+
kind: .token(choices: [.token(.period)]),
2499+
isOptional: true
2500+
),
24352501
Child(
24362502
name: "name",
24372503
kind: .token(choices: [.token(.identifier)])

Sources/SwiftParser/Declarations.swift

+12
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,15 @@ extension Parser {
16601660
_ handle: RecoveryConsumptionHandle
16611661
) -> RawTypeAliasDeclSyntax {
16621662
let (unexpectedBeforeTypealiasKeyword, typealiasKeyword) = self.eat(handle)
1663+
1664+
var extendedType: RawTypeSyntax? = nil
1665+
var unexpectedBeforePeriod: RawUnexpectedNodesSyntax? = nil
1666+
var period: RawTokenSyntax? = nil
1667+
if self.lookahead().canParseExtendedTypeForNominalTypeDecl() {
1668+
extendedType = parseSimpleType(parsingContext: .nominalTypeDeclExtendedName)
1669+
(unexpectedBeforePeriod, period) = self.expect(.period)
1670+
}
1671+
16631672
let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
16641673

16651674
// Parse a generic parameter list if it is present.
@@ -1700,6 +1709,9 @@ extension Parser {
17001709
modifiers: attrs.modifiers,
17011710
unexpectedBeforeTypealiasKeyword,
17021711
typealiasKeyword: typealiasKeyword,
1712+
extendedType: extendedType,
1713+
unexpectedBeforePeriod,
1714+
period: period,
17031715
unexpectedBeforeName,
17041716
name: name,
17051717
genericParameterClause: generics,

Sources/SwiftParser/Expressions.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ extension Parser {
10271027
// the token is an operator starts with '.', or the following token is '['.
10281028
let rootType: RawTypeSyntax?
10291029
if !self.at(prefix: ".") {
1030-
rootType = self.parseSimpleType(allowMemberTypes: false)
1030+
rootType = self.parseSimpleType(parsingContext: .keyPathRoot)
10311031
} else {
10321032
rootType = nil
10331033
}

Sources/SwiftParser/Names.swift

+8
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,14 @@ extension Parser.Lookahead {
271271
}
272272
return lookahead.at(prefix: ".")
273273
}
274+
275+
func canParseExtendedTypeForNominalTypeDecl() -> Bool {
276+
var lookahead = self.lookahead()
277+
guard lookahead.canParseSimpleType(parsingContext: .nominalTypeDeclExtendedName) else {
278+
return false
279+
}
280+
return lookahead.at(prefix: ".")
281+
}
274282
}
275283

276284
extension Parser.Lookahead {

Sources/SwiftParser/Nominals.swift

+48
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ protocol NominalTypeDeclarationTrait {
2424
modifiers: RawDeclModifierListSyntax,
2525
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
2626
introducerKeyword: RawTokenSyntax,
27+
extendedType: RawTypeSyntax?,
28+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
29+
period: RawTokenSyntax?,
2730
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
2831
name: RawTokenSyntax,
2932
primaryOrGenerics: PrimaryOrGenerics?,
@@ -42,6 +45,9 @@ extension RawProtocolDeclSyntax: NominalTypeDeclarationTrait {
4245
modifiers: RawDeclModifierListSyntax,
4346
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
4447
introducerKeyword: RawTokenSyntax,
48+
extendedType: RawTypeSyntax?,
49+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
50+
period: RawTokenSyntax?,
4551
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
4652
name: RawTokenSyntax,
4753
primaryOrGenerics: RawPrimaryAssociatedTypeClauseSyntax?,
@@ -55,6 +61,9 @@ extension RawProtocolDeclSyntax: NominalTypeDeclarationTrait {
5561
modifiers: modifiers,
5662
unexpectedBeforeIntroducerKeyword,
5763
protocolKeyword: introducerKeyword,
64+
extendedType: extendedType,
65+
unexpectedBeforePeriod,
66+
period: period,
5867
unexpectedBeforeIdentifier,
5968
name: name,
6069
primaryAssociatedTypeClause: primaryOrGenerics,
@@ -76,6 +85,9 @@ extension RawClassDeclSyntax: NominalTypeDeclarationTrait {
7685
modifiers: RawDeclModifierListSyntax,
7786
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
7887
introducerKeyword: RawTokenSyntax,
88+
extendedType: RawTypeSyntax?,
89+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
90+
period: RawTokenSyntax?,
7991
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
8092
name: RawTokenSyntax,
8193
primaryOrGenerics: RawGenericParameterClauseSyntax?,
@@ -89,6 +101,9 @@ extension RawClassDeclSyntax: NominalTypeDeclarationTrait {
89101
modifiers: modifiers,
90102
unexpectedBeforeIntroducerKeyword,
91103
classKeyword: introducerKeyword,
104+
extendedType: extendedType,
105+
unexpectedBeforePeriod,
106+
period: period,
92107
unexpectedBeforeIdentifier,
93108
name: name,
94109
genericParameterClause: primaryOrGenerics,
@@ -110,6 +125,9 @@ extension RawActorDeclSyntax: NominalTypeDeclarationTrait {
110125
modifiers: RawDeclModifierListSyntax,
111126
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
112127
introducerKeyword: RawTokenSyntax,
128+
extendedType: RawTypeSyntax?,
129+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
130+
period: RawTokenSyntax?,
113131
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
114132
name: RawTokenSyntax,
115133
primaryOrGenerics: RawGenericParameterClauseSyntax?,
@@ -123,6 +141,9 @@ extension RawActorDeclSyntax: NominalTypeDeclarationTrait {
123141
modifiers: modifiers,
124142
unexpectedBeforeIntroducerKeyword,
125143
actorKeyword: introducerKeyword,
144+
extendedType: extendedType,
145+
unexpectedBeforePeriod,
146+
period: period,
126147
unexpectedBeforeIdentifier,
127148
name: name,
128149
genericParameterClause: primaryOrGenerics,
@@ -144,6 +165,9 @@ extension RawStructDeclSyntax: NominalTypeDeclarationTrait {
144165
modifiers: RawDeclModifierListSyntax,
145166
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
146167
introducerKeyword: RawTokenSyntax,
168+
extendedType: RawTypeSyntax?,
169+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
170+
period: RawTokenSyntax?,
147171
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
148172
name: RawTokenSyntax,
149173
primaryOrGenerics: RawGenericParameterClauseSyntax?,
@@ -157,6 +181,9 @@ extension RawStructDeclSyntax: NominalTypeDeclarationTrait {
157181
modifiers: modifiers,
158182
unexpectedBeforeIntroducerKeyword,
159183
structKeyword: introducerKeyword,
184+
extendedType: extendedType,
185+
unexpectedBeforePeriod,
186+
period: period,
160187
unexpectedBeforeIdentifier,
161188
name: name,
162189
genericParameterClause: primaryOrGenerics,
@@ -178,6 +205,9 @@ extension RawEnumDeclSyntax: NominalTypeDeclarationTrait {
178205
modifiers: RawDeclModifierListSyntax,
179206
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
180207
introducerKeyword: RawTokenSyntax,
208+
extendedType: RawTypeSyntax?,
209+
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
210+
period: RawTokenSyntax?,
181211
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
182212
name: RawTokenSyntax,
183213
primaryOrGenerics: RawGenericParameterClauseSyntax?,
@@ -191,6 +221,9 @@ extension RawEnumDeclSyntax: NominalTypeDeclarationTrait {
191221
modifiers: modifiers,
192222
unexpectedBeforeIntroducerKeyword,
193223
enumKeyword: introducerKeyword,
224+
extendedType: extendedType,
225+
unexpectedBeforePeriod,
226+
period: period,
194227
unexpectedBeforeIdentifier,
195228
name: name,
196229
genericParameterClause: primaryOrGenerics,
@@ -214,13 +247,25 @@ extension Parser {
214247
introucerHandle: RecoveryConsumptionHandle
215248
) -> T where T: NominalTypeDeclarationTrait {
216249
let (unexpectedBeforeIntroducerKeyword, introducerKeyword) = self.eat(introucerHandle)
250+
251+
var extendedType: RawTypeSyntax? = nil
252+
var unexpectedBeforePeriod: RawUnexpectedNodesSyntax? = nil
253+
var period: RawTokenSyntax? = nil
254+
if self.lookahead().canParseExtendedTypeForNominalTypeDecl() {
255+
extendedType = parseSimpleType(parsingContext: .nominalTypeDeclExtendedName)
256+
(unexpectedBeforePeriod, period) = self.expect(.period)
257+
}
258+
217259
let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
218260
if unexpectedBeforeName == nil && name.isMissing && self.atStartOfLine {
219261
return T.init(
220262
attributes: attrs.attributes,
221263
modifiers: attrs.modifiers,
222264
unexpectedBeforeIntroducerKeyword,
223265
introducerKeyword: introducerKeyword,
266+
extendedType: extendedType,
267+
unexpectedBeforePeriod,
268+
period: period,
224269
unexpectedBeforeName,
225270
name: name,
226271
primaryOrGenerics: nil,
@@ -264,6 +309,9 @@ extension Parser {
264309
modifiers: attrs.modifiers,
265310
unexpectedBeforeIntroducerKeyword,
266311
introducerKeyword: introducerKeyword,
312+
extendedType: extendedType,
313+
unexpectedBeforePeriod,
314+
period: period,
267315
unexpectedBeforeName,
268316
name: name,
269317
primaryOrGenerics: primaryOrGenerics,

Sources/SwiftParser/Types.swift

+32-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax
1717
#endif
1818

19+
enum SimpleTypeParsingContext {
20+
case `default`
21+
case keyPathRoot
22+
case attributeName
23+
case nominalTypeDeclExtendedName
24+
}
25+
1926
extension Parser {
2027
/// Parse a type.
2128
mutating func parseType(misplacedSpecifiers: [RawTokenSyntax] = []) -> RawTypeSyntax {
@@ -187,12 +194,11 @@ extension Parser {
187194

188195
/// Parse the subset of types that we allow in attribute names.
189196
mutating func parseAttributeName() -> RawTypeSyntax {
190-
return parseSimpleType(forAttributeName: true)
197+
return parseSimpleType(parsingContext: .attributeName)
191198
}
192199

193200
mutating func parseSimpleType(
194-
allowMemberTypes: Bool = true,
195-
forAttributeName: Bool = false
201+
parsingContext: SimpleTypeParsingContext = .default
196202
) -> RawTypeSyntax {
197203
enum TypeBaseStart: TokenSpecSet {
198204
case `Self`
@@ -257,9 +263,25 @@ extension Parser {
257263
return wrapInTilde(RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)))
258264
}
259265

266+
func shouldContinueAfterPeriod() -> Bool {
267+
if self.peek(isAt: .keyword(.Type), .keyword(.Protocol)) {
268+
return true
269+
}
270+
switch parsingContext {
271+
case .keyPathRoot:
272+
return false
273+
case .nominalTypeDeclExtendedName:
274+
var lookahead = self.lookahead()
275+
lookahead.eat(.period)
276+
return lookahead.canParseExtendedTypeForNominalTypeDecl()
277+
default:
278+
return true
279+
}
280+
}
281+
260282
var loopProgress = LoopProgressCondition()
261283
while self.hasProgressed(&loopProgress) {
262-
if self.at(.period) && (allowMemberTypes || self.peek(isAt: .keyword(.Type), .keyword(.Protocol))) {
284+
if self.at(.period) && shouldContinueAfterPeriod() {
263285
let (unexpectedPeriod, period, skipMemberName) = self.consumeMemberPeriod(previousNode: base)
264286
if skipMemberName {
265287
let missingIdentifier = missingToken(.identifier)
@@ -315,7 +337,7 @@ extension Parser {
315337
}
316338

317339
// Do not allow ? or ! suffixes when parsing attribute names.
318-
if forAttributeName {
340+
if parsingContext == .attributeName {
319341
break
320342
}
321343

@@ -691,7 +713,7 @@ extension Parser.Lookahead {
691713
return true
692714
}
693715

694-
mutating func canParseSimpleType() -> Bool {
716+
mutating func canParseSimpleType(parsingContext: SimpleTypeParsingContext = .default) -> Bool {
695717
switch self.currentToken {
696718
case TokenSpec(.Any):
697719
self.consumeAnyToken()
@@ -736,6 +758,10 @@ extension Parser.Lookahead {
736758
var loopProgress = LoopProgressCondition()
737759
while self.hasProgressed(&loopProgress) {
738760
if self.at(.period) {
761+
if parsingContext == .nominalTypeDeclExtendedName {
762+
return true
763+
}
764+
739765
self.consumeAnyToken()
740766
if self.at(.keyword(.Type)) || self.at(.keyword(.Protocol)) {
741767
self.consumeAnyToken()

0 commit comments

Comments
 (0)