Skip to content

Improve modeling of TokenSpec in CodeGeneration #2077

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

Merged
merged 2 commits into from
Aug 17, 2023
Merged
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
53 changes: 43 additions & 10 deletions CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,40 @@ public struct TokenSpec {
case other
}

/// The name of the token, suitable for use in variable or enum case names.
public let varOrCaseName: TokenSyntax

/// If `true`, this is for an experimental language feature, and any public
/// API generated should be SPI.
/// Indicates if the token is part of an experimental language feature.
///
/// If `true`, this keyword is for an experimental language feature, and any public
/// API generated should be marked as SPI
public let isExperimental: Bool

/// The name of the token that can be shown in diagnostics.
public let nameForDiagnostics: String

/// The actual text of the token, if available.
public let text: String?

/// The kind of the token.
public let kind: Kind

/// The attributes that should be printed on any API for the generated keyword.
///
/// This is typically used to mark APIs as SPI when the keyword is part of an experimental language feature.
public var apiAttributes: AttributeListSyntax {
guard isExperimental else { return "" }
return AttributeListSyntax("@_spi(ExperimentalLanguageFeatures)").with(\.trailingTrivia, .newline)
}

/// Initializes a new `TokenSpec` instance.
///
/// - Parameters:
/// - name: A name of the token.
/// - isExperimental: Indicates if the token is part of an experimental language feature.
/// - nameForDiagnostics: A name of the token that can be shown in diagnostics.
/// - text: An actual text of the token, if available.
/// - kind: A kind of the token.
fileprivate init(
name: String,
isExperimental: Bool = false,
Expand All @@ -45,13 +69,11 @@ public struct TokenSpec {
self.kind = kind
}

/// Retrieve the attributes that should be printed on any API for the
/// generated token.
public var apiAttributes: AttributeListSyntax {
guard isExperimental else { return "" }
return AttributeListSyntax("@_spi(ExperimentalLanguageFeatures)").with(\.trailingTrivia, .newline)
}

/// Creates a new `TokenSpec` instance representing a punctuation token.
///
/// - Parameters:
/// - name: A name of the token.
/// - text: An actual text of the punctuation token.
static func punctuator(name: String, text: String) -> TokenSpec {
return TokenSpec(
name: name,
Expand All @@ -61,6 +83,11 @@ public struct TokenSpec {
)
}

/// Creates a new `TokenSpec` instance representing a pound keyword token.
///
/// - Parameters:
/// - name: A name of the token.
/// - text: An actual text of the pound keyword token.
static func poundKeyword(name: String, text: String) -> TokenSpec {
return TokenSpec(
name: name,
Expand All @@ -70,8 +97,14 @@ public struct TokenSpec {
)
}

/// Creates a new `TokenSpec` instance representing an other token.
///
/// - Parameters:
/// - name: A name of the token.
/// - nameForDiagnostics: A name of the token that can be shown in diagnostics.
/// - text: An actual text of the token, if available.
static func other(name: String, nameForDiagnostics: String, text: String? = nil) -> TokenSpec {
TokenSpec(
return TokenSpec(
name: name,
nameForDiagnostics: nameForDiagnostics,
text: text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ let tokenKindFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
} else if let text = tokenSpec.text {
SwitchCaseSyntax("case .\(tokenSpec.varOrCaseName):") {
StmtSyntax("return #\"\(raw: text)\"#")
StmtSyntax("return \(literal: text)")
}
} else {
SwitchCaseSyntax("case .\(tokenSpec.varOrCaseName)(let text):") {
Expand All @@ -90,7 +90,7 @@ let tokenKindFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
} else if let text = tokenSpec.text {
SwitchCaseSyntax("case .\(tokenSpec.varOrCaseName):") {
StmtSyntax("return #\"\(raw: text)\"#")
StmtSyntax("return \(literal: text)")
}
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@ let tokenKindFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
for tokenSpec in Token.allCases.map(\.spec) {
if let text = tokenSpec.text {
SwitchCaseSyntax("case .\(tokenSpec.varOrCaseName):") {
StmtSyntax("return #\"\(raw: text)\"#")
StmtSyntax("return \(literal: text)")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Utils
let tokensFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
try! ExtensionDeclSyntax("extension TokenSyntax") {
for tokenSpec in Token.allCases.map(\.spec) {
if let text = tokenSpec.text {
if tokenSpec.text != nil {
DeclSyntax(
"""
public static func \(tokenSpec.varOrCaseName)Token(
Expand Down
Loading