Skip to content

Commit 81d19df

Browse files
authored
Merge pull request #70292 from rintaro/astgen-keywordkind
[ASTGen] TokenSyntax.keyworkKind to directly get Keyword kind
2 parents 6ecaaa4 + a12113a commit 81d19df

File tree

5 files changed

+73
-56
lines changed

5 files changed

+73
-56
lines changed

lib/ASTGen/Sources/ASTGen/ASTGen.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,10 @@ extension ASTGenVisitor {
137137
/// escaped identifier, backticks are stripped.
138138
@inline(__always)
139139
func generateIdentifier(_ token: TokenSyntax) -> BridgedIdentifier {
140-
var text = token.rawText
141-
// FIXME: Maybe `TokenSyntax.tokenView.rawKind == .wildcard`, or expose it as `.rawTokenKind`.
142-
if text == "_" {
140+
if token.rawTokenKind == .wildcard {
143141
return nil
144142
}
143+
var text = token.rawText
145144
if text.count > 2 && text.hasPrefix("`") && text.hasSuffix("`") {
146145
text = .init(rebasing: text.dropFirst().dropLast())
147146
}
@@ -382,6 +381,24 @@ extension Optional where Wrapped: LazyCollectionProtocol {
382381
}
383382
}
384383

384+
extension TokenSyntax {
385+
/// Get `Keyword` kind if the token is a keyword.
386+
var keywordKind: Keyword? {
387+
// Performance note:
388+
// This is faster than `token.tokenKind == .keyword(.true)` because
389+
// `TokenKind.tokenKind` may instantiate `Swift.String`.
390+
// That being said, `SwiftSyntax.Keyword` is a non-SPI public type, so it
391+
// cannot be `@frozen`. Also `Keyword(_:SyntaxText)` itself is heavier than
392+
// simple `token.rawText == "true"`.
393+
// We should ensure `token.keywordKind == .true` is optimized out to
394+
// a simple `cmp` instruction.
395+
guard rawTokenKind == .keyword else {
396+
return nil
397+
}
398+
return Keyword(self.rawText)
399+
}
400+
}
401+
385402
/// Generate AST nodes for all top-level entities in the given source file.
386403
@_cdecl("swift_ASTGen_buildTopLevelASTNodes")
387404
public func buildTopLevelASTNodes(

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import ASTBridging
1414
import BasicBridging
1515
import SwiftDiagnostics
16-
@_spi(ExperimentalLanguageFeatures) import SwiftSyntax
16+
@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) import SwiftSyntax
1717

1818
// MARK: - TypeDecl
1919

@@ -293,7 +293,7 @@ extension ASTGenVisitor {
293293
let initializer = generate(initializerClause: node.bindings.first!.initializer!)
294294

295295
let isStatic = false // TODO: compute this
296-
let isLet = node.bindingSpecifier.tokenKind == .keyword(.let)
296+
let isLet = node.bindingSpecifier.keywordKind == .let
297297

298298
return .createParsed(
299299
self.ctx,
@@ -347,7 +347,7 @@ extension ASTGenVisitor {
347347
declContext: self.declContext,
348348
initKeywordLoc: self.generateSourceLoc(node.initKeyword),
349349
failabilityMarkLoc: self.generateSourceLoc(node.optionalMark),
350-
isIUO: node.optionalMark?.tokenKind == .exclamationMark,
350+
isIUO: node.optionalMark?.rawTokenKind == .exclamationMark,
351351
genericParamList: self.generate(genericParameterClause: node.genericParameterClause),
352352
parameterList: self.generate(functionParameterClause: node.signature.parameterClause),
353353
asyncSpecifierLoc: self.generateSourceLoc(node.signature.effectSpecifiers?.asyncSpecifier),
@@ -385,11 +385,11 @@ extension ASTGenVisitor {
385385
// MARK: - OperatorDecl
386386

387387
extension BridgedOperatorFixity {
388-
fileprivate init?(from tokenKind: TokenKind) {
389-
switch tokenKind {
390-
case .keyword(.infix): self = .infix
391-
case .keyword(.prefix): self = .prefix
392-
case .keyword(.postfix): self = .postfix
388+
fileprivate init?(from keyword: Keyword?) {
389+
switch keyword {
390+
case .infix: self = .infix
391+
case .prefix: self = .prefix
392+
case .postfix: self = .postfix
393393
default: return nil
394394
}
395395
}
@@ -402,7 +402,7 @@ extension ASTGenVisitor {
402402
self.generateIdentifierAndSourceLoc(node.operatorPrecedenceAndTypes?.precedenceGroup)
403403

404404
let fixity: BridgedOperatorFixity
405-
if let value = BridgedOperatorFixity(from: node.fixitySpecifier.tokenKind) {
405+
if let value = BridgedOperatorFixity(from: node.fixitySpecifier.keywordKind) {
406406
fixity = value
407407
} else {
408408
fixity = .infix
@@ -428,11 +428,11 @@ extension ASTGenVisitor {
428428
// MARK: - PrecedenceGroupDecl
429429

430430
extension BridgedAssociativity {
431-
fileprivate init?(from tokenKind: TokenKind) {
432-
switch tokenKind {
433-
case .keyword(.none): self = .none
434-
case .keyword(.left): self = .left
435-
case .keyword(.right): self = .right
431+
fileprivate init?(from keyword: Keyword?) {
432+
switch keyword {
433+
case .none?: self = .none
434+
case .left?: self = .left
435+
case .right?: self = .right
436436
default: return nil
437437
}
438438
}
@@ -459,14 +459,14 @@ extension ASTGenVisitor {
459459
switch element {
460460
case .precedenceGroupRelation(let relation):
461461
let keyword = relation.higherThanOrLowerThanLabel
462-
switch keyword.tokenKind {
463-
case .keyword(.higherThan):
462+
switch keyword.keywordKind {
463+
case .higherThan:
464464
if let current = body.higherThanRelation {
465465
diagnoseDuplicateSyntax(relation, original: current)
466466
} else {
467467
body.higherThanRelation = relation
468468
}
469-
case .keyword(.lowerThan):
469+
case .lowerThan:
470470
if let current = body.lowerThanRelation {
471471
diagnoseDuplicateSyntax(relation, original: current)
472472
} else {
@@ -492,7 +492,7 @@ extension ASTGenVisitor {
492492

493493
let associativityValue: BridgedAssociativity
494494
if let token = body.associativity?.value {
495-
if let value = BridgedAssociativity(from: token.tokenKind) {
495+
if let value = BridgedAssociativity(from: token.keywordKind) {
496496
associativityValue = value
497497
} else {
498498
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
@@ -504,7 +504,7 @@ extension ASTGenVisitor {
504504

505505
let assignmentValue: Bool
506506
if let token = body.assignment?.value {
507-
if token.tokenKind == .keyword(.true) {
507+
if token.keywordKind == .true {
508508
assignmentValue = true
509509
} else {
510510
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
@@ -538,15 +538,15 @@ extension ASTGenVisitor {
538538
// MARK: - ImportDecl
539539

540540
extension BridgedImportKind {
541-
fileprivate init?(from tokenKind: TokenKind) {
542-
switch tokenKind {
543-
case .keyword(.typealias): self = .type
544-
case .keyword(.struct): self = .struct
545-
case .keyword(.class): self = .class
546-
case .keyword(.enum): self = .enum
547-
case .keyword(.protocol): self = .protocol
548-
case .keyword(.var), .keyword(.let): self = .var
549-
case .keyword(.func): self = .func
541+
fileprivate init?(from keyword: Keyword?) {
542+
switch keyword {
543+
case .typealias: self = .type
544+
case .struct: self = .struct
545+
case .class: self = .class
546+
case .enum: self = .enum
547+
case .protocol: self = .protocol
548+
case .var, .let: self = .var
549+
case .func: self = .func
550550
default: return nil
551551
}
552552
}
@@ -556,7 +556,7 @@ extension ASTGenVisitor {
556556
func generate(importDecl node: ImportDeclSyntax) -> BridgedImportDecl {
557557
let importKind: BridgedImportKind
558558
if let specifier = node.importKindSpecifier {
559-
if let value = BridgedImportKind(from: specifier.tokenKind) {
559+
if let value = BridgedImportKind(from: specifier.keywordKind) {
560560
importKind = value
561561
} else {
562562
self.diagnose(Diagnostic(node: specifier, message: UnexpectedTokenKindError(token: specifier)))

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import ASTBridging
1414
import SwiftDiagnostics
15-
@_spi(ExperimentalLanguageFeatures) import SwiftSyntax
15+
@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) import SwiftSyntax
1616

1717
/// Check if an `ExprSyntax` can be generated using ASTGen.
1818
///
@@ -292,12 +292,12 @@ extension ASTGenVisitor {
292292

293293
private func createDeclNameRef(declReferenceExpr node: DeclReferenceExprSyntax) -> (name: BridgedDeclNameRef, loc: BridgedDeclNameLoc) {
294294
let baseName: BridgedDeclBaseName
295-
switch node.baseName.tokenKind {
296-
case .keyword(.`init`):
295+
switch node.baseName.keywordKind {
296+
case .`init`:
297297
baseName = .createConstructor()
298-
case .keyword(.deinit):
298+
case .deinit:
299299
baseName = .createDestructor()
300-
case .keyword(.subscript):
300+
case .subscript:
301301
baseName = .createSubscript()
302302
default:
303303
baseName = .createIdentifier(self.generateIdentifier(node.baseName))
@@ -480,14 +480,14 @@ extension ASTGenVisitor {
480480
asLoc: asLoc,
481481
type: type
482482
).asExpr
483-
case let question? where question.text == "?":
483+
case let question? where question.rawTokenKind == .postfixQuestionMark:
484484
return BridgedConditionalCheckedCastExpr.createParsed(
485485
self.ctx,
486486
asLoc: asLoc,
487487
questionLoc: self.generateSourceLoc(question),
488488
type: type
489489
).asExpr
490-
case let exclaim? where exclaim.text == "!":
490+
case let exclaim? where exclaim.rawTokenKind == .exclamationMark:
491491
return BridgedForcedCheckedCastExpr.createParsed(
492492
self.ctx,
493493
asLoc: asLoc,

lib/ASTGen/Sources/ASTGen/Literals.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extension ASTGenVisitor {
3939
}
4040

4141
func generate(booleanLiteralExpr node: BooleanLiteralExprSyntax) -> BridgedBooleanLiteralExpr {
42-
let value = node.literal.tokenKind == .keyword(.true)
42+
let value = node.literal.keywordKind == .true
4343
return .createParsed(
4444
ctx,
4545
value: value,

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extension ASTGenVisitor {
106106
let loc = self.generateSourceLoc(node.name)
107107

108108
// If this is the bare 'Any' keyword, produce an empty composition type.
109-
if node.name.rawText == "Any" && node.genericArgumentClause == nil {
109+
if node.name.keywordKind == .Any && node.genericArgumentClause == nil {
110110
return BridgedCompositionTypeRepr.createEmpty(self.ctx, anyKeywordLoc: loc)
111111
}
112112

@@ -203,14 +203,14 @@ extension ASTGenVisitor {
203203
func generate(metatypeType node: MetatypeTypeSyntax) -> BridgedTypeRepr {
204204
let baseType = generate(type: node.baseType)
205205
let tyLoc = self.generateSourceLoc(node.metatypeSpecifier)
206-
if node.metatypeSpecifier.rawText == "Type" {
206+
if node.metatypeSpecifier.keywordKind == .Type {
207207
return BridgedMetatypeTypeRepr.createParsed(
208208
self.ctx,
209209
base: baseType,
210210
typeKeywordLoc: tyLoc
211211
)
212212
} else {
213-
assert(node.metatypeSpecifier.rawText == "Protocol")
213+
assert(node.metatypeSpecifier.keywordKind == .Protocol)
214214
return BridgedProtocolTypeRepr.createParsed(
215215
self.ctx,
216216
base: baseType,
@@ -298,14 +298,14 @@ extension ASTGenVisitor {
298298
func generate(someOrAnyType node: SomeOrAnyTypeSyntax) -> BridgedTypeRepr {
299299
let someOrAnyLoc = self.generateSourceLoc(node.someOrAnySpecifier)
300300
let baseTy = generate(type: node.constraint)
301-
if node.someOrAnySpecifier.rawText == "some" {
301+
if node.someOrAnySpecifier.keywordKind == .some {
302302
return BridgedOpaqueReturnTypeRepr.createParsed(
303303
self.ctx,
304304
someKeywordLoc: someOrAnyLoc,
305305
base: baseTy
306306
)
307307
} else {
308-
assert(node.someOrAnySpecifier.text == "any")
308+
assert(node.someOrAnySpecifier.keywordKind == .any)
309309
return BridgedExistentialTypeRepr.createParsed(
310310
self.ctx,
311311
anyKeywordLoc: someOrAnyLoc,
@@ -320,16 +320,16 @@ extension ASTGenVisitor {
320320
// MARK: - SpecifierTypeRepr/AttributedTypeRepr
321321

322322
extension BridgedAttributedTypeSpecifier {
323-
fileprivate init?(from tokenKind: TokenKind) {
324-
switch tokenKind {
325-
case .keyword(.inout): self = .inOut
326-
case .keyword(.borrowing): self = .borrowing
327-
case .keyword(.consuming): self = .consuming
328-
case .keyword(.__shared): self = .legacyShared
329-
case .keyword(.__owned): self = .legacyOwned
330-
case .keyword(._const): self = .const
331-
case .keyword(.isolated): self = .isolated
332-
case .keyword(._resultDependsOn): self = .resultDependsOn
323+
fileprivate init?(from keyword: Keyword?) {
324+
switch keyword {
325+
case .inout: self = .inOut
326+
case .borrowing: self = .borrowing
327+
case .consuming: self = .consuming
328+
case .__shared: self = .legacyShared
329+
case .__owned: self = .legacyOwned
330+
case ._const: self = .const
331+
case .isolated: self = .isolated
332+
case ._resultDependsOn: self = .resultDependsOn
333333
default: return nil
334334
}
335335
}
@@ -341,7 +341,7 @@ extension ASTGenVisitor {
341341

342342
// Handle specifiers.
343343
if let specifier = node.specifier {
344-
if let kind = BridgedAttributedTypeSpecifier(from: specifier.tokenKind) {
344+
if let kind = BridgedAttributedTypeSpecifier(from: specifier.keywordKind) {
345345
type = BridgedSpecifierTypeRepr.createParsed(
346346
self.ctx,
347347
base: type,

0 commit comments

Comments
 (0)