Skip to content
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

[Syntax] Introduce SyntaxLayout #2824

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
13 changes: 0 additions & 13 deletions CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -376,19 +376,6 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
return "\(syntaxType)Protocol"
}

/// For base node types, generates the name of the protocol to which all
/// concrete leaf nodes that derive from this base kind should conform.
///
/// - Warning: This property can only be accessed for base node kinds; attempting to
/// access it for a non-base kind will result in a runtime error.
public var leafProtocolType: TypeSyntax {
if isBase {
return "_Leaf\(syntaxType)NodeProtocol"
} else {
fatalError("Only base kind can define leaf protocol")
}
}

/// If the syntax kind has been renamed, the previous raw value that is now
/// deprecated.
public var deprecatedRawValue: String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,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 +128,7 @@ struct GenerateSwiftSyntax: AsyncParsableCommand {
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxCollections.swift"], syntaxCollectionsFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxEnum.swift"], syntaxEnumFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxKind.swift"], syntaxKindFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxLayoutPropertyName.swift"], syntaxLayoutPropertyNameFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxRewriter.swift"], syntaxRewriterFile),
GeneratedFileSpec(swiftSyntaxGeneratedDir + ["SyntaxTraits.swift"], syntaxTraitsFile),
GeneratedFileSpec(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ let childNameForDiagnosticFile = SourceFileSyntax(leadingTrivia: copyrightHeader
)

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 @@ -52,10 +52,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: Int) {
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(
"""
public static var \(child.varDeclName): ConcreteSyntaxProperty<\(node.kind.syntaxType), \(type)> {
.init(\(raw: index))
}
"""
)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,7 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
}

leafProtocolDecl(type: node.kind.leafProtocolType, inheritedType: node.kind.protocolType)
leafProtocolExtension(type: node.kind.leafProtocolType, inheritedType: node.kind.protocolType)
leafProtocolExtension(inheritedType: node.kind.protocolType)
}

try! ExtensionDeclSyntax(
Expand Down Expand Up @@ -317,27 +316,13 @@ let syntaxBaseNodesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
}

leafProtocolDecl(type: "_LeafSyntaxNodeProtocol", inheritedType: "SyntaxProtocol")
leafProtocolExtension(type: "_LeafSyntaxNodeProtocol", inheritedType: "SyntaxProtocol")
leafProtocolExtension(inheritedType: "SyntaxProtocol")
}

private func leafProtocolDecl(type: TypeSyntax, inheritedType: TypeSyntax) -> DeclSyntax {
DeclSyntax(
"""
/// Protocol that syntax nodes conform to if they don't have any semantic subtypes.
/// These are syntax nodes that are not considered base nodes for other syntax types.
///
/// Syntax nodes conforming to this protocol have their inherited casting methods
/// deprecated to prevent incorrect casting.
public protocol \(type): \(inheritedType) {}
"""
)
}

private func leafProtocolExtension(type: TypeSyntax, inheritedType: TypeSyntax) -> DeclSyntax {
DeclSyntax(
private func leafProtocolExtension(inheritedType: TypeSyntax) -> DeclSyntax {
return DeclSyntax(
#"""
extension \#(type) {
extension _LeafSyntaxNodeProtocol where Self: \#(inheritedType) {
/// Checks if the current leaf syntax node can be cast to a different specified type.
///
/// - Returns: `false` since the leaf node cannot be cast to a different specified type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
"""
)

DeclSyntax("public static let syntaxKind = SyntaxKind.\(node.memberCallName)")
DeclSyntax("public static var syntaxKind: SyntaxKind { .\(node.enumCaseCallName) }")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ let syntaxKindFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
}
}

try VariableDeclSyntax("public var isLayout: Bool") {
try SwitchExprSyntax("switch self") {
for node in SYNTAX_NODES where node.layoutNode != nil {
SwitchCaseSyntax("case .\(node.enumCaseCallName):") {
StmtSyntax("return true")
}
}

SwitchCaseSyntax("default:") {
StmtSyntax("return false")
}
}
}

try VariableDeclSyntax("public var isMissing: Bool") {
try SwitchExprSyntax("switch self") {
for name in SyntaxNodeKind.allCases where name.isMissing {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// 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 syntaxLayoutPropertyNameFile = try! SourceFileSyntax(leadingTrivia: copyrightHeader) {
try ExtensionDeclSyntax("extension SyntaxLayoutProperty") {
try VariableDeclSyntax(
"""
/// Property name if this is a valid property.
/// 'nil' if the `syntaxKind` is not a layout syntax, or the index is out of range.
@_spi(RawSyntax)
public var name: String?
"""
) {
try SwitchExprSyntax("switch (self.syntaxKind, self.index.value)") {
for node in NON_BASE_SYNTAX_NODES {
if let layoutNode = node.layoutNode {
for (index, child) in layoutNode.children.enumerated() {
SwitchCaseSyntax("case (.\(node.enumCaseCallName), \(literal: index)):") {
StmtSyntax("return \(literal: child.identifier.description)")
}
}
}
}
SwitchCaseSyntax("default: return nil")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax {

\(SwiftSyntax.Trivia(joining: [node.documentation, node.experimentalDocNote, node.grammar, node.containedIn]))\
\(node.node.apiAttributes())\
public struct \(node.kind.syntaxType): \(node.baseType.syntaxBaseName)Protocol, SyntaxHashable, \(node.base.leafProtocolType)
public struct \(node.kind.syntaxType): \(node.baseType.syntaxBaseName)Protocol, SyntaxHashable, _LayoutSyntaxNodeProtocol
"""
) {
for childNodeChoices in node.node.childrenNodeChoices() {
Expand Down Expand Up @@ -208,6 +208,12 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax {
}
}

// ========
// Metadata
// ========

DeclSyntax("public static var syntaxKind: SyntaxKind { .\(node.enumCaseCallName) }")

let layout = ArrayExprSyntax {
for child in node.children {
ArrayElementSyntax(
Expand Down
Loading