Skip to content

Commit 056901f

Browse files
committed
Disallow the self/Self keyword where it’s not allowed in types
We weren’t matching the C++ parser’s behavior here. The `self` keyword is not allowed as a type name. `Self` in a nested type refers to a type named `Self` instead of the `Self` keyword.
1 parent f790929 commit 056901f

File tree

10 files changed

+137
-63
lines changed

10 files changed

+137
-63
lines changed

CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ public let TYPE_NODES: [Node] = [
301301
),
302302
Child(
303303
name: "Name",
304-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "self"), .keyword(text: "Self")]),
304+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "self")]),
305305
nameForDiagnostics: "name"
306306
),
307307
Child(
@@ -436,7 +436,6 @@ public let TYPE_NODES: [Node] = [
436436
name: "Name",
437437
kind: .token(choices: [
438438
.token(tokenKind: "IdentifierToken"),
439-
.keyword(text: "self"),
440439
.keyword(text: "Self"),
441440
.keyword(text: "Any"),
442441
.token(tokenKind: "WildcardToken"),

Sources/SwiftParser/Names.swift

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ extension Parser {
150150
let period: RawTokenSyntax?
151151
if self.lookahead().canParseBaseTypeForQualifiedDeclName() {
152152
type = self.parseQualifiedTypeIdentifier()
153-
period = self.consumePrefix(".", as: .period)
153+
period = self.expectWithoutRecovery(prefix: ".", as: .period)
154154
} else {
155155
type = nil
156156
period = nil
@@ -174,52 +174,70 @@ extension Parser {
174174
return RawTypeSyntax(self.parseAnyType())
175175
}
176176

177-
var result: RawTypeSyntax?
178-
var keepGoing: RawTokenSyntax? = nil
177+
let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier)
178+
let generics: RawGenericArgumentClauseSyntax?
179+
if self.atContextualPunctuator("<") {
180+
generics = self.parseGenericArguments()
181+
} else {
182+
generics = nil
183+
}
184+
185+
var result = RawTypeSyntax(
186+
RawIdentifierTypeSyntax(
187+
unexpectedBeforeName,
188+
name: name,
189+
genericArgumentClause: generics,
190+
arena: self.arena
191+
)
192+
)
193+
194+
// If qualified name base type cannot be parsed from the current
195+
// point (i.e. the next type identifier is not followed by a '.'),
196+
// then the next identifier is the final declaration name component.
197+
var backtrack = self.lookahead()
198+
guard
199+
backtrack.consume(ifPrefix: ".", as: .period) != nil,
200+
backtrack.canParseBaseTypeForQualifiedDeclName()
201+
else {
202+
return result
203+
}
204+
205+
var keepGoing = self.consume(if: .period)
179206
var loopProgress = LoopProgressCondition()
180-
repeat {
181-
let (unexpectedBeforeName, name) = self.expect(.identifier, .keyword(.self), .keyword(.Self), default: .identifier)
207+
while keepGoing != nil && self.hasProgressed(&loopProgress) {
208+
let (unexpectedBeforeName, name) = self.expect(.identifier, .keyword(.self), TokenSpec(.Self, remapping: .identifier), default: .identifier)
182209
let generics: RawGenericArgumentClauseSyntax?
183210
if self.atContextualPunctuator("<") {
184211
generics = self.parseGenericArguments()
185212
} else {
186213
generics = nil
187214
}
188-
if let keepGoing {
189-
result = RawTypeSyntax(
190-
RawMemberTypeSyntax(
191-
baseType: result!,
192-
period: keepGoing,
193-
unexpectedBeforeName,
194-
name: name,
195-
genericArgumentClause: generics,
196-
arena: self.arena
197-
)
198-
)
199-
} else {
200-
result = RawTypeSyntax(
201-
RawIdentifierTypeSyntax(
202-
unexpectedBeforeName,
203-
name: name,
204-
genericArgumentClause: generics,
205-
arena: self.arena
206-
)
215+
result = RawTypeSyntax(
216+
RawMemberTypeSyntax(
217+
baseType: result,
218+
period: keepGoing!,
219+
unexpectedBeforeName,
220+
name: name,
221+
genericArgumentClause: generics,
222+
arena: self.arena
207223
)
208-
}
224+
)
209225

210226
// If qualified name base type cannot be parsed from the current
211227
// point (i.e. the next type identifier is not followed by a '.'),
212228
// then the next identifier is the final declaration name component.
213229
var backtrack = self.lookahead()
214-
backtrack.consumePrefix(".", as: .period)
215-
guard backtrack.canParseBaseTypeForQualifiedDeclName() else {
230+
guard
231+
backtrack.consume(ifPrefix: ".", as: .period) != nil,
232+
backtrack.canParseBaseTypeForQualifiedDeclName()
233+
else {
216234
break
217235
}
218236

219237
keepGoing = self.consume(if: .period)
220-
} while keepGoing != nil && self.hasProgressed(&loopProgress)
238+
}
221239

222-
return result!
240+
return result
223241
}
224242
}
225243

Sources/SwiftParser/Parameters.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ extension Parser {
9797

9898
let type: RawTypeSyntax
9999

100-
if colon.presence == .missing, let secondName = names.secondName, secondName.tokenText.isStartingWithUppercase {
100+
if colon.presence == .missing,
101+
let secondName = names.secondName,
102+
secondName.tokenKind == .identifier,
103+
secondName.tokenText.isStartingWithUppercase
104+
{
101105
// Synthesize the secondName parameter as a type node.
102106
type = RawTypeSyntax(
103107
RawIdentifierTypeSyntax(

Sources/SwiftParser/Parser.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ extension Parser {
502502
/// currently positioned at a keyword, consume that keyword and remap it
503503
/// to and identifier.
504504
/// - Returns: The consumed token and any unexpected tokens that were skipped.
505+
/// The token is always guaranteed to be of `TokenKind.identifier`
505506
mutating func expectIdentifier(
506507
keywordRecovery: Bool = false,
507508
allowSelfOrCapitalSelfAsIdentifier: Bool = false,

Sources/SwiftParser/Types.swift

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,20 @@ extension Parser {
270270
)
271271
)
272272
} else {
273-
let (name, generics) = self.parseTypeNameWithGenerics(allowKeywordAsName: true)
273+
let name: RawTokenSyntax
274+
if let handle = self.at(anyIn: MemberTypeSyntax.NameOptions.self)?.handle {
275+
name = self.eat(handle)
276+
} else if self.currentToken.isLexerClassifiedKeyword {
277+
name = self.consumeAnyToken(remapping: .identifier)
278+
} else {
279+
name = missingToken(.identifier)
280+
}
281+
let generics: RawGenericArgumentClauseSyntax?
282+
if self.atContextualPunctuator("<") {
283+
generics = self.parseGenericArguments()
284+
} else {
285+
generics = nil
286+
}
274287
base = RawTypeSyntax(
275288
RawMemberTypeSyntax(
276289
baseType: base,
@@ -322,30 +335,23 @@ extension Parser {
322335
)
323336
}
324337

325-
mutating func parseTypeNameWithGenerics(allowKeywordAsName: Bool) -> (RawTokenSyntax, RawGenericArgumentClauseSyntax?) {
326-
let name: RawTokenSyntax
327-
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) {
328-
name = identOrSelf
329-
} else if allowKeywordAsName && self.currentToken.isLexerClassifiedKeyword {
330-
name = self.consumeAnyToken(remapping: .identifier)
331-
} else {
332-
name = missingToken(.identifier)
333-
}
334-
if self.atContextualPunctuator("<") {
335-
return (name, self.parseGenericArguments())
336-
}
337-
return (name, nil)
338-
}
339-
340338
/// Parse a type identifier.
341339
mutating func parseTypeIdentifier() -> RawTypeSyntax {
342340
if self.at(.keyword(.Any)) {
343341
return RawTypeSyntax(self.parseAnyType())
344342
}
345343

346-
let (name, generics) = parseTypeNameWithGenerics(allowKeywordAsName: false)
344+
let (unexpectedBeforeName, name) = self.expect(anyIn: IdentifierTypeSyntax.NameOptions.self, default: .identifier)
345+
let generics: RawGenericArgumentClauseSyntax?
346+
if self.atContextualPunctuator("<") {
347+
generics = self.parseGenericArguments()
348+
} else {
349+
generics = nil
350+
}
351+
347352
return RawTypeSyntax(
348353
RawIdentifierTypeSyntax(
354+
unexpectedBeforeName,
349355
name: name,
350356
genericArgumentClause: generics,
351357
arena: self.arena
@@ -479,6 +485,7 @@ extension Parser {
479485
if let first,
480486
second == nil,
481487
colon?.isMissing == true,
488+
first.tokenKind == .identifier,
482489
first.tokenText.isStartingWithUppercase
483490
{
484491
elements.append(

Sources/SwiftParser/generated/Parser+TokenSpecSet.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,6 @@ extension IdentifierPatternSyntax {
10831083
extension IdentifierTypeSyntax {
10841084
enum NameOptions: TokenSpecSet {
10851085
case identifier
1086-
case `self`
10871086
case `Self`
10881087
case `Any`
10891088
case wildcard
@@ -1092,8 +1091,6 @@ extension IdentifierTypeSyntax {
10921091
switch PrepareForKeywordMatch(lexeme) {
10931092
case TokenSpec(.identifier):
10941093
self = .identifier
1095-
case TokenSpec(.`self`):
1096-
self = .`self`
10971094
case TokenSpec(.`Self`):
10981095
self = .`Self`
10991096
case TokenSpec(.`Any`):
@@ -1109,8 +1106,6 @@ extension IdentifierTypeSyntax {
11091106
switch self {
11101107
case .identifier:
11111108
return .identifier
1112-
case .`self`:
1113-
return .keyword(.`self`)
11141109
case .`Self`:
11151110
return .keyword(.`Self`)
11161111
case .`Any`:
@@ -1395,16 +1390,13 @@ extension MemberTypeSyntax {
13951390
enum NameOptions: TokenSpecSet {
13961391
case identifier
13971392
case `self`
1398-
case `Self`
13991393

14001394
init?(lexeme: Lexer.Lexeme) {
14011395
switch PrepareForKeywordMatch(lexeme) {
14021396
case TokenSpec(.identifier):
14031397
self = .identifier
14041398
case TokenSpec(.`self`):
14051399
self = .`self`
1406-
case TokenSpec(.`Self`):
1407-
self = .`Self`
14081400
default:
14091401
return nil
14101402
}
@@ -1416,8 +1408,6 @@ extension MemberTypeSyntax {
14161408
return .identifier
14171409
case .`self`:
14181410
return .keyword(.`self`)
1419-
case .`Self`:
1420-
return .keyword(.`Self`)
14211411
}
14221412
}
14231413
}

Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,6 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) {
14061406
assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self))
14071407
assertNoError(kind, 1, verify(layout[1], as: RawTokenSyntax.self, tokenChoices: [
14081408
.tokenKind(.identifier),
1409-
.keyword("self"),
14101409
.keyword("Self"),
14111410
.keyword("Any"),
14121411
.tokenKind(.wildcard)
@@ -1797,7 +1796,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) {
17971796
assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self))
17981797
assertNoError(kind, 3, verify(layout[3], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.period)]))
17991798
assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self))
1800-
assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier), .keyword("self"), .keyword("Self")]))
1799+
assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.tokenKind(.identifier), .keyword("self")]))
18011800
assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self))
18021801
assertNoError(kind, 7, verify(layout[7], as: RawGenericArgumentClauseSyntax?.self))
18031802
assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self))

Sources/SwiftSyntax/generated/syntaxNodes/SyntaxTypeNodes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ public struct FunctionTypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
958958

959959
/// ### Children
960960
///
961-
/// - `name`: (`<identifier>` | `'self'` | `'Self'` | `'Any'` | `'_'`)
961+
/// - `name`: (`<identifier>` | `'Self'` | `'Any'` | `'_'`)
962962
/// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``?
963963
public struct IdentifierTypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
964964
public let _syntaxNode: Syntax
@@ -1204,7 +1204,7 @@ public struct ImplicitlyUnwrappedOptionalTypeSyntax: TypeSyntaxProtocol, SyntaxH
12041204
///
12051205
/// - `baseType`: ``TypeSyntax``
12061206
/// - `period`: `'.'`
1207-
/// - `name`: (`<identifier>` | `'self'` | `'Self'`)
1207+
/// - `name`: (`<identifier>` | `'self'`)
12081208
/// - `genericArgumentClause`: ``GenericArgumentClauseSyntax``?
12091209
public struct MemberTypeSyntax: TypeSyntaxProtocol, SyntaxHashable {
12101210
public let _syntaxNode: Syntax

Tests/SwiftParserTest/AttributeTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,24 @@ final class AttributeTests: XCTestCase {
208208
) {}
209209
"""
210210
)
211+
212+
assertParse(
213+
"""
214+
@derivitave(of: 1️⃣Self.other)
215+
func foo() {}
216+
""",
217+
substructure: Syntax(TokenSyntax.keyword(.Self)),
218+
substructureAfterMarker: "1️⃣"
219+
)
220+
221+
assertParse(
222+
"""
223+
@derivative(of: Foo.1️⃣Self.other)
224+
func foo() {}
225+
""",
226+
substructure: Syntax(TokenSyntax.identifier("Self")),
227+
substructureAfterMarker: "1️⃣"
228+
)
211229
}
212230

213231
func testTransposeAttribute() {

Tests/SwiftParserTest/TypeTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,42 @@ final class TypeTests: XCTestCase {
192192
"""
193193
)
194194
}
195+
196+
func testLowercaseSelf() {
197+
assertParse(
198+
"1️⃣self2️⃣",
199+
{ TypeSyntax.parse(from: &$0) },
200+
diagnostics: [
201+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected 'self' keyword before type"),
202+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected type", fixIts: ["insert type"]),
203+
],
204+
fixedSource: "<#type#>self"
205+
)
206+
}
207+
208+
func testUppercaseSelf() {
209+
assertParse(
210+
"Self",
211+
{ TypeSyntax.parse(from: &$0) },
212+
substructure: Syntax(TokenSyntax.keyword(.Self))
213+
)
214+
}
215+
216+
func testNestedLowercaseSelf() {
217+
assertParse(
218+
"Foo.1️⃣self",
219+
{ TypeSyntax.parse(from: &$0) },
220+
substructure: Syntax(TokenSyntax.keyword(.`self`)),
221+
substructureAfterMarker: "1️⃣"
222+
)
223+
}
224+
225+
func testNestedUppercaseSelf() {
226+
assertParse(
227+
"Foo.1️⃣Self",
228+
{ TypeSyntax.parse(from: &$0) },
229+
substructure: Syntax(TokenSyntax.identifier("Self")),
230+
substructureAfterMarker: "1️⃣"
231+
)
232+
}
195233
}

0 commit comments

Comments
 (0)