Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Parse an extended type as part of a nominal type declaration's name. #2942

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ public let DECL_NODES: [Node] = [
kind: .token(choices: [.keyword(.actor)]),
documentation: "The `actor` keyword."
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this actor is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)]),
Expand Down Expand Up @@ -386,6 +397,17 @@ public let DECL_NODES: [Node] = [
kind: .token(choices: [.keyword(.class)]),
documentation: "The `class` keyword for this declaration."
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this class is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)]),
Expand Down Expand Up @@ -830,6 +852,17 @@ public let DECL_NODES: [Node] = [
kind: .token(choices: [.keyword(.enum)]),
documentation: "The `enum` keyword for this declaration."
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this enum declaration is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)]),
Expand Down Expand Up @@ -2085,6 +2118,17 @@ public let DECL_NODES: [Node] = [
kind: .token(choices: [.keyword(.protocol)]),
documentation: "The `protocol` keyword for this declaration."
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this protocol is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)]),
Expand Down Expand Up @@ -2265,6 +2309,17 @@ public let DECL_NODES: [Node] = [
kind: .token(choices: [.keyword(.struct)]),
documentation: "The `struct` keyword for this declaration."
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this struct is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)]),
Expand Down Expand Up @@ -2432,6 +2487,17 @@ public let DECL_NODES: [Node] = [
name: "typealiasKeyword",
kind: .token(choices: [.keyword(.typealias)])
),
Child(
name: "extendedType",
kind: .node(kind: .type),
documentation: "The `type` in which this type alias is nested.",
isOptional: true
),
Child(
name: "period",
kind: .token(choices: [.token(.period)]),
isOptional: true
),
Child(
name: "name",
kind: .token(choices: [.token(.identifier)])
Expand Down
12 changes: 12 additions & 0 deletions Sources/SwiftParser/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,15 @@ extension Parser {
_ handle: RecoveryConsumptionHandle
) -> RawTypeAliasDeclSyntax {
let (unexpectedBeforeTypealiasKeyword, typealiasKeyword) = self.eat(handle)

var extendedType: RawTypeSyntax? = nil
var unexpectedBeforePeriod: RawUnexpectedNodesSyntax? = nil
var period: RawTokenSyntax? = nil
if self.lookahead().canParseExtendedTypeForNominalTypeDecl() {
extendedType = parseSimpleType(parsingContext: .nominalTypeDeclExtendedName)
(unexpectedBeforePeriod, period) = self.expect(.period)
}

let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)

// Parse a generic parameter list if it is present.
Expand Down Expand Up @@ -1700,6 +1709,9 @@ extension Parser {
modifiers: attrs.modifiers,
unexpectedBeforeTypealiasKeyword,
typealiasKeyword: typealiasKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeName,
name: name,
genericParameterClause: generics,
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/Expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ extension Parser {
// the token is an operator starts with '.', or the following token is '['.
let rootType: RawTypeSyntax?
if !self.at(prefix: ".") {
rootType = self.parseSimpleType(allowMemberTypes: false)
rootType = self.parseSimpleType(parsingContext: .keyPathRoot)
} else {
rootType = nil
}
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftParser/Names.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ extension Parser.Lookahead {
}
return lookahead.at(prefix: ".")
}

func canParseExtendedTypeForNominalTypeDecl() -> Bool {
var lookahead = self.lookahead()
guard lookahead.canParseSimpleType(parsingContext: .nominalTypeDeclExtendedName) else {
return false
}
return lookahead.at(prefix: ".")
}
}

extension Parser.Lookahead {
Expand Down
48 changes: 48 additions & 0 deletions Sources/SwiftParser/Nominals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ protocol NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: PrimaryOrGenerics?,
Expand All @@ -42,6 +45,9 @@ extension RawProtocolDeclSyntax: NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: RawPrimaryAssociatedTypeClauseSyntax?,
Expand All @@ -55,6 +61,9 @@ extension RawProtocolDeclSyntax: NominalTypeDeclarationTrait {
modifiers: modifiers,
unexpectedBeforeIntroducerKeyword,
protocolKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeIdentifier,
name: name,
primaryAssociatedTypeClause: primaryOrGenerics,
Expand All @@ -76,6 +85,9 @@ extension RawClassDeclSyntax: NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: RawGenericParameterClauseSyntax?,
Expand All @@ -89,6 +101,9 @@ extension RawClassDeclSyntax: NominalTypeDeclarationTrait {
modifiers: modifiers,
unexpectedBeforeIntroducerKeyword,
classKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeIdentifier,
name: name,
genericParameterClause: primaryOrGenerics,
Expand All @@ -110,6 +125,9 @@ extension RawActorDeclSyntax: NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: RawGenericParameterClauseSyntax?,
Expand All @@ -123,6 +141,9 @@ extension RawActorDeclSyntax: NominalTypeDeclarationTrait {
modifiers: modifiers,
unexpectedBeforeIntroducerKeyword,
actorKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeIdentifier,
name: name,
genericParameterClause: primaryOrGenerics,
Expand All @@ -144,6 +165,9 @@ extension RawStructDeclSyntax: NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: RawGenericParameterClauseSyntax?,
Expand All @@ -157,6 +181,9 @@ extension RawStructDeclSyntax: NominalTypeDeclarationTrait {
modifiers: modifiers,
unexpectedBeforeIntroducerKeyword,
structKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeIdentifier,
name: name,
genericParameterClause: primaryOrGenerics,
Expand All @@ -178,6 +205,9 @@ extension RawEnumDeclSyntax: NominalTypeDeclarationTrait {
modifiers: RawDeclModifierListSyntax,
_ unexpectedBeforeIntroducerKeyword: RawUnexpectedNodesSyntax?,
introducerKeyword: RawTokenSyntax,
extendedType: RawTypeSyntax?,
_ unexpectedBeforePeriod: RawUnexpectedNodesSyntax?,
period: RawTokenSyntax?,
_ unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?,
name: RawTokenSyntax,
primaryOrGenerics: RawGenericParameterClauseSyntax?,
Expand All @@ -191,6 +221,9 @@ extension RawEnumDeclSyntax: NominalTypeDeclarationTrait {
modifiers: modifiers,
unexpectedBeforeIntroducerKeyword,
enumKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeIdentifier,
name: name,
genericParameterClause: primaryOrGenerics,
Expand All @@ -214,13 +247,25 @@ extension Parser {
introucerHandle: RecoveryConsumptionHandle
) -> T where T: NominalTypeDeclarationTrait {
let (unexpectedBeforeIntroducerKeyword, introducerKeyword) = self.eat(introucerHandle)

var extendedType: RawTypeSyntax? = nil
var unexpectedBeforePeriod: RawUnexpectedNodesSyntax? = nil
var period: RawTokenSyntax? = nil
if self.lookahead().canParseExtendedTypeForNominalTypeDecl() {
extendedType = parseSimpleType(parsingContext: .nominalTypeDeclExtendedName)
(unexpectedBeforePeriod, period) = self.expect(.period)
}

let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
if unexpectedBeforeName == nil && name.isMissing && self.atStartOfLine {
return T.init(
attributes: attrs.attributes,
modifiers: attrs.modifiers,
unexpectedBeforeIntroducerKeyword,
introducerKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeName,
name: name,
primaryOrGenerics: nil,
Expand Down Expand Up @@ -264,6 +309,9 @@ extension Parser {
modifiers: attrs.modifiers,
unexpectedBeforeIntroducerKeyword,
introducerKeyword: introducerKeyword,
extendedType: extendedType,
unexpectedBeforePeriod,
period: period,
unexpectedBeforeName,
name: name,
primaryOrGenerics: primaryOrGenerics,
Expand Down
38 changes: 32 additions & 6 deletions Sources/SwiftParser/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax
#endif

enum SimpleTypeParsingContext {
case `default`
case keyPathRoot
case attributeName
case nominalTypeDeclExtendedName
}

extension Parser {
/// Parse a type.
mutating func parseType(misplacedSpecifiers: [RawTokenSyntax] = []) -> RawTypeSyntax {
Expand Down Expand Up @@ -187,12 +194,11 @@ extension Parser {

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

mutating func parseSimpleType(
allowMemberTypes: Bool = true,
forAttributeName: Bool = false
parsingContext: SimpleTypeParsingContext = .default
) -> RawTypeSyntax {
enum TypeBaseStart: TokenSpecSet {
case `Self`
Expand Down Expand Up @@ -257,9 +263,25 @@ extension Parser {
return wrapInTilde(RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)))
}

func shouldContinueAfterPeriod() -> Bool {
if self.peek(isAt: .keyword(.Type), .keyword(.Protocol)) {
return true
}
switch parsingContext {
case .keyPathRoot:
return false
case .nominalTypeDeclExtendedName:
var lookahead = self.lookahead()
lookahead.eat(.period)
return lookahead.canParseExtendedTypeForNominalTypeDecl()
default:
return true
}
}

var loopProgress = LoopProgressCondition()
while self.hasProgressed(&loopProgress) {
if self.at(.period) && (allowMemberTypes || self.peek(isAt: .keyword(.Type), .keyword(.Protocol))) {
if self.at(.period) && shouldContinueAfterPeriod() {
let (unexpectedPeriod, period, skipMemberName) = self.consumeMemberPeriod(previousNode: base)
if skipMemberName {
let missingIdentifier = missingToken(.identifier)
Expand Down Expand Up @@ -315,7 +337,7 @@ extension Parser {
}

// Do not allow ? or ! suffixes when parsing attribute names.
if forAttributeName {
if parsingContext == .attributeName {
break
}

Expand Down Expand Up @@ -691,7 +713,7 @@ extension Parser.Lookahead {
return true
}

mutating func canParseSimpleType() -> Bool {
mutating func canParseSimpleType(parsingContext: SimpleTypeParsingContext = .default) -> Bool {
switch self.currentToken {
case TokenSpec(.Any):
self.consumeAnyToken()
Expand Down Expand Up @@ -736,6 +758,10 @@ extension Parser.Lookahead {
var loopProgress = LoopProgressCondition()
while self.hasProgressed(&loopProgress) {
if self.at(.period) {
if parsingContext == .nominalTypeDeclExtendedName {
return true
}

self.consumeAnyToken()
if self.at(.keyword(.Type)) || self.at(.keyword(.Protocol)) {
self.consumeAnyToken()
Expand Down
Loading