Skip to content

Update CodeGeneration to latest SwiftSyntaxBuilder #1008

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
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
2 changes: 1 addition & 1 deletion CodeGeneration/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
.executable(name: "generate-swiftsyntaxbuilder", targets: ["generate-swiftsyntaxbuilder"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", revision: "0663a530c4e51066343c3c2fbd95f8e626b8d631"),
.package(url: "https://github.com/apple/swift-syntax.git", revision: "fa7ff05591294db031e3061e704994aa3b89d1bc"),
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.1.4")),
],
targets: [
Expand Down
4 changes: 2 additions & 2 deletions CodeGeneration/Sources/Utils/CodeGenerationFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import SwiftSyntax
public class CodeGenerationFormat: BasicFormat {
public override var indentation: TriviaPiece { .spaces(indentationLevel * 2) }

public override func visit(_ node: MemberDeclListItemSyntax) -> Syntax {
public override func visit(_ node: MemberDeclListItemSyntax) -> MemberDeclListItemSyntax {
let formatted = super.visit(node)
return formatted.withLeadingTrivia(indentedNewline + (formatted.leadingTrivia ?? []))
}

public override func visit(_ node: CodeBlockItemSyntax) -> Syntax {
public override func visit(_ node: CodeBlockItemSyntax) -> CodeBlockItemSyntax {
if node.parent?.parent?.is(SourceFileSyntax.self) == true, !node.item.is(ImportDeclSyntax.self) {
let formatted = super.visit(node)
return formatted.withLeadingTrivia(indentedNewline + indentedNewline + (formatted.leadingTrivia ?? []))
Expand Down
3 changes: 2 additions & 1 deletion CodeGeneration/Sources/Utils/GenerateTemplates.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

import Foundation
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftBasicFormat

Expand All @@ -26,7 +27,7 @@ public func generateTemplates(templates: [(SourceFile, String)], destination: UR
if verbose {
print("Generating \(fileURL.path)...")
}
let syntax = sourceFile.build(format: CodeGenerationFormat())
let syntax = sourceFile.formatted(using: CodeGenerationFormat())
try "\(syntax)\n".write(to: fileURL, atomically: true, encoding: .utf8)
}
}
28 changes: 14 additions & 14 deletions CodeGeneration/Sources/Utils/SyntaxBuildableChild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public extension Child {
/// If this node is a token that can't contain arbitrary text, generate a Swift
/// `assert` statement that verifies the variable with name var_name and of type
/// `TokenSyntax` contains one of the supported text options. Otherwise return `nil`.
func generateAssertStmtTextChoices(varName: String) -> ExpressibleAsExprBuildable? {
func generateAssertStmtTextChoices(varName: String) -> FunctionCallExpr? {
guard type.isToken else {
return nil
}
Expand All @@ -52,24 +52,24 @@ public extension Child {
return nil
}

var assertChoices: [ExpressibleAsExprBuildable] = []
var assertChoices: [Expr] = []
if type.isOptional {
assertChoices.append(SequenceExpr {
varName
BinaryOperatorExpr("==")
assertChoices.append(Expr(SequenceExpr {
IdentifierExpr(identifier: .identifier(varName))
BinaryOperatorExpr(text: "==")
NilLiteralExpr()
})
}))
}
for textChoice in choices {
assertChoices.append(SequenceExpr {
MemberAccessExpr(base: type.forceUnwrappedIfNeeded(expr: varName), name: "text")
BinaryOperatorExpr("==")
StringLiteralExpr(raw: textChoice)
})
assertChoices.append(Expr(SequenceExpr {
MemberAccessExpr(base: type.forceUnwrappedIfNeeded(expr: Expr(varName)), name: "text")
BinaryOperatorExpr(text: "==")
StringLiteralExpr(content: textChoice)
}))
}
let disjunction = ExprList(assertChoices.flatMap { [$0, BinaryOperatorExpr("||")] }.dropLast())
return FunctionCallExpr(calledExpression: "assert") {
SequenceExpr(elements: disjunction)
let disjunction = ExprList(assertChoices.flatMap { [$0, Expr(BinaryOperatorExpr(text: "||"))] }.dropLast())
return FunctionCallExpr(calledExpression: Expr("assert")) {
TupleExprElement(expression: SequenceExpr(elements: disjunction))
}
}
}
38 changes: 19 additions & 19 deletions CodeGeneration/Sources/Utils/SyntaxBuildableType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ public struct SyntaxBuildableType: Hashable {
/// with fixed test), return an expression of the form ` = defaultValue`
/// that can be used as the default value for a function parameter.
/// Otherwise, return the empty string.
public var defaultInitialization: ExpressibleAsExprBuildable? {
public var defaultInitialization: Expr? {
if isOptional {
return NilLiteralExpr()
return Expr(NilLiteralExpr())
} else if isToken {
if let token = token, token.text != nil {
return MemberAccessExpr(base: "Token", name: lowercaseFirstWord(name: token.name).backticked)
return Expr(MemberAccessExpr(base: "Token", name: lowercaseFirstWord(name: token.name).backticked))
} else if tokenKind == "EOFToken" {
return MemberAccessExpr(base: "Token", name: "eof")
return Expr(MemberAccessExpr(base: "Token", name: "eof"))
}
}
return nil
Expand All @@ -86,8 +86,8 @@ public struct SyntaxBuildableType: Hashable {
/// - For base kinds: `<BaseKind>Buildable`, e.g. `ExprBuildable` (these are implemented as protocols)
/// - For token: `TokenSyntax` (tokens don't have a dedicated type in SwiftSyntaxBuilder)
/// If the type is optional, the type is wrapped in an `OptionalType`.
public var buildable: TypeBuildable {
optionalWrapped(type: shorthandName).createTypeBuildable()
public var buildable: Type {
optionalWrapped(type: Type(shorthandName))
}

/// Whether parameters of this type should be initializable by a result builder.
Expand Down Expand Up @@ -125,8 +125,8 @@ public struct SyntaxBuildableType: Hashable {
/// The corresponding `*Syntax` type defined in the `SwiftSyntax` module,
/// which will eventually get built from `SwiftSyntaxBuilder`. If the type
/// is optional, this terminates with a `?`.
public var syntax: TypeBuildable {
optionalWrapped(type: syntaxBaseName)
public var syntax: TypeSyntax {
return optionalWrapped(type: TypeSyntax(syntaxBaseName))
}

/// The type that is used for paramters in SwiftSyntaxBuilder that take this
Expand All @@ -139,8 +139,8 @@ public struct SyntaxBuildableType: Hashable {
}
}

public var parameterType: TypeBuildable {
return optionalWrapped(type: parameterBaseType)
public var parameterType: TypeSyntax {
return optionalWrapped(type: TypeSyntax(parameterBaseType))
}

/// Assuming that this is a collection type, the non-optional type of the result builder
Expand All @@ -165,29 +165,29 @@ public struct SyntaxBuildableType: Hashable {
}

/// Wraps a type in an optional depending on whether `isOptional` is true.
public func optionalWrapped(type: ExpressibleAsTypeBuildable) -> TypeBuildable {
public func optionalWrapped(type: TypeSyntaxProtocol) -> TypeSyntax {
if isOptional {
return OptionalType(wrappedType: type)
return TypeSyntax(OptionalType(wrappedType: type))
} else {
return type.createTypeBuildable()
return TypeSyntax(type)
}
}

/// Wraps a type in an optional chaining depending on whether `isOptional` is true.
public func optionalChained(expr: ExpressibleAsExprBuildable) -> ExpressibleAsExprBuildable {
public func optionalChained(expr: ExprSyntaxProtocol) -> Expr {
if isOptional {
return OptionalChainingExpr(expression: expr)
return Expr(OptionalChainingExpr(expression: expr))
} else {
return expr
return Expr(expr)
}
}

/// Wraps a type in a force unwrap expression depending on whether `isOptional` is true.
public func forceUnwrappedIfNeeded(expr: ExpressibleAsExprBuildable) -> ExpressibleAsExprBuildable {
public func forceUnwrappedIfNeeded(expr: ExprSyntaxProtocol) -> ExprSyntax {
if isOptional {
return ForcedValueExpr(expression: expr)
return ExprSyntax(ForcedValueExpr(expression: expr))
} else {
return expr
return ExprSyntax(expr)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import Utils
let basicFormatFile = SourceFile {
ImportDecl(
leadingTrivia: .docLineComment(copyrightHeader),
path: "SwiftSyntax"
path: [AccessPathComponent(name: "SwiftSyntax")]
)

ClassDecl(modifiers: [Token.open], identifier: "BasicFormat", inheritanceClause: TypeInheritanceClause { InheritedType(typeName: "SyntaxRewriter") }) {
ClassDecl(modifiers: [DeclModifier(name: .open)], identifier: "BasicFormat", inheritanceClause: TypeInheritanceClause { InheritedType(typeName: Type("SyntaxRewriter")) }) {
VariableDecl("public var indentationLevel: Int = 0")
VariableDecl("open var indentation: TriviaPiece { .spaces(indentationLevel * 4) }")
VariableDecl("public var indentedNewline: Trivia { Trivia(pieces: [.newlines(1), indentation]) }")
Expand All @@ -40,15 +40,15 @@ let basicFormatFile = SourceFile {
}
}

private func createChildVisitCall(childType: SyntaxBuildableType, rewrittenExpr: ExprBuildable) -> ExprBuildable {
private func createChildVisitCall(childType: SyntaxBuildableType, rewrittenExpr: ExprSyntaxProtocol) -> FunctionCallExpr {
let visitCall: FunctionCallExpr
if childType.isOptional {
visitCall = FunctionCallExpr("\(rewrittenExpr).map(self.visit)")
} else {
visitCall = FunctionCallExpr("self.visit(\(rewrittenExpr))")
}
if childType.baseType?.baseName != "Syntax", childType.baseType?.isSyntaxCollection != true, childType.baseType != nil {
let optionalChained = childType.optionalChained(expr: visitCall).createExprBuildable()
let optionalChained = childType.optionalChained(expr: visitCall)
return FunctionCallExpr("\(optionalChained).cast(\(childType.syntaxBaseName).self)")
} else {
return visitCall
Expand All @@ -64,19 +64,19 @@ private func makeLayoutNodeRewriteFunc(node: Node) -> FunctionDecl {
}
return FunctionDecl(
leadingTrivia: .newline,
modifiers: [Token.open, Token(tokenSyntax: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
modifiers: [DeclModifier(name: .open), DeclModifier(name: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
identifier: .identifier("visit"),
signature: FunctionSignature(
input: ParameterClause(parameterList: [
FunctionParameter(
firstName: Token.wildcard,
secondName: .identifier("node"),
colon: .colon,
type: node.type.syntaxBaseName
type: Type(node.type.syntaxBaseName)

)
]),
output: rewriteResultType
output: ReturnClause(returnType: Type(rewriteResultType))
)
) {
for child in node.children {
Expand All @@ -98,11 +98,11 @@ private func makeLayoutNodeRewriteFunc(node: Node) -> FunctionDecl {
SequenceExpr("indentationLevel -= 1")
}
}
let reconstructed = FunctionCallExpr(calledExpression: "\(node.type.syntaxBaseName)") {
let reconstructed = FunctionCallExpr(calledExpression: Expr("\(node.type.syntaxBaseName)")) {
for child in node.children {
TupleExprElement(
label: child.isUnexpectedNodes ? nil : child.swiftName,
expression: child.swiftName
expression: Expr(child.swiftName)
)
}
}
Expand All @@ -118,19 +118,19 @@ private func makeSyntaxCollectionRewriteFunc(node: Node) -> FunctionDecl {
let rewriteResultType = node.type.syntaxBaseName
return FunctionDecl(
leadingTrivia: .newline,
modifiers: [Token.open, Token(tokenSyntax: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
modifiers: [DeclModifier(name: .open), DeclModifier(name: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
identifier: .identifier("visit"),
signature: FunctionSignature(
input: ParameterClause(parameterList: [
FunctionParameter(
firstName: Token.wildcard,
secondName: .identifier("node"),
colon: .colon,
type: node.type.syntaxBaseName
type: Type(node.type.syntaxBaseName)

)
]),
output: rewriteResultType
output: ReturnClause(returnType: Type(rewriteResultType))
)
) {
let formattedChildrenVarLet = node.elementsSeparatedByNewline ? "var" : "let"
Expand Down Expand Up @@ -161,26 +161,26 @@ private func makeSyntaxCollectionRewriteFunc(node: Node) -> FunctionDecl {
private func createTokenFormatFunction() -> FunctionDecl {
return FunctionDecl(
leadingTrivia: .newline,
modifiers: [Token.open, Token(tokenSyntax: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
modifiers: [DeclModifier(name: .open), DeclModifier(name: TokenSyntax.contextualKeyword("override", trailingTrivia: .space))],
identifier: .identifier("visit"),
signature: FunctionSignature(
input: ParameterClause(parameterList: [
FunctionParameter(
firstName: Token.wildcard,
secondName: .identifier("node"),
colon: .colon,
type: "TokenSyntax"
type: Type("TokenSyntax")

)
]),
output: "TokenSyntax"
output: ReturnClause(returnType: Type("TokenSyntax"))
)
) {
VariableDecl("var leadingTrivia = node.leadingTrivia")
VariableDecl("var trailingTrivia = node.trailingTrivia")
SwitchStmt(expression: MemberAccessExpr(base: "node", name: "tokenKind")) {
for token in SYNTAX_TOKENS where token.name != "ContextualKeyword" {
SwitchCase(label: SwitchCaseLabel(caseItems: CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: token.swiftKind))))) {
SwitchCase(label: SwitchCaseLabel(caseItems: [CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: token.swiftKind)))])) {
if token.requiresLeadingSpace {
IfStmt(
"""
Expand All @@ -204,10 +204,10 @@ private func createTokenFormatFunction() -> FunctionDecl {
}
}
}
SwitchCase(label: SwitchCaseLabel(caseItems: CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: "eof"))))) {
SwitchCase(label: SwitchCaseLabel(caseItems: [CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: "eof")))])) {
BreakStmt("break")
}
SwitchCase(label: SwitchCaseLabel(caseItems: CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: "contextualKeyword"))))) {
SwitchCase(label: SwitchCaseLabel(caseItems: [CaseItem(pattern: ExpressionPattern(expression: MemberAccessExpr(name: "contextualKeyword")))])) {
SwitchStmt(
"""
switch node.text {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import SwiftBasicFormat
let buildableCollectionNodesFile = SourceFile {
ImportDecl(
leadingTrivia: .docLineComment(copyrightHeader),
path: "SwiftSyntax"
path: [AccessPathComponent(name: "SwiftSyntax")]
)

for node in SYNTAX_NODES where node.isSyntaxCollection {
Expand All @@ -31,8 +31,8 @@ let buildableCollectionNodesFile = SourceFile {
leadingTrivia: node.documentation.isEmpty
? []
: .docLineComment("/// \(node.documentation)") + .newline,
extendedType: node.type.shorthandName,
inheritanceClause: TypeInheritanceClause { InheritedType(typeName: "ExpressibleByArrayLiteral") }
extendedType: Type(node.type.shorthandName),
inheritanceClause: TypeInheritanceClause { InheritedType(typeName: Type("ExpressibleByArrayLiteral")) }
) {
// Generate initializers
if elementType.isBaseType {
Expand Down
Loading