From 785547e412c1f75aa1ed24f77c1191b9c38a8111 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 24 Apr 2025 20:39:38 -0700 Subject: [PATCH 01/10] Make `@abi` non-experimental --- .../SyntaxSupport/AttributeNodes.swift | 4 +- .../SyntaxSupport/ExperimentalFeatures.swift | 5 - .../Sources/SyntaxSupport/KeywordSpec.swift | 2 +- Sources/SwiftParser/Attributes.swift | 24 ++-- .../generated/ExperimentalFeatures.swift | 11 +- .../generated/SwiftSyntax.md | 1 + Sources/SwiftSyntax/generated/Keyword.swift | 1 - .../generated/SyntaxAnyVisitor.swift | 2 - .../SwiftSyntax/generated/SyntaxEnum.swift | 1 - .../SwiftSyntax/generated/SyntaxKind.swift | 1 - .../generated/SyntaxRewriter.swift | 3 +- .../SwiftSyntax/generated/SyntaxVisitor.swift | 6 +- .../generated/raw/RawSyntaxNodesAB.swift | 3 - .../generated/syntaxNodes/SyntaxNodesAB.swift | 29 ++-- .../generated/syntaxNodes/SyntaxNodesD.swift | 4 + .../generated/syntaxNodes/SyntaxNodesEF.swift | 8 ++ .../syntaxNodes/SyntaxNodesGHI.swift | 4 + .../syntaxNodes/SyntaxNodesJKLMN.swift | 4 + .../syntaxNodes/SyntaxNodesQRS.swift | 4 + .../syntaxNodes/SyntaxNodesTUVWXYZ.swift | 8 ++ Tests/SwiftParserTest/AttributeTests.swift | 124 ++++-------------- 21 files changed, 86 insertions(+), 163 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index 26041a0cf89..3347cf8bb41 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -122,8 +122,7 @@ public let ATTRIBUTE_NODES: [Node] = [ Child( name: "abiArguments", // Special arguments for declaration syntax. e.g. @abi(func abiName() -> Int) - kind: .node(kind: .abiAttributeArguments), - experimentalFeature: .abiAttribute + kind: .node(kind: .abiAttributeArguments) ), ]), documentation: """ @@ -256,7 +255,6 @@ public let ATTRIBUTE_NODES: [Node] = [ Node( kind: .abiAttributeArguments, base: .syntax, - experimentalFeature: .abiAttribute, nameForDiagnostics: "ABI-providing declaration", documentation: "The arguments of the '@abi' attribute", children: [ diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index bdc09c1f462..aa36cd8ba53 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -19,7 +19,6 @@ public enum ExperimentalFeature: String, CaseIterable { case nonescapableTypes case trailingComma case coroutineAccessors - case abiAttribute case keypathWithMethodMembers case oldOwnershipOperatorSpellings case inlineArrayTypeSugar @@ -39,8 +38,6 @@ public enum ExperimentalFeature: String, CaseIterable { return "TrailingComma" case .coroutineAccessors: return "CoroutineAccessors" - case .abiAttribute: - return "ABIAttribute" case .keypathWithMethodMembers: return "KeypathWithMethodMembers" case .oldOwnershipOperatorSpellings: @@ -65,8 +62,6 @@ public enum ExperimentalFeature: String, CaseIterable { return "trailing commas" case .coroutineAccessors: return "coroutine accessors" - case .abiAttribute: - return "@abi attribute" case .keypathWithMethodMembers: return "keypaths with method members" case .oldOwnershipOperatorSpellings: diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 7c4b72eeafb..1a32f708965 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -357,7 +357,7 @@ public enum Keyword: CaseIterable { case ._version: return KeywordSpec("_version") case .abi: - return KeywordSpec("abi", experimentalFeature: .abiAttribute) + return KeywordSpec("abi") case .accesses: return KeywordSpec("accesses") case .actor: diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index 3cfc6ae801d..c29fa786846 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -230,9 +230,9 @@ extension Parser { switch peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) { case .abi: return parseAttribute(argumentMode: .required) { parser in - return parser.parseABIAttributeArguments() + return (nil, .abiArguments(parser.parseABIAttributeArguments())) } parseMissingArguments: { parser in - return parser.parseABIAttributeArguments(missingLParen: true) + return (nil, .abiArguments(parser.parseABIAttributeArguments(missingLParen: true))) } case .available, ._spi_available: return parseAttribute(argumentMode: .required) { parser in @@ -794,9 +794,9 @@ extension Parser { /// - Parameter missingLParen: `true` if the opening paren for the argument list was missing. mutating func parseABIAttributeArguments( missingLParen: Bool = false - ) -> (RawUnexpectedNodesSyntax?, RawAttributeSyntax.Arguments) { - func makeMissingProviderArguments(unexpectedBefore: [RawSyntax]) -> RawAttributeSyntax.Arguments { - let args = RawABIAttributeArgumentsSyntax( + ) -> RawABIAttributeArgumentsSyntax { + func makeMissingProviderArguments(unexpectedBefore: [RawSyntax]) -> RawABIAttributeArgumentsSyntax { + return RawABIAttributeArgumentsSyntax( provider: .missing( RawMissingDeclSyntax( unexpectedBefore.isEmpty ? nil : RawUnexpectedNodesSyntax(elements: unexpectedBefore, arena: self.arena), @@ -808,7 +808,6 @@ extension Parser { ), arena: self.arena ) - return .abiArguments(args) } // Consider the three kinds of mistakes we might see here: @@ -824,23 +823,16 @@ extension Parser { // In lieu of that, we judge that recovering gracefully from #3 is more important than #2 and therefore do not even // attempt to parse the argument unless we've seen a left paren. guard !missingLParen && !self.at(.rightParen) else { - return (nil, makeMissingProviderArguments(unexpectedBefore: [])) + return makeMissingProviderArguments(unexpectedBefore: []) } let decl = parseDeclaration(in: .argumentList) - guard experimentalFeatures.contains(.abiAttribute) else { - return ( - RawUnexpectedNodesSyntax([decl], arena: self.arena), - .argumentList(RawLabeledExprListSyntax(elements: [], arena: self.arena)) - ) - } - guard let provider = RawABIAttributeArgumentsSyntax.Provider(decl) else { - return (nil, makeMissingProviderArguments(unexpectedBefore: [decl.raw])) + return makeMissingProviderArguments(unexpectedBefore: [decl.raw]) } - return (nil, .abiArguments(RawABIAttributeArgumentsSyntax(provider: provider, arena: self.arena))) + return RawABIAttributeArgumentsSyntax(provider: provider, arena: self.arena) } } diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index 77c5206bb99..9513b06aac7 100644 --- a/Sources/SwiftParser/generated/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -43,17 +43,14 @@ extension Parser.ExperimentalFeatures { /// Whether to enable the parsing of coroutine accessors. public static let coroutineAccessors = Self (rawValue: 1 << 5) - /// Whether to enable the parsing of @abi attribute. - public static let abiAttribute = Self (rawValue: 1 << 6) - /// Whether to enable the parsing of keypaths with method members. - public static let keypathWithMethodMembers = Self (rawValue: 1 << 7) + public static let keypathWithMethodMembers = Self (rawValue: 1 << 6) /// Whether to enable the parsing of `_move` and `_borrow` as ownership operators. - public static let oldOwnershipOperatorSpellings = Self (rawValue: 1 << 8) + public static let oldOwnershipOperatorSpellings = Self (rawValue: 1 << 7) /// Whether to enable the parsing of sugar type for InlineArray. - public static let inlineArrayTypeSugar = Self (rawValue: 1 << 9) + public static let inlineArrayTypeSugar = Self (rawValue: 1 << 8) /// Creates a new value representing the experimental feature with the /// given name, or returns nil if the name is not recognized. @@ -71,8 +68,6 @@ extension Parser.ExperimentalFeatures { self = .trailingComma case "CoroutineAccessors": self = .coroutineAccessors - case "ABIAttribute": - self = .abiAttribute case "KeypathWithMethodMembers": self = .keypathWithMethodMembers case "OldOwnershipOperatorSpellings": diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index 4ec126dbe4f..ee9216345d3 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -303,6 +303,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. ### Attributes +- - - - diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 20b36ff1455..6f049eb7936 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -54,7 +54,6 @@ public enum Keyword: UInt8, Hashable, Sendable { case _underlyingVersion case _UnknownLayout case _version - @_spi(ExperimentalLanguageFeatures) case abi case accesses case actor diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 124561440e0..761e69e41d9 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -57,12 +57,10 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } - @_spi(ExperimentalLanguageFeatures) override open func visit(_ node: ABIAttributeArgumentsSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } - @_spi(ExperimentalLanguageFeatures) override open func visitPost(_ node: ABIAttributeArgumentsSyntax) { visitAnyPost(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 283c1d82d03..5f70ddd32a8 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -16,7 +16,6 @@ /// Enum to exhaustively switch over all different syntax nodes. public enum SyntaxEnum: Sendable { case token(TokenSyntax) - @_spi(ExperimentalLanguageFeatures) case abiAttributeArguments(ABIAttributeArgumentsSyntax) @_spi(Compiler) case accessorBlockFile(AccessorBlockFileSyntax) diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index 62883dd7ac3..f1d00716562 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -16,7 +16,6 @@ /// Enumerates the known kinds of Syntax represented in the Syntax tree. public enum SyntaxKind: Sendable { case token - @_spi(ExperimentalLanguageFeatures) case abiAttributeArguments @_spi(Compiler) case accessorBlockFile diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 77eb14701ba..06778189fb7 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -99,10 +99,9 @@ open class SyntaxRewriter { return token } - /// Visit a `ABIAttributeArgumentsSyntax`. + /// Visit a ``ABIAttributeArgumentsSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node - @_spi(ExperimentalLanguageFeatures) open func visit(_ node: ABIAttributeArgumentsSyntax) -> ABIAttributeArgumentsSyntax { return ABIAttributeArgumentsSyntax(unsafeCasting: visitChildren(node._syntaxNode)) } diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index 739a203874c..d600655152f 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -35,17 +35,15 @@ open class SyntaxVisitor { dispatchVisit(Syntax(node)) } - /// Visiting `ABIAttributeArgumentsSyntax` specifically. + /// Visiting ``ABIAttributeArgumentsSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. - @_spi(ExperimentalLanguageFeatures) open func visit(_ node: ABIAttributeArgumentsSyntax) -> SyntaxVisitorContinueKind { return .visitChildren } - /// The function called after visiting `ABIAttributeArgumentsSyntax` and its descendants. + /// The function called after visiting ``ABIAttributeArgumentsSyntax`` and its descendants. /// - node: the node we just finished visiting. - @_spi(ExperimentalLanguageFeatures) open func visitPost(_ node: ABIAttributeArgumentsSyntax) { } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift index 5c824e33f3c..2c820290b8b 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift @@ -13,7 +13,6 @@ // Do not edit directly! // swift-format-ignore-file -@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) public struct RawABIAttributeArgumentsSyntax: RawSyntaxNodeProtocol { public enum Provider: RawSyntaxNodeProtocol { @@ -1615,8 +1614,6 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { case dynamicReplacementArguments(RawDynamicReplacementAttributeArgumentsSyntax) case effectsArguments(RawEffectsAttributeArgumentListSyntax) case documentationArguments(RawDocumentationAttributeArgumentListSyntax) - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) case abiArguments(RawABIAttributeArgumentsSyntax) public static func isKindOf(_ raw: RawSyntax) -> Bool { diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index 1a444b28949..6baae95f2e3 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -17,8 +17,6 @@ /// The arguments of the '@abi' attribute /// -/// - Note: Requires experimental feature `abiAttribute`. -/// /// ### Children /// /// - `provider`: (``AssociatedTypeDeclSyntax`` | ``DeinitializerDeclSyntax`` | ``EnumCaseDeclSyntax`` | ``FunctionDeclSyntax`` | ``InitializerDeclSyntax`` | ``MissingDeclSyntax`` | ``SubscriptDeclSyntax`` | ``TypeAliasDeclSyntax`` | ``VariableDeclSyntax``) @@ -26,7 +24,6 @@ /// ### Contained in /// /// - ``AttributeSyntax``.``AttributeSyntax/arguments`` -@_spi(ExperimentalLanguageFeatures) public struct ABIAttributeArgumentsSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { public enum Provider: SyntaxChildChoices, SyntaxHashable { case associatedType(AssociatedTypeDeclSyntax) @@ -2600,6 +2597,10 @@ public struct AssignmentExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExp /// - `inheritanceClause`: ``InheritanceClauseSyntax``? /// - `initializer`: ``TypeInitializerClauseSyntax``? /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct AssociatedTypeDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3097,7 +3098,7 @@ public struct AttributeClauseFileSyntax: SyntaxProtocol, SyntaxHashable, _LeafSy /// - `atSign`: `@` /// - `attributeName`: ``TypeSyntax`` /// - `leftParen`: `(`? -/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | `ABIAttributeArgumentsSyntax`)? +/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | ``ABIAttributeArgumentsSyntax``)? /// - `rightParen`: `)`? /// /// ### Contained in @@ -3118,8 +3119,6 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr case dynamicReplacementArguments(DynamicReplacementAttributeArgumentsSyntax) case effectsArguments(EffectsAttributeArgumentListSyntax) case documentationArguments(DocumentationAttributeArgumentListSyntax) - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) case abiArguments(ABIAttributeArgumentsSyntax) public var _syntaxNode: Syntax { @@ -3201,8 +3200,6 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .documentationArguments(node) } - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public init(_ node: ABIAttributeArgumentsSyntax) { self = .abiArguments(node) } @@ -3521,30 +3518,24 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return self.as(DocumentationAttributeArgumentListSyntax.self)! } - /// Checks if the current syntax node can be cast to `ABIAttributeArgumentsSyntax`. + /// Checks if the current syntax node can be cast to ``ABIAttributeArgumentsSyntax``. /// /// - Returns: `true` if the node can be cast, `false` otherwise. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public func `is`(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> Bool { return self.as(syntaxType) != nil } - /// Attempts to cast the current syntax node to `ABIAttributeArgumentsSyntax`. + /// Attempts to cast the current syntax node to ``ABIAttributeArgumentsSyntax``. /// - /// - Returns: An instance of `ABIAttributeArgumentsSyntax`, or `nil` if the cast fails. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) + /// - Returns: An instance of ``ABIAttributeArgumentsSyntax``, or `nil` if the cast fails. public func `as`(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> ABIAttributeArgumentsSyntax? { return ABIAttributeArgumentsSyntax.init(self) } - /// Force-casts the current syntax node to `ABIAttributeArgumentsSyntax`. + /// Force-casts the current syntax node to ``ABIAttributeArgumentsSyntax``. /// - /// - Returns: An instance of `ABIAttributeArgumentsSyntax`. + /// - Returns: An instance of ``ABIAttributeArgumentsSyntax``. /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. - /// - Note: Requires experimental feature `abiAttribute`. - @_spi(ExperimentalLanguageFeatures) public func cast(_ syntaxType: ABIAttributeArgumentsSyntax.Type) -> ABIAttributeArgumentsSyntax { return self.as(ABIAttributeArgumentsSyntax.self)! } diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift index 6c8b49198a3..4891b0cdf97 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift @@ -893,6 +893,10 @@ public struct DeferStmtSyntax: StmtSyntaxProtocol, SyntaxHashable, _LeafStmtSynt /// - `deinitKeyword`: `deinit` /// - `effectSpecifiers`: ``DeinitializerEffectSpecifiersSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct DeinitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index 2c9f89946cf..41c56cd8b1d 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -312,6 +312,10 @@ public struct EditorPlaceholderExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _ /// - `modifiers`: ``DeclModifierListSyntax`` /// - `caseKeyword`: `case` /// - `elements`: ``EnumCaseElementListSyntax`` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct EnumCaseDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3312,6 +3316,10 @@ public struct FunctionCallExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafE /// - `signature`: ``FunctionSignatureSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct FunctionDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index d28ff8b926b..6fd799b9e7f 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -4022,6 +4022,10 @@ public struct InitializerClauseSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt /// - `signature`: ``FunctionSignatureSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `body`: ``CodeBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift index fe4e496d5ab..902e11c9a85 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesJKLMN.swift @@ -4536,6 +4536,10 @@ public struct MetatypeTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeS /// - `attributes`: ``AttributeListSyntax`` /// - `modifiers`: ``DeclModifierListSyntax`` /// - `placeholder`: `` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct MissingDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift index 2431b585fc8..1a705af1c4d 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift @@ -3108,6 +3108,10 @@ public struct SubscriptCallExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _Leaf /// - `returnClause`: ``ReturnClauseSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? /// - `accessorBlock`: ``AccessorBlockSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct SubscriptDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift index 88aa709709f..cf0c4b33f19 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift @@ -1851,6 +1851,10 @@ public struct TupleTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTypeSynt /// - `genericParameterClause`: ``GenericParameterClauseSyntax``? /// - `initializer`: ``TypeInitializerClauseSyntax`` /// - `genericWhereClause`: ``GenericWhereClauseSyntax``? +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct TypeAliasDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -3219,6 +3223,10 @@ public struct ValueBindingPatternSyntax: PatternSyntaxProtocol, SyntaxHashable, /// - `modifiers`: ``DeclModifierListSyntax`` /// - `bindingSpecifier`: (`let` | `var` | `inout` | `_mutating` | `_borrowing` | `_consuming`) /// - `bindings`: ``PatternBindingListSyntax`` +/// +/// ### Contained in +/// +/// - ``ABIAttributeArgumentsSyntax``.``ABIAttributeArgumentsSyntax/provider`` public struct VariableDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 1bc34070d1b..5d82301c61e 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -960,23 +960,20 @@ final class AttributeTests: ParserTestCase { parameterClause: FunctionParameterClauseSyntax {}, returnClause: ReturnClauseSyntax(type: TypeSyntax("Int")) ) - ) {}, - experimentalFeatures: [.abiAttribute] + ) {} ) assertParse( """ @abi(associatedtype AssocTy) associatedtype AssocTy - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(deinit) deinit {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -984,50 +981,43 @@ final class AttributeTests: ParserTestCase { @abi(case someCase) case someCase } - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(func fn()) func fn() - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(init()) init() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(subscript(i: Int) -> Element) subscript(i: Int) -> Element {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(typealias Typealias = @escaping () -> Void) typealias Typealias = () -> Void - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(let c1, c2) let c1, c2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v1, v2) var v1, v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( @@ -1042,8 +1032,7 @@ final class AttributeTests: ParserTestCase { ), diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file") - ], - experimentalFeatures: [.abiAttribute] + ] ) assertParse( @@ -1067,8 +1056,7 @@ final class AttributeTests: ParserTestCase { ), diagnostics: [ DiagnosticSpec(locationMarker: "1️⃣", message: "import is not permitted as ABI-providing declaration") - ], - experimentalFeatures: [.abiAttribute] + ] ) // @@ -1079,15 +1067,13 @@ final class AttributeTests: ParserTestCase { """ @abi(associatedtype AssocTy = T) associatedtype AssocTy - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(deinit {}) deinit {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1095,50 +1081,43 @@ final class AttributeTests: ParserTestCase { @abi(case someCase = 42) case someCase } - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(func fn() {}) func fn() - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(init() {}) init() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(subscript(i: Int) -> Element { get {} set {} }) subscript(i: Int) -> Element {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(let c1 = 1, c2 = 2) let c1, c2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v1 = 1, v2 = 2) var v1, v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @abi(var v3 { get {} set {} }) var v3 - """, - experimentalFeatures: [.abiAttribute] + """ ) // @@ -1160,8 +1139,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(var <#pattern#>) var v1 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1184,8 +1162,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(var v2) var v2 - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1203,8 +1180,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn2() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1221,8 +1197,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn3() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) assertParse( """ @@ -1244,8 +1219,7 @@ final class AttributeTests: ParserTestCase { fixedSource: """ @abi(<#declaration#>) func fn4_abi()) func fn4() {} - """, - experimentalFeatures: [.abiAttribute] + """ ) // `#if` is banned inside an `@abi` attribute. @@ -1278,51 +1252,7 @@ final class AttributeTests: ParserTestCase { func _fn() throws(E) ) func fn() throws(E) {} - """, - experimentalFeatures: [.abiAttribute] - ) - } - - func testABIAttributeWithoutFeature() throws { - assertParse( - """ - @abi(1️⃣func fn() -> Int2️⃣) - func fn1() -> Int { } - """, - substructure: FunctionDeclSyntax( - attributes: [ - .attribute( - AttributeSyntax( - attributeName: TypeSyntax("abi"), - leftParen: .leftParenToken(), - [Syntax(try FunctionDeclSyntax("func fn() -> Int"))], - arguments: .argumentList([]), - rightParen: .rightParenToken() - ) - ) - ], - name: "fn1", - signature: FunctionSignatureSyntax( - parameterClause: FunctionParameterClauseSyntax {}, - returnClause: ReturnClauseSyntax(type: TypeSyntax("Int")) - ) - ) {}, - diagnostics: [ - DiagnosticSpec( - locationMarker: "1️⃣", - message: "unexpected code 'func fn() -> Int' in attribute" - ), - DiagnosticSpec( - locationMarker: "2️⃣", - message: "expected argument for '@abi' attribute", - fixIts: ["insert attribute argument"] - ), - ], - fixedSource: """ - @abi(func fn() -> Int) - func fn1() -> Int { } - """, - experimentalFeatures: [] + """ ) } From b9d90d9098a29db76d74c7887bd9abceb9ae3d05 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 9 May 2025 12:39:13 -0700 Subject: [PATCH 02/10] [CI] Remove skip for ready for review This unfortunately ends up causing CI checks to reset and always skipped after marking a PR ready for review. --- .github/workflows/pull_request.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index fd8e6f14272..62868ba50eb 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,5 +1,7 @@ name: Pull request +# PRs created by GitHub Actions don't kick off further actions (https://github.com/peter-evans/create-pull-request/blob/d57e551ebc1a16dee0b8c9ea6d24dba7627a6e35/docs/concepts-guidelines.md#triggering-further-workflow-runs). +# As a workaround, we mark automerge PRs that are created by GitHub actions as draft and trigger the GitHub actions by marking the PR as ready for review. We'd prefer not re-triggering testing on a normal user's PR in this case, but skipping them causes the checks to reset. on: pull_request: types: [opened, reopened, synchronize, ready_for_review] @@ -11,20 +13,15 @@ concurrency: jobs: tests: name: Test - # PRs created by GitHub Actions don't kick off further actions (https://github.com/peter-evans/create-pull-request/blob/d57e551ebc1a16dee0b8c9ea6d24dba7627a6e35/docs/concepts-guidelines.md#triggering-further-workflow-runs). - # As a workaround, we mark automerge PRs that are created by GitHub actions as draft and trigger the GitHub actions by marking the PR as ready for review. But we don't want to re-trigger testing this when a normal user's PR is marked as ready for review. - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main soundness: name: Soundness - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: api_breakage_check_enabled: false # https://github.com/swiftlang/swift-syntax/issues/3010 docs_check_additional_arguments: "--disable-parameters-and-returns-validation" verify_source_code: name: Validate generated code - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: ubuntu-latest container: image: swift:latest @@ -37,7 +34,6 @@ jobs: run: "./swift-syntax-dev-utils verify-source-code --toolchain /usr" test_using_swift_syntax_dev_utils_linux: name: Run tests using swift-syntax-dev-utils (Linux) - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: ubuntu-latest container: image: swift:latest @@ -50,7 +46,6 @@ jobs: run: "./swift-syntax-dev-utils test --enable-rawsyntax-validation --enable-test-fuzzing --toolchain /usr" test_using_swift_syntax_dev_utils_windows: name: Run tests using swift-syntax-dev-utils (Windows) - if: (github.event.action != 'ready_for_review') || (github.event.action == 'ready_for_review' && github.event.pull_request.user.login == 'github-actions[bot]') runs-on: windows-2022 steps: - name: Pull Docker image From d95175a34c9b3ac0c2389da30dffe175d9e2e33c Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 9 May 2025 12:41:01 -0700 Subject: [PATCH 03/10] Update the allowed user for publishing releases to bnbarham --- .github/workflows/publish_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 44f68cce276..715bdcbcc8b 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - run: | - if [[ "${{ github.triggering_actor }}" != "ahoppen" ]]; then + if [[ "${{ github.triggering_actor }}" != "bnbarham" ]]; then echo "${{ github.triggering_actor }} is not allowed to create a release" exit 1 fi From cc3a7a2b14f48b2139a3a1a4064393801f7cd32b Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 14 May 2025 14:14:30 -0700 Subject: [PATCH 04/10] Add more code owners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 96e24e703e1..2d063195ca8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,7 +8,7 @@ # Order is important. The last matching pattern has the most precedence. # Owner of anything in SwiftSyntax not owned by anyone else. -* @ahoppen @bnbarham +* @ahoppen @bnbarham @hamishknight @rintaro # Macros /Sources/SwiftSyntaxMacros @DougGregor From 462f81933a2f3438c0332a13ae403286b055d35c Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Mon, 19 May 2025 09:07:22 -0700 Subject: [PATCH 05/10] Add trailing comma support in cases missing from Swift 6.1 --- Sources/SwiftParser/Attributes.swift | 17 ++++++- Sources/SwiftParser/Availability.swift | 5 ++ Sources/SwiftParser/Nominals.swift | 5 ++ Sources/SwiftParser/Types.swift | 5 ++ Tests/SwiftParserTest/AttributeTests.swift | 48 +++++++++++++++++++ Tests/SwiftParserTest/DeclarationTests.swift | 27 +++++++++++ Tests/SwiftParserTest/TypeTests.swift | 38 +++++++++++++++ .../translated/AvailabilityQueryTests.swift | 12 +---- ...AvailabilityQueryUnavailabilityTests.swift | 28 ++++++----- 9 files changed, 161 insertions(+), 24 deletions(-) diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index c29fa786846..7df62ae0617 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -362,7 +362,7 @@ extension Parser { let additionalArgs = self.parseArgumentListElements( pattern: .none, flavor: .attributeArguments, - allowTrailingComma: false + allowTrailingComma: true ) return [roleElement] + additionalArgs } @@ -852,6 +852,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing closure then there are no more elements + if self.at(.rightParen) { + break + } } while keepGoing != nil return RawBackDeployedAttributeArgumentsSyntax( unexpectedBeforeLabel, @@ -883,6 +888,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing closure then there are no more elements + if self.at(.rightParen) { + break + } } while keepGoing != nil return RawOriginallyDefinedInAttributeArgumentsSyntax( @@ -1001,6 +1011,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing closure then there are no more elements + if self.at(.rightParen) { + break + } } while keepGoing != nil return RawDocumentationAttributeArgumentListSyntax(elements: arguments, arena: self.arena) diff --git a/Sources/SwiftParser/Availability.swift b/Sources/SwiftParser/Availability.swift index fc0979937a2..caa41583d10 100644 --- a/Sources/SwiftParser/Availability.swift +++ b/Sources/SwiftParser/Availability.swift @@ -47,6 +47,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing closure, there are no more elements + if self.at(.rightParen) { + break + } } while keepGoing != nil && self.hasProgressed(&availabilityArgumentProgress) } diff --git a/Sources/SwiftParser/Nominals.swift b/Sources/SwiftParser/Nominals.swift index bbd15cf5618..eebdcd6fa0c 100644 --- a/Sources/SwiftParser/Nominals.swift +++ b/Sources/SwiftParser/Nominals.swift @@ -361,6 +361,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing comma, there are no more elements + if at(prefix: ">") { + break + } } while keepGoing != nil && self.hasProgressed(&loopProgress) } let rangle = self.expectWithoutRecovery(prefix: ">", as: .rightAngle) diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 67c7604ce0f..098215aab30 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -430,6 +430,11 @@ extension Parser { arena: self.arena ) ) + + // If this was a trailing comma, we're done parsing the list + if self.at(prefix: ">") { + break + } } while keepGoing != nil && self.hasProgressed(&loopProgress) } diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 5d82301c61e..2159c1f0b63 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -470,6 +470,15 @@ final class AttributeTests: ParserTestCase { """ ) + assertParse( + """ + @backDeployed( + before: macOS 12.0, + ) + struct Foo {} + """ + ) + assertParse( """ @backDeployed(before: macos 12.0, iOS 15.0) @@ -477,6 +486,15 @@ final class AttributeTests: ParserTestCase { """ ) + assertParse( + """ + @backDeployed( + before: macos 12.0, + iOS 15.0,) + struct Foo {} + """ + ) + assertParse( """ @available(macOS 11.0, *) @@ -537,6 +555,16 @@ final class AttributeTests: ParserTestCase { """ ) + assertParse( + """ + @_originallyDefinedIn( + module: "ToasterKit", + macOS 10.15, + ) + struct Vehicle {} + """ + ) + assertParse( """ @_originallyDefinedIn(module: "ToasterKit", macOS 10.15, iOS 13) @@ -846,6 +874,26 @@ final class AttributeTests: ParserTestCase { } """ ) + + assertParse( + """ + @attached( + member, + names: named(deinit), + ) + macro m() + """ + ) + + assertParse( + """ + @attached( + extension, + conformances: P1, P2, + ) + macro AddAllConformances() + """ + ) } func testAttachedExtensionAttribute() { diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 7ec097ec5bd..f55aa4c1a3d 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -3529,4 +3529,31 @@ final class DeclarationTests: ParserTestCase { ] ) } + + func testTrailingCommas() { + assertParse( + """ + protocol Baaz< + Foo, + Bar, + > { + associatedtype Foo + associatedtype Bar + } + """ + ) + + assertParse( + """ + struct Foo< + T1, + T2, + T3, + >: Baaz< + T1, + T2, + > {} + """ + ) + } } diff --git a/Tests/SwiftParserTest/TypeTests.swift b/Tests/SwiftParserTest/TypeTests.swift index 6e49d5fa75d..2d317551c14 100644 --- a/Tests/SwiftParserTest/TypeTests.swift +++ b/Tests/SwiftParserTest/TypeTests.swift @@ -734,6 +734,44 @@ final class TypeTests: ParserTestCase { fixedSource: "func foo(test: nonisolated(nonsendinghello) () async -> Void)" ) } + + func testTrailingCommas() { + assertParse( + """ + let foo: ( + bar: String, + quux: String, + ) + """ + ) + + assertParse( + """ + let closure: ( + String, + String, + ) -> ( + bar: String, + quux: String, + ) + """ + ) + + assertParse( + """ + struct Foo {} + + typealias Bar< + T1, + T2, + > = Foo< + T1, + T2, + Bool, + > + """ + ) + } } final class InlineArrayTypeTests: ParserTestCase { diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift index 4425e329fd5..6646317adca 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift @@ -400,17 +400,7 @@ final class AvailabilityQueryTests: ParserTestCase { """ if #available(OSX 10.51,1️⃣) { } - """, - diagnostics: [ - DiagnosticSpec( - message: "expected version restriction in availability argument", - fixIts: ["insert version restriction"] - ) - ], - fixedSource: """ - if #available(OSX 10.51, <#identifier#>) { - } - """ + """ ) } diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift index 24d1827bcc0..d99f63155f4 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift @@ -381,19 +381,9 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase { func testAvailabilityQueryUnavailability23() { assertParse( """ - if #unavailable(OSX 10.51,1️⃣) { + if #unavailable(OSX 10.51,) { } - """, - diagnostics: [ - DiagnosticSpec( - message: "expected version restriction in availability argument", - fixIts: ["insert version restriction"] - ) - ], - fixedSource: """ - if #unavailable(OSX 10.51, <#identifier#>) { - } - """ + """ ) } @@ -611,4 +601,18 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase { ] ) } + + func testTrailingComma() { + assertParse( + """ + func fooDeprecated() { + if #available( + iOS 18.0, + macOS 14.0, + *, + ) {} + } + """ + ) + } } From 793ccbdb3e3de408f0e9a46b0d00f268dae96095 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Mon, 19 May 2025 15:52:54 -0700 Subject: [PATCH 06/10] Revert attribute changes --- Sources/SwiftParser/Attributes.swift | 17 +------ Sources/SwiftParser/Availability.swift | 5 -- Tests/SwiftParserTest/AttributeTests.swift | 48 ------------------- .../translated/AvailabilityQueryTests.swift | 12 ++++- ...AvailabilityQueryUnavailabilityTests.swift | 28 +++++------ 5 files changed, 24 insertions(+), 86 deletions(-) diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index 7df62ae0617..c29fa786846 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -362,7 +362,7 @@ extension Parser { let additionalArgs = self.parseArgumentListElements( pattern: .none, flavor: .attributeArguments, - allowTrailingComma: true + allowTrailingComma: false ) return [roleElement] + additionalArgs } @@ -852,11 +852,6 @@ extension Parser { arena: self.arena ) ) - - // If this was a trailing closure then there are no more elements - if self.at(.rightParen) { - break - } } while keepGoing != nil return RawBackDeployedAttributeArgumentsSyntax( unexpectedBeforeLabel, @@ -888,11 +883,6 @@ extension Parser { arena: self.arena ) ) - - // If this was a trailing closure then there are no more elements - if self.at(.rightParen) { - break - } } while keepGoing != nil return RawOriginallyDefinedInAttributeArgumentsSyntax( @@ -1011,11 +1001,6 @@ extension Parser { arena: self.arena ) ) - - // If this was a trailing closure then there are no more elements - if self.at(.rightParen) { - break - } } while keepGoing != nil return RawDocumentationAttributeArgumentListSyntax(elements: arguments, arena: self.arena) diff --git a/Sources/SwiftParser/Availability.swift b/Sources/SwiftParser/Availability.swift index caa41583d10..fc0979937a2 100644 --- a/Sources/SwiftParser/Availability.swift +++ b/Sources/SwiftParser/Availability.swift @@ -47,11 +47,6 @@ extension Parser { arena: self.arena ) ) - - // If this was a trailing closure, there are no more elements - if self.at(.rightParen) { - break - } } while keepGoing != nil && self.hasProgressed(&availabilityArgumentProgress) } diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 2159c1f0b63..5d82301c61e 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -470,15 +470,6 @@ final class AttributeTests: ParserTestCase { """ ) - assertParse( - """ - @backDeployed( - before: macOS 12.0, - ) - struct Foo {} - """ - ) - assertParse( """ @backDeployed(before: macos 12.0, iOS 15.0) @@ -486,15 +477,6 @@ final class AttributeTests: ParserTestCase { """ ) - assertParse( - """ - @backDeployed( - before: macos 12.0, - iOS 15.0,) - struct Foo {} - """ - ) - assertParse( """ @available(macOS 11.0, *) @@ -555,16 +537,6 @@ final class AttributeTests: ParserTestCase { """ ) - assertParse( - """ - @_originallyDefinedIn( - module: "ToasterKit", - macOS 10.15, - ) - struct Vehicle {} - """ - ) - assertParse( """ @_originallyDefinedIn(module: "ToasterKit", macOS 10.15, iOS 13) @@ -874,26 +846,6 @@ final class AttributeTests: ParserTestCase { } """ ) - - assertParse( - """ - @attached( - member, - names: named(deinit), - ) - macro m() - """ - ) - - assertParse( - """ - @attached( - extension, - conformances: P1, P2, - ) - macro AddAllConformances() - """ - ) } func testAttachedExtensionAttribute() { diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift index 6646317adca..4425e329fd5 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift @@ -400,7 +400,17 @@ final class AvailabilityQueryTests: ParserTestCase { """ if #available(OSX 10.51,1️⃣) { } - """ + """, + diagnostics: [ + DiagnosticSpec( + message: "expected version restriction in availability argument", + fixIts: ["insert version restriction"] + ) + ], + fixedSource: """ + if #available(OSX 10.51, <#identifier#>) { + } + """ ) } diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift index d99f63155f4..24d1827bcc0 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift @@ -381,9 +381,19 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase { func testAvailabilityQueryUnavailability23() { assertParse( """ - if #unavailable(OSX 10.51,) { + if #unavailable(OSX 10.51,1️⃣) { } - """ + """, + diagnostics: [ + DiagnosticSpec( + message: "expected version restriction in availability argument", + fixIts: ["insert version restriction"] + ) + ], + fixedSource: """ + if #unavailable(OSX 10.51, <#identifier#>) { + } + """ ) } @@ -601,18 +611,4 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase { ] ) } - - func testTrailingComma() { - assertParse( - """ - func fooDeprecated() { - if #available( - iOS 18.0, - macOS 14.0, - *, - ) {} - } - """ - ) - } } From f7848539d72e852f67a1ae8bec269321b607b415 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Mon, 19 May 2025 19:00:38 -0700 Subject: [PATCH 07/10] Support trailing commas in types within expressions --- Sources/SwiftParser/Types.swift | 3 ++- Tests/SwiftParserTest/ExpressionTests.swift | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 098215aab30..58eacfa59b9 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -1057,7 +1057,8 @@ extension Parser.Lookahead { return false } // Parse the comma, if the list continues. - } while self.consume(if: .comma) != nil && self.hasProgressed(&loopProgress) + // This could be the trailing comma. + } while self.consume(if: .comma) != nil && !self.at(prefix: ">") && self.hasProgressed(&loopProgress) } guard self.consume(ifPrefix: ">", as: .rightAngle) != nil else { diff --git a/Tests/SwiftParserTest/ExpressionTests.swift b/Tests/SwiftParserTest/ExpressionTests.swift index e63d753d2da..3eb7d83add2 100644 --- a/Tests/SwiftParserTest/ExpressionTests.swift +++ b/Tests/SwiftParserTest/ExpressionTests.swift @@ -2125,6 +2125,26 @@ final class ExpressionTests: ParserTestCase { """ ) } + + func testTrailingCommasInTypeExpressions() { + assertParse( + """ + let _ = Foo2.self + """ + ) + + assertParse( + """ + let _ = Foo2() + """ + ) + + assertParse( + """ + let _ = ((Int, Bool, String,) -> Void).self + """ + ) + } } final class MemberExprTests: ParserTestCase { From d754c2db557a2f2af4a33a8dd945b95a415cdea7 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 20 May 2025 10:20:04 -0700 Subject: [PATCH 08/10] Add support for SE-0460 @specialized Add support to parse the non-underscored version of the @specialized attribute. rdar://150033316 --- .../SyntaxSupport/AttributeNodes.swift | 18 +++++ .../Sources/SyntaxSupport/KeywordSpec.swift | 3 + .../SyntaxSupport/SyntaxNodeKind.swift | 2 + Sources/SwiftParser/Attributes.swift | 12 +++ Sources/SwiftParser/TokenPrecedence.swift | 1 + .../SyntaxKindNameForDiagnostics.swift | 2 + .../generated/SwiftSyntax.md | 1 + .../generated/ChildNameForKeyPath.swift | 6 ++ Sources/SwiftSyntax/generated/Keyword.swift | 4 + .../generated/RenamedNodesCompatibility.swift | 8 ++ .../generated/SyntaxAnyVisitor.swift | 8 ++ .../generated/SyntaxBaseNodes.swift | 1 + .../SwiftSyntax/generated/SyntaxEnum.swift | 3 + .../SwiftSyntax/generated/SyntaxKind.swift | 3 + .../generated/SyntaxRewriter.swift | 16 ++++ .../SwiftSyntax/generated/SyntaxVisitor.swift | 24 ++++++ .../generated/raw/RawSyntaxNodesAB.swift | 7 +- .../generated/raw/RawSyntaxNodesQRS.swift | 58 +++++++++++++ .../generated/raw/RawSyntaxValidation.swift | 8 ++ .../generated/syntaxNodes/SyntaxNodesAB.swift | 34 +++++++- .../syntaxNodes/SyntaxNodesGHI.swift | 1 + .../syntaxNodes/SyntaxNodesQRS.swift | 81 +++++++++++++++++++ Tests/SwiftParserTest/AttributeTests.swift | 30 +++++++ Tests/SwiftParserTest/DeclarationTests.swift | 9 +++ 24 files changed, 338 insertions(+), 2 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index 3347cf8bb41..d960ec5db26 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -74,6 +74,11 @@ public let ATTRIBUTE_NODES: [Node] = [ // Special arguments for keyword decl name e.g. 'subscript(_:)', and availability arguments. kind: .node(kind: .specializeAttributeArgumentList) ), + Child( + name: "specializedArguments", + // Special arguments for generic where clause. + kind: .node(kind: .specializedAttributeArgument) + ), Child( name: "objCName", // Special arguments for Objective-C names. e.g. 'methodNameWithArg1:Arg2:' @@ -717,6 +722,19 @@ public let ATTRIBUTE_NODES: [Node] = [ ] ), + Node( + kind: .specializedAttributeArgument, + base: .syntax, + nameForDiagnostics: "argument to '@specialized", + documentation: "The generic where clause for the `@specialized` attribute", + children: [ + Child( + name: "genericWhereClause", + kind: .node(kind: .genericWhereClause) + ) + ] + ), + Node( kind: .specializeTargetFunctionArgument, base: .syntax, diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 1a32f708965..a0e6730e18d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -104,6 +104,7 @@ public enum Keyword: CaseIterable { case _PackageDescription case _read case _RefCountedObject + case specialized case _specialize case _spi_available case _Trivial @@ -340,6 +341,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("_read") case ._RefCountedObject: return KeywordSpec("_RefCountedObject") + case .specialized: + return KeywordSpec("specialized") case ._specialize: return KeywordSpec("_specialize") case ._spi_available: diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index 6e50fe39500..98cd248e22b 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -259,6 +259,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case simpleStringLiteralSegmentList case someOrAnyType case sourceFile + case specializedAttributeArgument case specializeAttributeArgumentList case specializeAvailabilityArgument case specializeTargetFunctionArgument @@ -454,6 +455,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case .someOrAnyType: return "constrainedSugarType" case .simpleTypeSpecifier: return "typeSpecifier" case .specializeAttributeArgumentList: return "specializeAttributeSpecList" + case .specializedAttributeArgument: return "specializedAttribute" case .specializeAvailabilityArgument: return "availabilityEntry" case .specializeTargetFunctionArgument: return "targetFunctionEntry" case .stringLiteralSegmentList: return "stringLiteralSegments" diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index c29fa786846..5946e76cdff 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -41,6 +41,7 @@ extension Parser { case _effects case _implements case _originallyDefinedIn + case specialized case _specialize case _spi_available case `rethrows` @@ -63,6 +64,7 @@ extension Parser { case TokenSpec(._effects): self = ._effects case TokenSpec(._implements): self = ._implements case TokenSpec(._originallyDefinedIn): self = ._originallyDefinedIn + case TokenSpec(.specialized): self = .specialized case TokenSpec(._specialize): self = ._specialize case TokenSpec(._spi_available): self = ._spi_available case TokenSpec(.`rethrows`): self = .rethrows @@ -89,6 +91,7 @@ extension Parser { case ._effects: return .keyword(._effects) case ._implements: return .keyword(._implements) case ._originallyDefinedIn: return .keyword(._originallyDefinedIn) + case .specialized: return .keyword(.specialized) case ._specialize: return .keyword(._specialize) case ._spi_available: return .keyword(._spi_available) case .`rethrows`: return .keyword(.rethrows) @@ -254,6 +257,10 @@ extension Parser { return parseAttribute(argumentMode: .optional) { parser in return (nil, .objCName(parser.parseObjectiveCSelector())) } + case .specialized: + return parseAttribute(argumentMode: .required) { parser in + return (nil, .specializedArguments(parser.parseSpecializedAttributeArgument())) + } case ._specialize: return parseAttribute(argumentMode: .required) { parser in return (nil, .specializeArguments(parser.parseSpecializeAttributeArgumentList())) @@ -645,6 +652,11 @@ extension Parser { } extension Parser { + mutating func parseSpecializedAttributeArgument() -> RawSpecializedAttributeArgumentSyntax { + let whereClause = self.parseGenericWhereClause() + return RawSpecializedAttributeArgumentSyntax(genericWhereClause: whereClause, arena: self.arena) + } + mutating func parseSpecializeAttributeArgumentList() -> RawSpecializeAttributeArgumentListSyntax { var elements = [RawSpecializeAttributeArgumentListSyntax.Element]() // Parse optional "exported" and "kind" labeled parameters. diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index 01fdbc06f78..c0a9a04bd08 100644 --- a/Sources/SwiftParser/TokenPrecedence.swift +++ b/Sources/SwiftParser/TokenPrecedence.swift @@ -267,6 +267,7 @@ enum TokenPrecedence: Comparable { ._effects, ._implements, ._originallyDefinedIn, + .specialized, ._specialize, ._spi_available, .abi, diff --git a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift index 9a9d00393e7..6c4448e9dbd 100644 --- a/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/SyntaxKindNameForDiagnostics.swift @@ -362,6 +362,8 @@ extension SyntaxKind { return "availability entry" case .specializeTargetFunctionArgument: return "attribute argument" + case .specializedAttributeArgument: + return "argument to '@specialized" case .stringLiteralExpr: return "string literal" case .structDecl: diff --git a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md index ee9216345d3..124109abadf 100644 --- a/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md +++ b/Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md @@ -327,6 +327,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code. - - - +- ### Miscellaneous Syntax diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 802b6ae8003..079b4f842f3 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -2962,6 +2962,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "trailingComma" case \SpecializeTargetFunctionArgumentSyntax.unexpectedAfterTrailingComma: return "unexpectedAfterTrailingComma" + case \SpecializedAttributeArgumentSyntax.unexpectedBeforeGenericWhereClause: + return "unexpectedBeforeGenericWhereClause" + case \SpecializedAttributeArgumentSyntax.genericWhereClause: + return "genericWhereClause" + case \SpecializedAttributeArgumentSyntax.unexpectedAfterGenericWhereClause: + return "unexpectedAfterGenericWhereClause" case \StringLiteralExprSyntax.unexpectedBeforeOpeningPounds: return "unexpectedBeforeOpeningPounds" case \StringLiteralExprSyntax.openingPounds: diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 6f049eb7936..3a848bf62b7 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -46,6 +46,7 @@ public enum Keyword: UInt8, Hashable, Sendable { case _PackageDescription case _read case _RefCountedObject + case specialized case _specialize case _spi_available case _Trivial @@ -601,6 +602,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = ._implements case "_noMetadata": self = ._noMetadata + case "specialized": + self = .specialized case "_specialize": self = ._specialize case "autoclosure": @@ -789,6 +792,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "_PackageDescription", "_read", "_RefCountedObject", + "specialized", "_specialize", "_spi_available", "_Trivial", diff --git a/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift index d9eed528b19..3aa308c9fc1 100644 --- a/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedNodesCompatibility.swift @@ -178,6 +178,9 @@ public typealias SpecializeAttributeSpecListSyntax = SpecializeAttributeArgument @available(*, deprecated, renamed: "GenericSpecializationExprSyntax") public typealias SpecializeExprSyntax = GenericSpecializationExprSyntax +@available(*, deprecated, renamed: "SpecializedAttributeArgumentSyntax") +public typealias SpecializedAttributeSyntax = SpecializedAttributeArgumentSyntax + @available(*, deprecated, renamed: "StringLiteralSegmentListSyntax") public typealias StringLiteralSegmentsSyntax = StringLiteralSegmentListSyntax @@ -493,6 +496,11 @@ extension SyntaxKind { return .genericSpecializationExpr } + @available(*, deprecated, renamed: "SpecializedAttributeArgumentSyntax") + public static var specializedAttribute: Self { + return .specializedAttributeArgument + } + @available(*, deprecated, renamed: "StringLiteralSegmentListSyntax") public static var stringLiteralSegments: Self { return .stringLiteralSegmentList diff --git a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift index 761e69e41d9..b8c4128e2d9 100644 --- a/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxAnyVisitor.swift @@ -1983,6 +1983,14 @@ open class SyntaxAnyVisitor: SyntaxVisitor { visitAnyPost(node._syntaxNode) } + override open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SyntaxVisitorContinueKind { + return visitAny(node._syntaxNode) + } + + override open func visitPost(_ node: SpecializedAttributeArgumentSyntax) { + visitAnyPost(node._syntaxNode) + } + override open func visit(_ node: StringLiteralExprSyntax) -> SyntaxVisitorContinueKind { return visitAny(node._syntaxNode) } diff --git a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift index 8c1a8444f88..cf9cf32bbb7 100644 --- a/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift +++ b/Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift @@ -1749,6 +1749,7 @@ extension Syntax { .node(SpecializeAttributeArgumentListSyntax.self), .node(SpecializeAvailabilityArgumentSyntax.self), .node(SpecializeTargetFunctionArgumentSyntax.self), + .node(SpecializedAttributeArgumentSyntax.self), .node(StringLiteralExprSyntax.self), .node(StringLiteralSegmentListSyntax.self), .node(StringSegmentSyntax.self), diff --git a/Sources/SwiftSyntax/generated/SyntaxEnum.swift b/Sources/SwiftSyntax/generated/SyntaxEnum.swift index 5f70ddd32a8..629a783306d 100644 --- a/Sources/SwiftSyntax/generated/SyntaxEnum.swift +++ b/Sources/SwiftSyntax/generated/SyntaxEnum.swift @@ -265,6 +265,7 @@ public enum SyntaxEnum: Sendable { case specializeAttributeArgumentList(SpecializeAttributeArgumentListSyntax) case specializeAvailabilityArgument(SpecializeAvailabilityArgumentSyntax) case specializeTargetFunctionArgument(SpecializeTargetFunctionArgumentSyntax) + case specializedAttributeArgument(SpecializedAttributeArgumentSyntax) case stringLiteralExpr(StringLiteralExprSyntax) case stringLiteralSegmentList(StringLiteralSegmentListSyntax) case stringSegment(StringSegmentSyntax) @@ -800,6 +801,8 @@ extension Syntax { return .specializeAvailabilityArgument(SpecializeAvailabilityArgumentSyntax(self)!) case .specializeTargetFunctionArgument: return .specializeTargetFunctionArgument(SpecializeTargetFunctionArgumentSyntax(self)!) + case .specializedAttributeArgument: + return .specializedAttributeArgument(SpecializedAttributeArgumentSyntax(self)!) case .stringLiteralExpr: return .stringLiteralExpr(StringLiteralExprSyntax(self)!) case .stringLiteralSegmentList: diff --git a/Sources/SwiftSyntax/generated/SyntaxKind.swift b/Sources/SwiftSyntax/generated/SyntaxKind.swift index f1d00716562..7c24764a8c0 100644 --- a/Sources/SwiftSyntax/generated/SyntaxKind.swift +++ b/Sources/SwiftSyntax/generated/SyntaxKind.swift @@ -265,6 +265,7 @@ public enum SyntaxKind: Sendable { case specializeAttributeArgumentList case specializeAvailabilityArgument case specializeTargetFunctionArgument + case specializedAttributeArgument case stringLiteralExpr case stringLiteralSegmentList case stringSegment @@ -925,6 +926,8 @@ public enum SyntaxKind: Sendable { return SpecializeAvailabilityArgumentSyntax.self case .specializeTargetFunctionArgument: return SpecializeTargetFunctionArgumentSyntax.self + case .specializedAttributeArgument: + return SpecializedAttributeArgumentSyntax.self case .stringLiteralExpr: return StringLiteralExprSyntax.self case .stringLiteralSegmentList: diff --git a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift index 06778189fb7..fce415516c9 100644 --- a/Sources/SwiftSyntax/generated/SyntaxRewriter.swift +++ b/Sources/SwiftSyntax/generated/SyntaxRewriter.swift @@ -1776,6 +1776,13 @@ open class SyntaxRewriter { return SpecializeTargetFunctionArgumentSyntax(unsafeCasting: visitChildren(node._syntaxNode)) } + /// Visit a ``SpecializedAttributeArgumentSyntax``. + /// - Parameter node: the node that is being visited + /// - Returns: the rewritten node + open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SpecializedAttributeArgumentSyntax { + return SpecializedAttributeArgumentSyntax(unsafeCasting: visitChildren(node._syntaxNode)) + } + /// Visit a ``StringLiteralExprSyntax``. /// - Parameter node: the node that is being visited /// - Returns: the rewritten node @@ -3357,6 +3364,11 @@ open class SyntaxRewriter { Syntax(visit(SpecializeTargetFunctionArgumentSyntax(unsafeCasting: node))) } + @inline(never) + private func visitSpecializedAttributeArgumentSyntaxImpl(_ node: Syntax) -> Syntax { + Syntax(visit(SpecializedAttributeArgumentSyntax(unsafeCasting: node))) + } + @inline(never) private func visitStringLiteralExprSyntaxImpl(_ node: Syntax) -> Syntax { Syntax(visit(StringLiteralExprSyntax(unsafeCasting: node))) @@ -4111,6 +4123,8 @@ open class SyntaxRewriter { return self.visitSpecializeAvailabilityArgumentSyntaxImpl(_:) case .specializeTargetFunctionArgument: return self.visitSpecializeTargetFunctionArgumentSyntaxImpl(_:) + case .specializedAttributeArgument: + return self.visitSpecializedAttributeArgumentSyntaxImpl(_:) case .stringLiteralExpr: return self.visitStringLiteralExprSyntaxImpl(_:) case .stringLiteralSegmentList: @@ -4697,6 +4711,8 @@ open class SyntaxRewriter { return visitSpecializeAvailabilityArgumentSyntaxImpl(node) case .specializeTargetFunctionArgument: return visitSpecializeTargetFunctionArgumentSyntaxImpl(node) + case .specializedAttributeArgument: + return visitSpecializedAttributeArgumentSyntaxImpl(node) case .stringLiteralExpr: return visitStringLiteralExprSyntaxImpl(node) case .stringLiteralSegmentList: diff --git a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift index d600655152f..d7a5c5b9b0f 100644 --- a/Sources/SwiftSyntax/generated/SyntaxVisitor.swift +++ b/Sources/SwiftSyntax/generated/SyntaxVisitor.swift @@ -2913,6 +2913,18 @@ open class SyntaxVisitor { open func visitPost(_ node: SpecializeTargetFunctionArgumentSyntax) { } + /// Visiting ``SpecializedAttributeArgumentSyntax`` specifically. + /// - Parameter node: the node we are visiting. + /// - Returns: how should we continue visiting. + open func visit(_ node: SpecializedAttributeArgumentSyntax) -> SyntaxVisitorContinueKind { + return .visitChildren + } + + /// The function called after visiting ``SpecializedAttributeArgumentSyntax`` and its descendants. + /// - node: the node we just finished visiting. + open func visitPost(_ node: SpecializedAttributeArgumentSyntax) { + } + /// Visiting ``StringLiteralExprSyntax`` specifically. /// - Parameter node: the node we are visiting. /// - Returns: how should we continue visiting. @@ -5438,6 +5450,14 @@ open class SyntaxVisitor { visitPost(SpecializeTargetFunctionArgumentSyntax(unsafeCasting: node)) } + @inline(never) + private func visitSpecializedAttributeArgumentSyntaxImpl(_ node: Syntax) { + if visit(SpecializedAttributeArgumentSyntax(unsafeCasting: node)) == .visitChildren { + visitChildren(node) + } + visitPost(SpecializedAttributeArgumentSyntax(unsafeCasting: node)) + } + @inline(never) private func visitStringLiteralExprSyntaxImpl(_ node: Syntax) { if visit(StringLiteralExprSyntax(unsafeCasting: node)) == .visitChildren { @@ -6342,6 +6362,8 @@ open class SyntaxVisitor { return self.visitSpecializeAvailabilityArgumentSyntaxImpl(_:) case .specializeTargetFunctionArgument: return self.visitSpecializeTargetFunctionArgumentSyntaxImpl(_:) + case .specializedAttributeArgument: + return self.visitSpecializedAttributeArgumentSyntaxImpl(_:) case .stringLiteralExpr: return self.visitStringLiteralExprSyntaxImpl(_:) case .stringLiteralSegmentList: @@ -6928,6 +6950,8 @@ open class SyntaxVisitor { self.visitSpecializeAvailabilityArgumentSyntaxImpl(node) case .specializeTargetFunctionArgument: self.visitSpecializeTargetFunctionArgumentSyntaxImpl(node) + case .specializedAttributeArgument: + self.visitSpecializedAttributeArgumentSyntaxImpl(node) case .stringLiteralExpr: self.visitStringLiteralExprSyntaxImpl(node) case .stringLiteralSegmentList: diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift index 2c820290b8b..1dc419a7df4 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift @@ -1605,6 +1605,7 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { case argumentList(RawLabeledExprListSyntax) case availability(RawAvailabilityArgumentListSyntax) case specializeArguments(RawSpecializeAttributeArgumentListSyntax) + case specializedArguments(RawSpecializedAttributeArgumentSyntax) case objCName(RawObjCSelectorPieceListSyntax) case implementsArguments(RawImplementsAttributeArgumentsSyntax) case differentiableArguments(RawDifferentiableAttributeArgumentsSyntax) @@ -1617,7 +1618,7 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { case abiArguments(RawABIAttributeArgumentsSyntax) public static func isKindOf(_ raw: RawSyntax) -> Bool { - RawLabeledExprListSyntax.isKindOf(raw) || RawAvailabilityArgumentListSyntax.isKindOf(raw) || RawSpecializeAttributeArgumentListSyntax.isKindOf(raw) || RawObjCSelectorPieceListSyntax.isKindOf(raw) || RawImplementsAttributeArgumentsSyntax.isKindOf(raw) || RawDifferentiableAttributeArgumentsSyntax.isKindOf(raw) || RawDerivativeAttributeArgumentsSyntax.isKindOf(raw) || RawBackDeployedAttributeArgumentsSyntax.isKindOf(raw) || RawOriginallyDefinedInAttributeArgumentsSyntax.isKindOf(raw) || RawDynamicReplacementAttributeArgumentsSyntax.isKindOf(raw) || RawEffectsAttributeArgumentListSyntax.isKindOf(raw) || RawDocumentationAttributeArgumentListSyntax.isKindOf(raw) || RawABIAttributeArgumentsSyntax.isKindOf(raw) + RawLabeledExprListSyntax.isKindOf(raw) || RawAvailabilityArgumentListSyntax.isKindOf(raw) || RawSpecializeAttributeArgumentListSyntax.isKindOf(raw) || RawSpecializedAttributeArgumentSyntax.isKindOf(raw) || RawObjCSelectorPieceListSyntax.isKindOf(raw) || RawImplementsAttributeArgumentsSyntax.isKindOf(raw) || RawDifferentiableAttributeArgumentsSyntax.isKindOf(raw) || RawDerivativeAttributeArgumentsSyntax.isKindOf(raw) || RawBackDeployedAttributeArgumentsSyntax.isKindOf(raw) || RawOriginallyDefinedInAttributeArgumentsSyntax.isKindOf(raw) || RawDynamicReplacementAttributeArgumentsSyntax.isKindOf(raw) || RawEffectsAttributeArgumentListSyntax.isKindOf(raw) || RawDocumentationAttributeArgumentListSyntax.isKindOf(raw) || RawABIAttributeArgumentsSyntax.isKindOf(raw) } public var raw: RawSyntax { @@ -1628,6 +1629,8 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { return node.raw case .specializeArguments(let node): return node.raw + case .specializedArguments(let node): + return node.raw case .objCName(let node): return node.raw case .implementsArguments(let node): @@ -1658,6 +1661,8 @@ public struct RawAttributeSyntax: RawSyntaxNodeProtocol { self = .availability(node) } else if let node = node.as(RawSpecializeAttributeArgumentListSyntax.self) { self = .specializeArguments(node) + } else if let node = node.as(RawSpecializedAttributeArgumentSyntax.self) { + self = .specializedArguments(node) } else if let node = node.as(RawObjCSelectorPieceListSyntax.self) { self = .objCName(node) } else if let node = node.as(RawImplementsAttributeArgumentsSyntax.self) { diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift index e4313ae32a7..3092d21e457 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesQRS.swift @@ -1190,6 +1190,64 @@ public struct RawSpecializeTargetFunctionArgumentSyntax: RawSyntaxNodeProtocol { } } +@_spi(RawSyntax) +public struct RawSpecializedAttributeArgumentSyntax: RawSyntaxNodeProtocol { + @_spi(RawSyntax) + public var layoutView: RawSyntaxLayoutView { + return raw.layoutView! + } + + public static func isKindOf(_ raw: RawSyntax) -> Bool { + return raw.kind == .specializedAttributeArgument + } + + public var raw: RawSyntax + + init(raw: RawSyntax) { + precondition(Self.isKindOf(raw)) + self.raw = raw + } + + private init(unchecked raw: RawSyntax) { + self.raw = raw + } + + public init?(_ other: some RawSyntaxNodeProtocol) { + guard Self.isKindOf(other.raw) else { + return nil + } + self.init(unchecked: other.raw) + } + + public init( + _ unexpectedBeforeGenericWhereClause: RawUnexpectedNodesSyntax? = nil, + genericWhereClause: RawGenericWhereClauseSyntax, + _ unexpectedAfterGenericWhereClause: RawUnexpectedNodesSyntax? = nil, + arena: __shared RawSyntaxArena + ) { + let raw = RawSyntax.makeLayout( + kind: .specializedAttributeArgument, uninitializedCount: 3, arena: arena) { layout in + layout.initialize(repeating: nil) + layout[0] = unexpectedBeforeGenericWhereClause?.raw + layout[1] = genericWhereClause.raw + layout[2] = unexpectedAfterGenericWhereClause?.raw + } + self.init(unchecked: raw) + } + + public var unexpectedBeforeGenericWhereClause: RawUnexpectedNodesSyntax? { + layoutView.children[0].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var genericWhereClause: RawGenericWhereClauseSyntax { + layoutView.children[1].map(RawGenericWhereClauseSyntax.init(raw:))! + } + + public var unexpectedAfterGenericWhereClause: RawUnexpectedNodesSyntax? { + layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) + } +} + @_spi(RawSyntax) public struct RawStmtSyntax: RawStmtSyntaxNodeProtocol { @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 0ca5359f6e7..182d2d0aeba 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -2638,6 +2638,12 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 7, verify(layout[7], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) } + func validateSpecializedAttributeArgumentSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { + assert(layout.count == 3) + assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 1, verify(layout[1], as: RawGenericWhereClauseSyntax.self)) + assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) + } func validateStringLiteralExprSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { assert(layout.count == 11) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) @@ -3606,6 +3612,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { validateSpecializeAvailabilityArgumentSyntax(kind: kind, layout: layout) case .specializeTargetFunctionArgument: validateSpecializeTargetFunctionArgumentSyntax(kind: kind, layout: layout) + case .specializedAttributeArgument: + validateSpecializedAttributeArgumentSyntax(kind: kind, layout: layout) case .stringLiteralExpr: validateStringLiteralExprSyntax(kind: kind, layout: layout) case .stringLiteralSegmentList: diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index 6baae95f2e3..c36ad53e31d 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -3098,7 +3098,7 @@ public struct AttributeClauseFileSyntax: SyntaxProtocol, SyntaxHashable, _LeafSy /// - `atSign`: `@` /// - `attributeName`: ``TypeSyntax`` /// - `leftParen`: `(`? -/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | ``ABIAttributeArgumentsSyntax``)? +/// - `arguments`: (``LabeledExprListSyntax`` | ``AvailabilityArgumentListSyntax`` | ``SpecializeAttributeArgumentListSyntax`` | ``SpecializedAttributeArgumentSyntax`` | ``ObjCSelectorPieceListSyntax`` | ``ImplementsAttributeArgumentsSyntax`` | ``DifferentiableAttributeArgumentsSyntax`` | ``DerivativeAttributeArgumentsSyntax`` | ``BackDeployedAttributeArgumentsSyntax`` | ``OriginallyDefinedInAttributeArgumentsSyntax`` | ``DynamicReplacementAttributeArgumentsSyntax`` | ``EffectsAttributeArgumentListSyntax`` | ``DocumentationAttributeArgumentListSyntax`` | ``ABIAttributeArgumentsSyntax``)? /// - `rightParen`: `)`? /// /// ### Contained in @@ -3110,6 +3110,7 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr case argumentList(LabeledExprListSyntax) case availability(AvailabilityArgumentListSyntax) case specializeArguments(SpecializeAttributeArgumentListSyntax) + case specializedArguments(SpecializedAttributeArgumentSyntax) case objCName(ObjCSelectorPieceListSyntax) case implementsArguments(ImplementsAttributeArgumentsSyntax) case differentiableArguments(DifferentiableAttributeArgumentsSyntax) @@ -3129,6 +3130,8 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return node._syntaxNode case .specializeArguments(let node): return node._syntaxNode + case .specializedArguments(let node): + return node._syntaxNode case .objCName(let node): return node._syntaxNode case .implementsArguments(let node): @@ -3164,6 +3167,10 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .specializeArguments(node) } + public init(_ node: SpecializedAttributeArgumentSyntax) { + self = .specializedArguments(node) + } + public init(_ node: ObjCSelectorPieceListSyntax) { self = .objCName(node) } @@ -3211,6 +3218,8 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self = .availability(node) } else if let node = node.as(SpecializeAttributeArgumentListSyntax.self) { self = .specializeArguments(node) + } else if let node = node.as(SpecializedAttributeArgumentSyntax.self) { + self = .specializedArguments(node) } else if let node = node.as(ObjCSelectorPieceListSyntax.self) { self = .objCName(node) } else if let node = node.as(ImplementsAttributeArgumentsSyntax.self) { @@ -3241,6 +3250,7 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr .node(LabeledExprListSyntax.self), .node(AvailabilityArgumentListSyntax.self), .node(SpecializeAttributeArgumentListSyntax.self), + .node(SpecializedAttributeArgumentSyntax.self), .node(ObjCSelectorPieceListSyntax.self), .node(ImplementsAttributeArgumentsSyntax.self), .node(DifferentiableAttributeArgumentsSyntax.self), @@ -3320,6 +3330,28 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr return self.as(SpecializeAttributeArgumentListSyntax.self)! } + /// Checks if the current syntax node can be cast to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: `true` if the node can be cast, `false` otherwise. + public func `is`(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> Bool { + return self.as(syntaxType) != nil + } + + /// Attempts to cast the current syntax node to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: An instance of ``SpecializedAttributeArgumentSyntax``, or `nil` if the cast fails. + public func `as`(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> SpecializedAttributeArgumentSyntax? { + return SpecializedAttributeArgumentSyntax.init(self) + } + + /// Force-casts the current syntax node to ``SpecializedAttributeArgumentSyntax``. + /// + /// - Returns: An instance of ``SpecializedAttributeArgumentSyntax``. + /// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast. + public func cast(_ syntaxType: SpecializedAttributeArgumentSyntax.Type) -> SpecializedAttributeArgumentSyntax { + return self.as(SpecializedAttributeArgumentSyntax.self)! + } + /// Checks if the current syntax node can be cast to ``ObjCSelectorPieceListSyntax``. /// /// - Returns: `true` if the node can be cast, `false` otherwise. diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index 6fd799b9e7f..b61d7b799ca 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -1261,6 +1261,7 @@ public struct GenericSpecializationExprSyntax: ExprSyntaxProtocol, SyntaxHashabl /// - ``MacroDeclSyntax``.``MacroDeclSyntax/genericWhereClause`` /// - ``ProtocolDeclSyntax``.``ProtocolDeclSyntax/genericWhereClause`` /// - ``SpecializeAttributeArgumentListSyntax`` +/// - ``SpecializedAttributeArgumentSyntax``.``SpecializedAttributeArgumentSyntax/genericWhereClause`` /// - ``StructDeclSyntax``.``StructDeclSyntax/genericWhereClause`` /// - ``SubscriptDeclSyntax``.``SubscriptDeclSyntax/genericWhereClause`` /// - ``TypeAliasDeclSyntax``.``TypeAliasDeclSyntax/genericWhereClause`` diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift index 1a705af1c4d..e8af78d650f 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesQRS.swift @@ -2062,6 +2062,87 @@ public struct SpecializeTargetFunctionArgumentSyntax: SyntaxProtocol, SyntaxHash ]) } +// MARK: - SpecializedAttributeArgumentSyntax + +/// The generic where clause for the `@specialized` attribute +/// +/// ### Children +/// +/// - `genericWhereClause`: ``GenericWhereClauseSyntax`` +/// +/// ### Contained in +/// +/// - ``AttributeSyntax``.``AttributeSyntax/arguments`` +public struct SpecializedAttributeArgumentSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { + public let _syntaxNode: Syntax + + public init?(_ node: __shared some SyntaxProtocol) { + guard node.raw.kind == .specializedAttributeArgument else { + return nil + } + self._syntaxNode = node._syntaxNode + } + + @_transparent + init(unsafeCasting node: Syntax) { + self._syntaxNode = node + } + + /// - Parameters: + /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeGenericWhereClause: UnexpectedNodesSyntax? = nil, + genericWhereClause: GenericWhereClauseSyntax, + _ unexpectedAfterGenericWhereClause: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + // Extend the lifetime of all parameters so their arenas don't get destroyed + // before they can be added as children of the new arena. + self = withExtendedLifetime((RawSyntaxArena(), (unexpectedBeforeGenericWhereClause, genericWhereClause, unexpectedAfterGenericWhereClause))) { (arena, _) in + let layout: [RawSyntax?] = [unexpectedBeforeGenericWhereClause?.raw, genericWhereClause.raw, unexpectedAfterGenericWhereClause?.raw] + let raw = RawSyntax.makeLayout( + kind: SyntaxKind.specializedAttributeArgument, + from: layout, + arena: arena, + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia + ) + return Syntax.forRoot(raw, rawNodeArena: arena).cast(Self.self) + } + } + + public var unexpectedBeforeGenericWhereClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 0)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 0, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public var genericWhereClause: GenericWhereClauseSyntax { + get { + return Syntax(self).child(at: 1)!.cast(GenericWhereClauseSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 1, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public var unexpectedAfterGenericWhereClause: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 2, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(SpecializedAttributeArgumentSyntax.self) + } + } + + public static let structure: SyntaxNodeStructure = .layout([\Self.unexpectedBeforeGenericWhereClause, \Self.genericWhereClause, \Self.unexpectedAfterGenericWhereClause]) +} + // MARK: - StringLiteralExprSyntax /// A string literal. diff --git a/Tests/SwiftParserTest/AttributeTests.swift b/Tests/SwiftParserTest/AttributeTests.swift index 5d82301c61e..695df2b4735 100644 --- a/Tests/SwiftParserTest/AttributeTests.swift +++ b/Tests/SwiftParserTest/AttributeTests.swift @@ -39,6 +39,30 @@ final class AttributeTests: ParserTestCase { } """ ) + + assertParse( + """ + @specializedℹ️(1️⃣ + func 2️⃣foo() { + } + """, + diagnostics: [ + DiagnosticSpec( + message: "expected argument for '@specialized' attribute", + fixIts: ["insert attribute argument"] + ), + DiagnosticSpec( + message: "expected ')' to end attribute", + notes: [NoteSpec(message: "to match this opening '('")], + fixIts: ["insert ')'"] + ), + ], + fixedSource: """ + @specialized(where <#type#> == <#type#>) + func foo() { + } + """ + ) } func testMissingGenericTypeToAttribute() { @@ -87,6 +111,12 @@ final class AttributeTests: ParserTestCase { func foo(_ t: T) {} """ ) + assertParse( + """ + @specialized(where T : Int) + func foo(_ t: T) {} + """ + ) } func testMissingClosingParenToAttribute() { diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 7ec097ec5bd..77d621a8f64 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -770,6 +770,15 @@ final class DeclarationTests: ParserTestCase { } """ ) + assertParse( + """ + @specialized(where Array == Int) + @specialized(where T.Element == Int) + public func funcWithComplexSpecializeRequirements(t: T) -> Int { + return 55555 + } + """ + ) } func testParseRetroactiveExtension() { From 0efe93161ae29830b57fd82317bbf697ae99cf9f Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Fri, 23 May 2025 17:27:57 -0700 Subject: [PATCH 09/10] Add a `SendableMetatype` conformance to `Macro` `Macro.Type` is used in various `Error`s and since SE-0470, needs to conform to `SendableMetatype`. --- Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift b/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift index 6203a6f9127..3045b364475 100644 --- a/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift +++ b/Sources/SwiftSyntaxMacros/MacroProtocols/Macro.swift @@ -10,9 +10,18 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=6.2) +/// Describes a macro. +public protocol Macro: SendableMetatype { + /// How the resulting expansion should be formatted, `.auto` by default. + /// Use `.disabled` for the expansion to be used as is. + static var formatMode: FormatMode { get } +} +#else /// Describes a macro. public protocol Macro { /// How the resulting expansion should be formatted, `.auto` by default. /// Use `.disabled` for the expansion to be used as is. static var formatMode: FormatMode { get } } +#endif From 07fff59cf4f449d347bfbd9844910fe0b8803916 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 30 May 2025 14:14:22 +0100 Subject: [PATCH 10/10] Change InlineArray sugar separator `x` -> `of` --- .../Sources/SyntaxSupport/KeywordSpec.swift | 3 -- .../Sources/SyntaxSupport/TypeNodes.swift | 6 +-- .../ValidateSyntaxNodes.swift | 5 ++- Sources/SwiftParser/TokenPrecedence.swift | 1 - Sources/SwiftParser/Types.swift | 14 +++---- Sources/SwiftSyntax/generated/Keyword.swift | 10 ----- .../generated/raw/RawSyntaxValidation.swift | 2 +- .../syntaxNodes/SyntaxNodesGHI.swift | 10 ++--- .../SwiftParserTest/ExpressionTypeTests.swift | 40 +++++++++---------- Tests/SwiftParserTest/TypeTests.swift | 32 +++++++-------- 10 files changed, 55 insertions(+), 68 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index a0e6730e18d..eeb66ea4b56 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -276,7 +276,6 @@ public enum Keyword: CaseIterable { case `while` case willSet case wrt - case x case yield public var spec: KeywordSpec { @@ -685,8 +684,6 @@ public enum Keyword: CaseIterable { return KeywordSpec("willSet") case .wrt: return KeywordSpec("wrt") - case .x: - return KeywordSpec("x", experimentalFeature: .inlineArrayTypeSugar) case .yield: return KeywordSpec("yield") } diff --git a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift index 3d65755fa45..ab81dde2a2d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TypeNodes.swift @@ -304,7 +304,7 @@ public let TYPE_NODES: [Node] = [ base: .type, experimentalFeature: .inlineArrayTypeSugar, nameForDiagnostics: "inline array type", - documentation: "An inline array type `[3 x Int]`, sugar for `InlineArray<3, Int>`.", + documentation: "An inline array type `[3 of Int]`, sugar for `InlineArray<3, Int>`.", children: [ Child( name: "leftSquare", @@ -317,12 +317,12 @@ public let TYPE_NODES: [Node] = [ documentation: """ The `count` argument for the inline array type. - - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ x Int]`. + - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ of Int]`. """ ), Child( name: "separator", - kind: .token(choices: [.keyword(.x)]) + kind: .token(choices: [.keyword(.of)]) ), Child( name: "element", diff --git a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift index d2eceb9334f..164b1505895 100644 --- a/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift +++ b/CodeGeneration/Tests/ValidateSyntaxNodes/ValidateSyntaxNodes.swift @@ -372,10 +372,11 @@ class ValidateSyntaxNodes: XCTestCase { message: "child 'defaultKeyword' has a single keyword as its only token choice and is followed by a colon. It should thus be named 'defaultLabel'" ), - // 'separator' is more descriptive than 'xKeyword' + // 'separator' is more descriptive than 'ofKeyword' ValidationFailure( node: .inlineArrayType, - message: "child 'separator' has a single keyword as its only token choice and should thus be named 'xKeyword'" + message: + "child 'separator' has a single keyword as its only token choice and should thus be named 'ofKeyword'" ), ] ) diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index c0a9a04bd08..2879548d56c 100644 --- a/Sources/SwiftParser/TokenPrecedence.swift +++ b/Sources/SwiftParser/TokenPrecedence.swift @@ -345,7 +345,6 @@ enum TokenPrecedence: Comparable { .visibility, .weak, .wrt, - .x, .unsafe: self = .exprKeyword #if RESILIENT_LIBRARIES diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 58eacfa59b9..68a6428ef49 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -649,11 +649,11 @@ extension Parser { precondition(self.experimentalFeatures.contains(.inlineArrayTypeSugar)) // We allow both values and types here and for the element type for - // better recovery in cases where the user writes e.g '[Int x 3]'. + // better recovery in cases where the user writes e.g '[Int of 3]'. let count = self.parseGenericArgumentType() let (unexpectedBeforeSeparator, separator) = self.expect( - TokenSpec(.x, allowAtStartOfLine: false) + TokenSpec(.of, allowAtStartOfLine: false) ) let element = self.parseGenericArgumentType() @@ -879,18 +879,18 @@ extension Parser.Lookahead { return false } - // We must have at least '[ x', which cannot be any other + // We must have at least '[ of', which cannot be any other // kind of expression or type. We specifically look for both types and // integers for better recovery in e.g cases where the user writes e.g - // '[Int x 2]'. We only do type-scalar since variadics would be ambiguous - // e.g 'Int...x'. + // '[Int of 2]'. We only do type-scalar since variadics would be ambiguous + // e.g 'Int...of'. guard self.canParseTypeScalar() || self.canParseIntegerLiteral() else { return false } // We don't currently allow multi-line since that would require // disambiguation with array literals. - return self.consume(if: TokenSpec(.x, allowAtStartOfLine: false)) != nil + return self.consume(if: TokenSpec(.of, allowAtStartOfLine: false)) != nil } mutating func canParseInlineArrayTypeBody() -> Bool { @@ -898,7 +898,7 @@ extension Parser.Lookahead { return false } // Note we look for both types and integers for better recovery in e.g cases - // where the user writes e.g '[Int x 2]'. + // where the user writes e.g '[Int of 2]'. guard self.canParseGenericArgument() else { return false } diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 3a848bf62b7..aedba46b9f1 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -222,19 +222,10 @@ public enum Keyword: UInt8, Hashable, Sendable { case `while` case willSet case wrt - @_spi(ExperimentalLanguageFeatures) - case x case yield @_spi(RawSyntax) public init?(_ text: SyntaxText) { switch text.count { - case 1: - switch text { - case "x": - self = .x - default: - return nil - } case 2: switch text { case "as": @@ -964,7 +955,6 @@ public enum Keyword: UInt8, Hashable, Sendable { "while", "willSet", "wrt", - "x", "yield", ] diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 182d2d0aeba..4eb22f87384 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1748,7 +1748,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 3, verify(layout[3], as: RawGenericArgumentSyntax.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.keyword("x")])) + assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [.keyword("of")])) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 7, verify(layout[7], as: RawGenericArgumentSyntax.self)) assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index b61d7b799ca..b6eec06d4b0 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -4373,7 +4373,7 @@ public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDe // MARK: - InlineArrayTypeSyntax -/// An inline array type `[3 x Int]`, sugar for `InlineArray<3, Int>`. +/// An inline array type `[3 of Int]`, sugar for `InlineArray<3, Int>`. /// /// - Note: Requires experimental feature `inlineArrayTypeSugar`. /// @@ -4381,7 +4381,7 @@ public struct InitializerDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDe /// /// - `leftSquare`: `[` /// - `count`: ``GenericArgumentSyntax`` -/// - `separator`: `x` +/// - `separator`: `of` /// - `element`: ``GenericArgumentSyntax`` /// - `rightSquare`: `]` @_spi(ExperimentalLanguageFeatures) @@ -4412,7 +4412,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy _ unexpectedBetweenLeftSquareAndCount: UnexpectedNodesSyntax? = nil, count: GenericArgumentSyntax, _ unexpectedBetweenCountAndSeparator: UnexpectedNodesSyntax? = nil, - separator: TokenSyntax = .keyword(.x), + separator: TokenSyntax = .keyword(.of), _ unexpectedBetweenSeparatorAndElement: UnexpectedNodesSyntax? = nil, element: GenericArgumentSyntax, _ unexpectedBetweenElementAndRightSquare: UnexpectedNodesSyntax? = nil, @@ -4491,7 +4491,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy /// The `count` argument for the inline array type. /// - /// - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ x Int]`. + /// - Note: In semantically valid Swift code, this is always an integer or a wildcard type, e.g `_` in `[_ of Int]`. public var count: GenericArgumentSyntax { get { return Syntax(self).child(at: 3)!.cast(GenericArgumentSyntax.self) @@ -4512,7 +4512,7 @@ public struct InlineArrayTypeSyntax: TypeSyntaxProtocol, SyntaxHashable, _LeafTy /// ### Tokens /// - /// For syntax trees generated by the parser, this is guaranteed to be `x`. + /// For syntax trees generated by the parser, this is guaranteed to be `of`. public var separator: TokenSyntax { get { return Syntax(self).child(at: 5)!.cast(TokenSyntax.self) diff --git a/Tests/SwiftParserTest/ExpressionTypeTests.swift b/Tests/SwiftParserTest/ExpressionTypeTests.swift index 5def6ec1241..f9f6587dbe4 100644 --- a/Tests/SwiftParserTest/ExpressionTypeTests.swift +++ b/Tests/SwiftParserTest/ExpressionTypeTests.swift @@ -111,26 +111,26 @@ final class ExpressionTypeTests: ParserTestCase { // Make sure we can handle cases where the type is spelled first in // an InlineArray sugar type. let cases: [UInt: String] = [ - #line: "[3 x Int]", - #line: "[[3 x Int]]", - #line: "[[Int x 3]]", - #line: "[_ x Int]", - #line: "[Int x Int]", - #line: "[@escaping () -> Int x Int]", - #line: "[Int.Type x Int]", - #line: "[sending P & Q x Int]", - #line: "[(some P & Q) -> Int x Int]", - #line: "[~P x Int]", - #line: "[(Int, String) x Int]", - #line: "[G x Int]", - #line: "[[3 x Int] x Int]", - #line: "[[Int] x Int]", - #line: "[_ x Int]", - #line: "[_? x Int]", - #line: "[_?x Int]", - #line: "[_! x Int]", - #line: "[_!x Int]", - #line: "[Int?x Int]", + #line: "[3 of Int]", + #line: "[[3 of Int]]", + #line: "[[Int of 3]]", + #line: "[_ of Int]", + #line: "[Int of Int]", + #line: "[@escaping () -> Int of Int]", + #line: "[Int.Type of Int]", + #line: "[sending P & Q of Int]", + #line: "[(some P & Q) -> Int of Int]", + #line: "[~P of Int]", + #line: "[(Int, String) of Int]", + #line: "[G of Int]", + #line: "[[3 of Int] of Int]", + #line: "[[Int] of Int]", + #line: "[_ of Int]", + #line: "[_? of Int]", + #line: "[_?of Int]", + #line: "[_! of Int]", + #line: "[_!of Int]", + #line: "[Int?of Int]", ] for (line, type) in cases { assertParse( diff --git a/Tests/SwiftParserTest/TypeTests.swift b/Tests/SwiftParserTest/TypeTests.swift index 2d317551c14..4ab3316b6b7 100644 --- a/Tests/SwiftParserTest/TypeTests.swift +++ b/Tests/SwiftParserTest/TypeTests.swift @@ -781,18 +781,18 @@ final class InlineArrayTypeTests: ParserTestCase { func testBasic() { assertParse( - "[3 x Int]", + "[3 of Int]", substructure: InlineArrayTypeSyntax( count: .init(argument: .expr("3")), - separator: .keyword(.x), + separator: .keyword(.of), element: .init(argument: .type(TypeSyntax("Int"))) ) ) assertParse( - "[Int x _]", + "[Int of _]", substructure: InlineArrayTypeSyntax( count: .init(argument: .type(TypeSyntax("Int"))), - separator: .keyword(.x), + separator: .keyword(.of), element: .init(argument: .type(TypeSyntax("_"))) ) ) @@ -804,7 +804,7 @@ final class InlineArrayTypeTests: ParserTestCase { """ S<[ 3 - 1️⃣x + 1️⃣of Int ]>() """, @@ -815,7 +815,7 @@ final class InlineArrayTypeTests: ParserTestCase { assertParse( """ S<[3 - 1️⃣x + 1️⃣of Int ]>() """, @@ -826,23 +826,23 @@ final class InlineArrayTypeTests: ParserTestCase { assertParse( """ S<[3 - 1️⃣x Int]>() + 1️⃣of Int]>() """, diagnostics: [ - DiagnosticSpec(message: "unexpected code 'x Int' in array") + DiagnosticSpec(message: "unexpected code 'of Int' in array") ] ) // These are okay. assertParse( """ - S<[3 x + S<[3 of Int]>() """ ) assertParse( """ S<[ - 3 x Int + 3 of Int ]>() """ ) @@ -850,17 +850,17 @@ final class InlineArrayTypeTests: ParserTestCase { func testDiagnostics() { assertParse( - "2️⃣[3 x1️⃣", + "2️⃣[3 of1️⃣", diagnostics: [ DiagnosticSpec( message: "expected element type and ']' to end inline array type", fixIts: ["insert element type and ']'"] ) ], - fixedSource: "[3 x <#type#>]" + fixedSource: "[3 of <#type#>]" ) assertParse( - "ℹ️[3 x Int1️⃣", + "ℹ️[3 of Int1️⃣", diagnostics: [ DiagnosticSpec( message: "expected ']' to end inline array type", @@ -868,12 +868,12 @@ final class InlineArrayTypeTests: ParserTestCase { fixIts: ["insert ']'"] ) ], - fixedSource: "[3 x Int]" + fixedSource: "[3 of Int]" ) } func testEllipsis() { - // Make sure this isn't parsed as ' x ' - assertParse("[x...x]") + // Make sure this isn't parsed as ' of ' + assertParse("[x...of]") } }