Skip to content

Add Syntax nodes for compiler generated files #2968

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
Feb 22, 2025
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
26 changes: 0 additions & 26 deletions CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,30 +181,4 @@ public let AVAILABILITY_NODES: [Node] = [
),
]
),

Node(
kind: .availabilityMacroDefinition,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "availability macro definition",
documentation: "Syntax for '-define-availability' compiler arguments, never appear in Swift source code",
parserFunction: "parseAvailabilityMacroDefinition",
children: [
Child(
name: "platformVersion",
kind: .node(kind: .platformVersion)
),
Child(
name: "colon",
kind: .token(choices: [.token(.colon)])
),
Child(
name: "specs",
kind: .collection(
kind: .availabilityArgumentList,
collectionElementName: "AvailabilityArgument"
)
),
]
),
]
2 changes: 1 addition & 1 deletion CodeGeneration/Sources/SyntaxSupport/Child.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public enum ChildKind {
/// The child is a collection of `kind`.
case collection(
kind: SyntaxNodeKind,
collectionElementName: String,
collectionElementName: String? = nil,
defaultsToEmpty: Bool = false,
deprecatedCollectionElementName: String? = nil
)
Expand Down
147 changes: 147 additions & 0 deletions CodeGeneration/Sources/SyntaxSupport/CompilerNodes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

public let COMPILER_NODES: [Node] = [
Node(
kind: .availabilityMacroDefinitionFile,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "availability macro definition",
documentation: """
Syntax for '-define-availability' compiler arguments, never appear in Swift source code.
""",
parserFunction: "parseAvailabilityMacroDefinitionFile",
children: [
Child(
name: "platformVersion",
kind: .node(kind: .platformVersion)
),
Child(
name: "colon",
kind: .token(choices: [.token(.colon)])
),
Child(
name: "specs",
kind: .collection(kind: .availabilityArgumentList)
),
Child(
name: "endOfFileToken",
kind: .token(choices: [.token(.endOfFile)])
),
]
),

Node(
kind: .accessorBlockFile,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "accessors",
documentation: """
Syntax for 'accessor' macro expansion, never appear in Swift source code.
""",
parserFunction: "parseAccessorBlockFile",
children: [
Child(
name: "leftBrace",
kind: .token(choices: [.token(.leftBrace)]),
isOptional: true
),
Child(
name: "accessors",
kind: .collection(kind: .accessorDeclList)
),
Child(
name: "rightBrace",
kind: .token(choices: [.token(.rightBrace)]),
isOptional: true
),
Child(
name: "endOfFileToken",
kind: .token(choices: [.token(.endOfFile)])
),
]
),

Node(
kind: .attributeClauseFile,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "attribute list",
documentation: """
Syntax for 'memberAttribute' macro expansion or 'swift_attr' attribute in Clang, never appear in Swift source code.
""",
parserFunction: "parseAttributeClauseFile",
traits: [
"WithAttributes",
"WithModifiers",
],
children: [
Child(
name: "attributes",
kind: .collection(
kind: .attributeList,
collectionElementName: "Attribute"
)
),
Child(
name: "modifiers",
kind: .collection(kind: .declModifierList)
),
Child(
name: "endOfFileToken",
kind: .token(choices: [.token(.endOfFile)])
),
]
),

Node(
kind: .codeBlockFile,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "code block",
documentation: """
Syntax for 'body' macro expansions, never appear in Swift source code.
""",
parserFunction: "parseCodeBlockFile",
children: [
Child(
name: "body",
kind: .node(kind: .codeBlock)
),
Child(
name: "endOfFileToken",
kind: .token(choices: [.token(.endOfFile)])
),
]
),

Node(
kind: .memberBlockItemListFile,
base: .syntax,
spi: "Compiler",
nameForDiagnostics: "member list",
documentation: """
Syntax for declaration macro expansions in type contexts, never appear in Swift source code.
""",
parserFunction: "parseMemberBlockItemListFile",
children: [
Child(
name: "members",
kind: .collection(kind: .memberBlockItemList)
),
Child(
name: "endOfFileToken",
kind: .token(choices: [.token(.endOfFile)])
),
]
),
]
6 changes: 5 additions & 1 deletion CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
case _canImportVersionInfo
case abiAttributeArguments
case accessorBlock
case accessorBlockFile
case accessorDecl
case accessorDeclList
case accessorEffectSpecifiers
Expand All @@ -39,12 +40,13 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
case associatedTypeDecl
case attribute
case attributedType
case attributeClauseFile
case attributeList
case availabilityArgument
case availabilityArgumentList
case availabilityCondition
case availabilityLabeledArgument
case availabilityMacroDefinition
case availabilityMacroDefinitionFile
case awaitExpr
case backDeployedAttributeArguments
case binaryOperatorExpr
Expand All @@ -69,6 +71,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
case closureShorthandParameterList
case closureSignature
case codeBlock
case codeBlockFile
case codeBlockItem
case codeBlockItemList
case compositionType
Expand Down Expand Up @@ -195,6 +198,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon
case memberBlock
case memberBlockItem
case memberBlockItemList
case memberBlockItemListFile
case memberType
case metatypeType
case missing
Expand Down
1 change: 1 addition & 0 deletions CodeGeneration/Sources/SyntaxSupport/SyntaxNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private let unsortedSyntaxNodes: [Node] =
+ TYPE_NODES
+ PATTERN_NODES
+ AVAILABILITY_NODES
+ COMPILER_NODES

public let SYNTAX_NODES: [Node] =
unsortedSyntaxNodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,10 @@ func makeCompatibilityAddMethod(for child: Child) -> DeclSyntax? {
!child.isUnexpectedNodes,
case .collection(
kind: _,
collectionElementName: let collectionElementName,
collectionElementName: let collectionElementName?,
defaultsToEmpty: _,
deprecatedCollectionElementName: let deprecatedCollectionElementName
) = child.kind,
let deprecatedCollectionElementName
deprecatedCollectionElementName: let deprecatedCollectionElementName?
) = child.kind
{
let childEltType = childNode.collectionElementType.syntaxBaseName

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax {
// If needed, this could be added in the future, but for now withUnexpected should be sufficient.
if let childNode = SYNTAX_NODE_MAP[child.syntaxNodeKind]?.collectionNode,
!child.isUnexpectedNodes,
case .collection(_, collectionElementName: let childElt, _, _) = child.kind
case .collection(_, collectionElementName: let childElt?, _, _) = child.kind
{
let childEltType = childNode.collectionElementType.syntaxBaseName

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,26 @@ class ValidateSyntaxNodes: XCTestCase {
node: .sourceFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .availabilityMacroDefinitionFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .accessorBlockFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .attributeClauseFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .codeBlockFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .memberBlockItemListFile,
message: "child 'endOfFileToken' has a token as its only token choice and should thus be named 'endOfFile'"
),
ValidationFailure(
node: .stringLiteralExpr,
message:
Expand Down Expand Up @@ -549,6 +569,7 @@ class ValidateSyntaxNodes: XCTestCase {
message: "could conform to trait 'Parenthesized' but does not"
),
ValidationFailure(node: .lifetimeTypeSpecifier, message: "could conform to trait 'Parenthesized' but does not"),
ValidationFailure(node: .codeBlockFile, message: "could conform to trait 'WithCodeBlock' but does not"),
]
)
}
Expand All @@ -573,7 +594,27 @@ class ValidateSyntaxNodes: XCTestCase {
failures,
expectedFailures: [
// it's not obvious that the end of file is represented by a token, thus its good to highlight it in the name
ValidationFailure(node: .sourceFile, message: "child 'endOfFileToken' should not end with 'Token'")
ValidationFailure(node: .sourceFile, message: "child 'endOfFileToken' should not end with 'Token'"),
ValidationFailure(
node: .availabilityMacroDefinitionFile,
message: "child 'endOfFileToken' should not end with 'Token'"
),
ValidationFailure(
node: .accessorBlockFile,
message: "child 'endOfFileToken' should not end with 'Token'"
),
ValidationFailure(
node: .attributeClauseFile,
message: "child 'endOfFileToken' should not end with 'Token'"
),
ValidationFailure(
node: .codeBlockFile,
message: "child 'endOfFileToken' should not end with 'Token'"
),
ValidationFailure(
node: .memberBlockItemListFile,
message: "child 'endOfFileToken' should not end with 'Token'"
),
]
)
}
Expand Down Expand Up @@ -758,14 +799,21 @@ class ValidateSyntaxNodes: XCTestCase {
failures.append(
ValidationFailure(
node: node.kind,
message:
"non-collection node should not contain 'List'"
message: "non-collection node should not contain 'List'"
)
)
}
}

assertFailuresMatchXFails(failures, expectedFailures: [])
assertFailuresMatchXFails(
failures,
expectedFailures: [
ValidationFailure(
node: .memberBlockItemListFile,
message: "non-collection node should not contain 'List'"
)
]
)
}

/// Children should always have a plural as their name instead of ending with 'List'.
Expand Down
17 changes: 0 additions & 17 deletions Sources/SwiftParser/Availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -304,20 +304,3 @@ extension Parser {
}
}
}

extension Parser {
/// Parse an argument for '-define-availability' compiler option.
mutating func parseAvailabilityMacroDefinition() -> RawAvailabilityMacroDefinitionSyntax {
let namedAndVersion = self.parsePlatformVersion(allowStarAsVersionNumber: false)
let (unexpectedBetweenPlatformVersionAndColon, colon) = self.expect(.colon)
let specs = self.parseAvailabilitySpecList()

return RawAvailabilityMacroDefinitionSyntax(
platformVersion: namedAndVersion,
unexpectedBetweenPlatformVersionAndColon,
colon: colon,
specs: specs,
arena: self.arena
)
}
}
1 change: 1 addition & 0 deletions Sources/SwiftParser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_swift_syntax_library(SwiftParser
Availability.swift
CharacterInfo.swift
CollectionNodes+Parsable.swift
CompilerFiles.swift
Declarations.swift
Directives.swift
ExpressionInterpretedAsVersionTuple.swift
Expand Down
Loading