Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,14 @@ struct ChildNodeChoices {
}
}

func syntaxGetter(propertyName: TokenSyntax, propertyType: TypeSyntax) -> VariableDeclSyntax {
try! VariableDeclSyntax("public var \(propertyName.declNameOrVarCallName): \(propertyType)") {
func syntaxGetter(
propertyName: TokenSyntax,
propertyType: TypeSyntax,
attributes: String = ""
) -> VariableDeclSyntax {
try! VariableDeclSyntax(
"\(raw: attributes)public var \(propertyName.declNameOrVarCallName): \(propertyType)"
) {
try! SwitchExprSyntax("switch self") {
for choice in self.choices {
SwitchCaseSyntax("case .\(choice.enumCaseCallName)(let node):") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private let swiftParserGeneratedDir = ["SwiftParser", generatedDirName]
private let swiftParserDiagnosticsGeneratedDir = ["SwiftParserDiagnostics", generatedDirName]
private let swiftSyntaxGeneratedDir = ["SwiftSyntax", generatedDirName]
private let swiftSyntaxBuilderGeneratedDir = ["SwiftSyntaxBuilder", generatedDirName]
private let swiftSyntaxTestSupportGeneratedDir = ["_SwiftSyntaxTestSupport", generatedDirName]
private let BASE_KIND_FILES: [SyntaxNodeKind: String] = [
.decl: "SyntaxDeclNodes.swift",
.expr: "SyntaxExprNodes.swift",
Expand Down Expand Up @@ -115,7 +116,7 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {
),

// SwiftSyntax
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["ChildNameForKeyPath.swift"], childNameForKeyPathFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["ConcreteSyntaxProperty.swift"], concreteSyntaxPropertyFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["Keyword.swift"], keywordFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["raw", "RawSyntaxValidation.swift"], rawSyntaxValidationFile),
GeneratedFileSpec(
Expand All @@ -128,6 +129,7 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxCollections.swift"], syntaxCollectionsFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxEnum.swift"], syntaxEnumFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxKind.swift"], syntaxKindFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxLayoutNodes.swift"], syntaxLayoutNodesFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxRewriter.swift"], syntaxRewriterFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxTraits.swift"], syntaxTraitsFile),
GeneratedFileSpec(
Expand All @@ -151,6 +153,9 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {
swiftSyntaxBuilderGeneratedDir + ["RenamedChildrenBuilderCompatibility.swift"],
renamedChildrenBuilderCompatibilityFile
),

// _SwiftSyntaxTestSupport
GeneratedFileSpec(swiftSyntaxTestSupportGeneratedDir + ["ChildChoicesTypeName.swift"], childChoicesTypeNameFile),
]
// This split of letters produces files for the syntax nodes that have about equal size, which improves compile time

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftSyntax
import SwiftSyntaxBuilder

/// Wraps `decl` in the compilation condition that gates the static node structure reflection
/// API, `SyntaxProtocol.structure` and `SyntaxProtocol.keyPathInParent`.
///
/// Building with `-DSWIFTSYNTAX_NO_STRUCTURE_REFLECTION` drops that API, along with the key
/// paths and metatypes it keeps alive.
func ifStructureReflectionEnabled(_ decl: DeclSyntax) -> DeclSyntax {
return DeclSyntax(
"""
#if !SWIFTSYNTAX_NO_STRUCTURE_REFLECTION
\(decl)
#endif
"""
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftSyntax
import SwiftSyntaxBuilder

/// The 'SyntaxProtocol._syntaxDataRef' witness for a node type that stores its
/// '_syntaxNode'.
///
/// Reading the trivial reference out of the stored property borrows it, so unlike the
/// default implementation this doesn't retain and release the arena.
let syntaxDataRefDecl: DeclSyntax = DeclSyntax(
"""
@_spi(RawSyntax)
public var _syntaxDataRef: SyntaxDataRef {
return SyntaxDataRef(_syntaxNode.dataRef)
}
"""
)
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ let layoutNodesParsableFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
}

try! VariableDeclSyntax(
"""
/// Every layout node that conforms to ``SyntaxParseable``.
///
/// ``syntaxParseableTypes`` combines this with the collection nodes that conform to
/// ``SyntaxParseable``.
@_spi(Testing)
public var layoutNodeSyntaxParseableTypes: [SyntaxParseable.Type]
"""
) {
ArrayExprSyntax {
for node in SYNTAX_NODES where node.parserFunction != nil {
ArrayElementSyntax(expression: ExprSyntax("\(node.kind.syntaxType).self"))
}
}
}

try! ExtensionDeclSyntax("fileprivate extension Parser") {
DeclSyntax(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ let childNameForDiagnosticFile = SourceFileSyntax(leadingTrivia: copyrightHeader
importSwiftSyntax(accessLevel: .internal)

try! FunctionDeclSyntax(
"private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String?"
"private func childNameForDiagnostics(_ property: SyntaxLayoutProperty) -> String?"
) {
try! SwitchExprSyntax("switch keyPath") {
try! SwitchExprSyntax("switch property") {
for node in NON_BASE_SYNTAX_NODES.compactMap(\.layoutNode) {
for child in node.children {
if let nameForDiagnostics = child.nameForDiagnostics {
SwitchCaseSyntax("case \\\(node.type.syntaxBaseName).\(child.memberCallName):") {
SwitchCaseSyntax("case \(node.type.syntaxBaseName).layout[.\(child.memberCallName)]:") {
StmtSyntax(#"return "\#(raw: nameForDiagnostics)""#)
}
}
Expand All @@ -44,10 +44,10 @@ let childNameForDiagnosticFile = SourceFileSyntax(leadingTrivia: copyrightHeader
"""
extension SyntaxProtocol {
var childNameInParent: String? {
guard let keyPath = self.keyPathInParent else {
guard let property = self.propertyInParent else {
return nil
}
return childNameForDiagnostics(keyPath)
return childNameForDiagnostics(property)
}
}
"""
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftSyntax
import SwiftSyntaxBuilder
import SyntaxSupport
import Utils

let concreteSyntaxPropertyFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
DeclSyntax(
"""
extension ConcreteSyntaxProperty {
fileprivate init(index: UInt32) {
self.index = .init(index)
}
}
"""
)

for node in NON_BASE_SYNTAX_NODES {
if let layoutNode = node.layoutNode {
try! ExtensionDeclSyntax(
"\(node.apiAttributes())extension ConcreteSyntaxProperty where Base == \(node.kind.syntaxType)"
) {
for (index, child) in layoutNode.children.enumerated() {
let childType: TypeSyntax =
child.kind.isNodeChoicesEmpty
? child.syntaxNodeKind.syntaxType
: "\(node.kind.syntaxType).\(child.syntaxChoicesType)"
let type = child.isOptional ? TypeSyntax("\(childType)?") : TypeSyntax("\(childType)")
DeclSyntax(
"""
\(child.apiAttributes)public static var \(child.varDeclName): ConcreteSyntaxProperty<\(node.kind.syntaxType), \(type)> {
.init(index: \(raw: index))
}
"""
)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
) {
DeclSyntax("public let _syntaxNode: Syntax")

syntaxDataRefDecl

DeclSyntax(
"""
/// Create a \(raw: node.kind.doccLink) node from a specialized syntax node.
Expand Down Expand Up @@ -271,18 +273,22 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
"""
)

try VariableDeclSyntax("public static var structure: SyntaxNodeStructure") {
let choices = ArrayExprSyntax {
for childNode in SYNTAX_NODES where childNode.base == node.kind {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(\(childNode.kind.syntaxType).self)")
)
}
}
ifStructureReflectionEnabled(
DeclSyntax(
try VariableDeclSyntax("public static var structure: SyntaxNodeStructure") {
let choices = ArrayExprSyntax {
for childNode in SYNTAX_NODES where childNode.base == node.kind {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(\(childNode.kind.syntaxType).self)")
)
}
}

StmtSyntax("return .choices(\(choices))")
}
StmtSyntax("return .choices(\(choices))")
}
)
)
}

leafProtocolDecl(type: node.kind.leafProtocolType, inheritedType: node.kind.protocolType)
Expand All @@ -296,23 +302,27 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
extension Syntax
"""
) {
try VariableDeclSyntax("public static var structure: SyntaxNodeStructure") {
let choices = ArrayExprSyntax {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(TokenSyntax.self)")
)
ifStructureReflectionEnabled(
DeclSyntax(
try VariableDeclSyntax("public static var structure: SyntaxNodeStructure") {
let choices = ArrayExprSyntax {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(TokenSyntax.self)")
)

for node in NON_BASE_SYNTAX_NODES {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(\(node.kind.syntaxType).self)")
)
}
}
for node in NON_BASE_SYNTAX_NODES {
ArrayElementSyntax(
leadingTrivia: .newline,
expression: ExprSyntax(".node(\(node.kind.syntaxType).self)")
)
}
}

StmtSyntax("return .choices(\(choices))")
}
StmtSyntax("return .choices(\(choices))")
}
)
)
}

leafProtocolDecl(type: "_LeafSyntaxNodeProtocol", inheritedType: "SyntaxProtocol")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {

DeclSyntax("public let _syntaxNode: Syntax")

syntaxDataRefDecl

DeclSyntax(
"""
public init?(_ node: some SyntaxProtocol) {
Expand Down
Loading
Loading