diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 50daee24036..4ece892b6f7 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -89,6 +89,7 @@ public let DECL_NODES: [Node] = [ traits: [ "WithOptionalCodeBlock", "WithAttributes", + "WithModifiers", ], children: [ Child( @@ -97,10 +98,10 @@ public let DECL_NODES: [Node] = [ nameForDiagnostics: "attributes" ), Child( - name: "modifier", - kind: .node(kind: .declModifier), + name: "modifiers", + kind: .collection(kind: .declModifierList, collectionElementName: "Modifier", defaultsToEmpty: true), nameForDiagnostics: "modifiers", - isOptional: true + documentation: "Modifiers like `mutating` or `yielding` that affect the accessor declaration." ), Child( name: "accessorSpecifier", @@ -495,6 +496,7 @@ public let DECL_NODES: [Node] = [ .keyword(.unowned), .keyword(.weak), .keyword(.sending), + .keyword(.yielding), ]) ), Child( diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 2b1809ae634..e8aeee549ef 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -279,6 +279,7 @@ public enum Keyword: CaseIterable { case willSet case wrt case yield + case yielding public var spec: KeywordSpec { switch self { @@ -537,7 +538,7 @@ public enum Keyword: CaseIterable { case .module: return KeywordSpec("module") case .mutate: - return KeywordSpec("mutate", experimentalFeature: .borrowAndMutateAccessors) + return KeywordSpec("mutate") case .mutableAddressWithNativeOwner: return KeywordSpec("mutableAddressWithNativeOwner") case .mutableAddressWithOwner: @@ -692,6 +693,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("wrt") case .yield: return KeywordSpec("yield") + case .yielding: + return KeywordSpec("yielding") } } } diff --git a/Sources/SwiftParser/CollectionNodes+Parsable.swift b/Sources/SwiftParser/CollectionNodes+Parsable.swift index 3424de77418..f3083ac4601 100644 --- a/Sources/SwiftParser/CollectionNodes+Parsable.swift +++ b/Sources/SwiftParser/CollectionNodes+Parsable.swift @@ -67,7 +67,7 @@ extension AccessorDeclListSyntax: SyntaxParseable { } makeMissing: { remainingTokens, arena in return RawAccessorDeclSyntax( attributes: RawAttributeListSyntax(elements: [], arena: arena), - modifier: nil, + modifiers: RawDeclModifierListSyntax(elements: [], arena: arena), accessorSpecifier: RawTokenSyntax(missing: .keyword, text: "get", arena: arena), parameters: nil, effectSpecifiers: nil, diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index bfe5d3022e1..8f4731a7871 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1658,44 +1658,51 @@ extension Parser { struct AccessorIntroducer { var attributes: RawAttributeListSyntax - var modifier: RawDeclModifierSyntax? + var modifiers: RawDeclModifierListSyntax var kind: AccessorDeclSyntax.AccessorSpecifierOptions var unexpectedBeforeToken: RawUnexpectedNodesSyntax? var token: RawTokenSyntax } + mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax { + var elements = [RawDeclModifierSyntax]() + + for _ in 0.. AccessorIntroducer? { - // Check there is an identifier before consuming + // Look ahead to verify attributes/modifiers/kind var look = self.lookahead() let _ = look.consumeAttributeList() - let hasModifier = look.consume(ifAnyIn: AccessorModifier.self) != nil + let modifierCount = look.consume(anySequence: AccessorModifier.self) guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else { return nil } let attrs = self.parseAttributeList() - - // Parse the contextual keywords for 'mutating' and 'nonmutating' before - // get and set. - let modifier: RawDeclModifierSyntax? - if hasModifier { - let (unexpectedBeforeName, name) = self.expect(anyIn: AccessorModifier.self, default: .mutating) - modifier = RawDeclModifierSyntax( - unexpectedBeforeName, - name: name, - detail: nil, - arena: self.arena - ) - } else { - modifier = nil - } + let modifiers = self.parseAccessorModifierList(count: modifierCount) let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) + return AccessorIntroducer( attributes: attrs, - modifier: modifier, + modifiers: modifiers, kind: kind, unexpectedBeforeToken: unexpectedBeforeIntroducer, token: introducer @@ -1738,7 +1745,7 @@ extension Parser { let body = self.parseOptionalCodeBlock() return RawAccessorDeclSyntax( attributes: introducer.attributes, - modifier: introducer.modifier, + modifiers: introducer.modifiers, introducer.unexpectedBeforeToken, accessorSpecifier: introducer.token, parameters: parameters, diff --git a/Sources/SwiftParser/Lookahead.swift b/Sources/SwiftParser/Lookahead.swift index ff3b1a66b2f..7b1cfcd7379 100644 --- a/Sources/SwiftParser/Lookahead.swift +++ b/Sources/SwiftParser/Lookahead.swift @@ -160,6 +160,18 @@ extension Parser.Lookahead { } } +// MARK: Skipping a sequence of tokens + +extension Parser.Lookahead { + mutating func consume(anySequence: SpecSet.Type) -> Int { + var count = 0 + while consume(ifAnyIn: SpecSet.self) != nil { + count += 1 + } + return count + } +} + // MARK: Skipping Tokens extension Parser.Lookahead { diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index 212d6dfbcfa..484d4e92792 100644 --- a/Sources/SwiftParser/TokenPrecedence.swift +++ b/Sources/SwiftParser/TokenPrecedence.swift @@ -237,7 +237,7 @@ enum TokenPrecedence: Comparable { .dependsOn, .scoped, .sending, // Accessors .get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress, - .mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate, + .mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate, .yielding, // Misc .import, .using: self = .declKeyword diff --git a/Sources/SwiftParser/TokenSpecSet.swift b/Sources/SwiftParser/TokenSpecSet.swift index d44c9410047..4b95ff00996 100644 --- a/Sources/SwiftParser/TokenSpecSet.swift +++ b/Sources/SwiftParser/TokenSpecSet.swift @@ -66,6 +66,7 @@ enum AccessorModifier: TokenSpecSet { case borrowing case mutating case nonmutating + case yielding init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { @@ -74,6 +75,7 @@ enum AccessorModifier: TokenSpecSet { case TokenSpec(.borrowing): self = .borrowing case TokenSpec(.mutating): self = .mutating case TokenSpec(.nonmutating): self = .nonmutating + case TokenSpec(.yielding): self = .yielding default: return nil } } @@ -85,6 +87,7 @@ enum AccessorModifier: TokenSpecSet { case .borrowing: return .keyword(.borrowing) case .mutating: return .keyword(.mutating) case .nonmutating: return .keyword(.nonmutating) + case .yielding: return .keyword(.yielding) } } } diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index 92d9b8d96a4..3cf7c524456 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -40,7 +40,6 @@ extension AccessorDeclSyntax { case modify case `init` case borrow - @_spi(ExperimentalLanguageFeatures) case mutate init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { @@ -77,7 +76,7 @@ extension AccessorDeclSyntax { self = .`init` case TokenSpec(.borrow): self = .borrow - case TokenSpec(.mutate) where experimentalFeatures.contains(.borrowAndMutateAccessors): + case TokenSpec(.mutate): self = .mutate default: return nil @@ -951,6 +950,7 @@ extension DeclModifierSyntax { case unowned case weak case sending + case yielding init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { @@ -1026,6 +1026,8 @@ extension DeclModifierSyntax { self = .weak case TokenSpec(.sending): self = .sending + case TokenSpec(.yielding): + self = .yielding default: return nil } @@ -1105,6 +1107,8 @@ extension DeclModifierSyntax { self = .weak case TokenSpec(.sending): self = .sending + case TokenSpec(.yielding): + self = .yielding default: return nil } @@ -1184,6 +1188,8 @@ extension DeclModifierSyntax { return .keyword(.weak) case .sending: return .keyword(.sending) + case .yielding: + return .keyword(.yielding) } } @@ -1265,6 +1271,8 @@ extension DeclModifierSyntax { return .keyword(.weak) case .sending: return .keyword(.sending) + case .yielding: + return .keyword(.yielding) } } } diff --git a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift index f047dc2cc51..bfe3b5c8175 100644 --- a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift @@ -23,7 +23,7 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? { switch keyPath { case \AccessorDeclSyntax.attributes: return "attributes" - case \AccessorDeclSyntax.modifier: + case \AccessorDeclSyntax.modifiers: return "modifiers" case \AccessorDeclSyntax.parameters: return "parameter" diff --git a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift index 3adfb33fbd0..402a0b7b4c7 100644 --- a/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift +++ b/Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift @@ -13,6 +13,36 @@ // This file provides compatibility aliases to keep dependents of SwiftSyntax building. // All users of the declarations in this file should transition away from them ASAP. +extension AccessorDeclSyntax { + @available(*, deprecated, message: "use modifiers to see all modifiers on an accessor declaration") + public var modifier: DeclModifierSyntax? { + get { + // The legacy `modifier` API predates `yielding` + if let m = modifiers.first(where: { $0.name.text != "yielding" }) { + return m + } + return nil + } + set { + if let newValue { + modifiers = [newValue] + } else { + modifiers = [] + } + } + } + @available(*, deprecated, message: "use unexpectedBetweenAttributesAndModifers") + public var unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? { + get { unexpectedBetweenAttributesAndModifiers } + set { unexpectedBetweenAttributesAndModifiers = newValue } + } + @available(*, deprecated, message: "use unexpectedBetweenModifiersAndAccessorSpecifier") + public var unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? { + get { unexpectedBetweenModifiersAndAccessorSpecifier } + set { unexpectedBetweenModifiersAndAccessorSpecifier = newValue } + } +} + extension AccessorEffectSpecifiersSyntax { @_disfavoredOverload @available(*, deprecated, message: "use throwsClause instead of throwsSpecifier") diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index db537fb970b..6e333bc6b61 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -60,12 +60,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBeforeAttributes" case \AccessorDeclSyntax.attributes: return "attributes" - case \AccessorDeclSyntax.unexpectedBetweenAttributesAndModifier: - return "unexpectedBetweenAttributesAndModifier" - case \AccessorDeclSyntax.modifier: - return "modifier" - case \AccessorDeclSyntax.unexpectedBetweenModifierAndAccessorSpecifier: - return "unexpectedBetweenModifierAndAccessorSpecifier" + case \AccessorDeclSyntax.unexpectedBetweenAttributesAndModifiers: + return "unexpectedBetweenAttributesAndModifiers" + case \AccessorDeclSyntax.modifiers: + return "modifiers" + case \AccessorDeclSyntax.unexpectedBetweenModifiersAndAccessorSpecifier: + return "unexpectedBetweenModifiersAndAccessorSpecifier" case \AccessorDeclSyntax.accessorSpecifier: return "accessorSpecifier" case \AccessorDeclSyntax.unexpectedBetweenAccessorSpecifierAndParameters: diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 31007c1ade1..c1b547a9678 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -145,7 +145,6 @@ public enum Keyword: UInt8, Hashable, Sendable { @_spi(ExperimentalLanguageFeatures) case modify case module - @_spi(ExperimentalLanguageFeatures) case mutate case mutableAddressWithNativeOwner case mutableAddressWithOwner @@ -226,6 +225,7 @@ public enum Keyword: UInt8, Hashable, Sendable { case willSet case wrt case yield + case yielding @_spi(RawSyntax) public init?(_ text: SyntaxText) { switch text.count { @@ -590,6 +590,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = .rethrows case "Sendable": self = .Sendable + case "yielding": + self = .yielding default: return nil } @@ -1053,6 +1055,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "willSet", "wrt", "yield", + "yielding", ] @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift index 1d82e4cbad3..243ce033f0f 100644 --- a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift @@ -14,13 +14,13 @@ // swift-format-ignore-file extension AccessorDeclSyntax { - @available(*, deprecated, renamed: "unexpectedBetweenModifierAndAccessorSpecifier") - public var unexpectedBetweenModifierAndAccessorKind: UnexpectedNodesSyntax? { + @available(*, deprecated, renamed: "unexpectedBetweenModifiersAndAccessorSpecifier") + public var unexpectedBetweenModifiersAndAccessorKind: UnexpectedNodesSyntax? { get { - return unexpectedBetweenModifierAndAccessorSpecifier + return unexpectedBetweenModifiersAndAccessorSpecifier } set { - unexpectedBetweenModifierAndAccessorSpecifier = newValue + unexpectedBetweenModifiersAndAccessorSpecifier = newValue } } @@ -64,15 +64,15 @@ extension AccessorDeclSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:modifier:_:accessorSpecifier:_:parameters:_:effectSpecifiers:_:body:_:trailingTrivia:)") + @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:modifiers:_:accessorSpecifier:_:parameters:_:effectSpecifiers:_:body:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - _ unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? = nil, - modifier: DeclModifierSyntax? = nil, - _ unexpectedBetweenModifierAndAccessorKind: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + _ unexpectedBetweenModifiersAndAccessorKind: UnexpectedNodesSyntax? = nil, accessorKind: TokenSyntax, _ unexpectedBetweenAccessorKindAndParameter: UnexpectedNodesSyntax? = nil, parameter: AccessorParametersSyntax? = nil, @@ -87,9 +87,9 @@ extension AccessorDeclSyntax { leadingTrivia: leadingTrivia, unexpectedBeforeAttributes, attributes: attributes, - unexpectedBetweenAttributesAndModifier, - modifier: modifier, - unexpectedBetweenModifierAndAccessorKind, + unexpectedBetweenAttributesAndModifiers, + modifiers: modifiers, + unexpectedBetweenModifiersAndAccessorKind, accessorSpecifier: accessorKind, unexpectedBetweenAccessorKindAndParameter, parameters: parameter, diff --git a/Sources/SwiftSyntax/generated/SyntaxCollections.swift b/Sources/SwiftSyntax/generated/SyntaxCollections.swift index 529785471e9..66824658e29 100644 --- a/Sources/SwiftSyntax/generated/SyntaxCollections.swift +++ b/Sources/SwiftSyntax/generated/SyntaxCollections.swift @@ -483,6 +483,7 @@ public struct ConditionElementListSyntax: SyntaxCollection, SyntaxHashable { /// /// ### Contained in /// +/// - ``AccessorDeclSyntax``.``AccessorDeclSyntax/modifiers`` /// - ``ActorDeclSyntax``.``ActorDeclSyntax/modifiers`` /// - ``AssociatedTypeDeclSyntax``.``AssociatedTypeDeclSyntax/modifiers`` /// - ``ClassDeclSyntax``.``ClassDeclSyntax/modifiers`` diff --git a/Sources/SwiftSyntax/generated/SyntaxTraits.swift b/Sources/SwiftSyntax/generated/SyntaxTraits.swift index 670ea0e0dac..90bb01eec08 100644 --- a/Sources/SwiftSyntax/generated/SyntaxTraits.swift +++ b/Sources/SwiftSyntax/generated/SyntaxTraits.swift @@ -679,7 +679,7 @@ extension SyntaxProtocol { extension AccessorBlockSyntax: BracedSyntax {} -extension AccessorDeclSyntax: WithOptionalCodeBlockSyntax, WithAttributesSyntax {} +extension AccessorDeclSyntax: WithOptionalCodeBlockSyntax, WithAttributesSyntax, WithModifiersSyntax {} extension AccessorEffectSpecifiersSyntax: EffectSpecifiersSyntax {} diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift index a04d4c66d1a..56dc1ccc6f3 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift @@ -421,9 +421,9 @@ public struct RawAccessorDeclSyntax: RawDeclSyntaxNodeProtocol { public init( _ unexpectedBeforeAttributes: RawUnexpectedNodesSyntax? = nil, attributes: RawAttributeListSyntax, - _ unexpectedBetweenAttributesAndModifier: RawUnexpectedNodesSyntax? = nil, - modifier: RawDeclModifierSyntax?, - _ unexpectedBetweenModifierAndAccessorSpecifier: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndModifiers: RawUnexpectedNodesSyntax? = nil, + modifiers: RawDeclModifierListSyntax, + _ unexpectedBetweenModifiersAndAccessorSpecifier: RawUnexpectedNodesSyntax? = nil, accessorSpecifier: RawTokenSyntax, _ unexpectedBetweenAccessorSpecifierAndParameters: RawUnexpectedNodesSyntax? = nil, parameters: RawAccessorParametersSyntax?, @@ -439,9 +439,9 @@ public struct RawAccessorDeclSyntax: RawDeclSyntaxNodeProtocol { layout.initialize(repeating: nil) layout[0] = unexpectedBeforeAttributes?.raw layout[1] = attributes.raw - layout[2] = unexpectedBetweenAttributesAndModifier?.raw - layout[3] = modifier?.raw - layout[4] = unexpectedBetweenModifierAndAccessorSpecifier?.raw + layout[2] = unexpectedBetweenAttributesAndModifiers?.raw + layout[3] = modifiers.raw + layout[4] = unexpectedBetweenModifiersAndAccessorSpecifier?.raw layout[5] = accessorSpecifier.raw layout[6] = unexpectedBetweenAccessorSpecifierAndParameters?.raw layout[7] = parameters?.raw @@ -462,15 +462,15 @@ public struct RawAccessorDeclSyntax: RawDeclSyntaxNodeProtocol { layoutView.children[1].map(RawAttributeListSyntax.init(raw:))! } - public var unexpectedBetweenAttributesAndModifier: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenAttributesAndModifiers: RawUnexpectedNodesSyntax? { layoutView.children[2].map(RawUnexpectedNodesSyntax.init(raw:)) } - public var modifier: RawDeclModifierSyntax? { - layoutView.children[3].map(RawDeclModifierSyntax.init(raw:)) + public var modifiers: RawDeclModifierListSyntax { + layoutView.children[3].map(RawDeclModifierListSyntax.init(raw:))! } - public var unexpectedBetweenModifierAndAccessorSpecifier: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenModifiersAndAccessorSpecifier: RawUnexpectedNodesSyntax? { layoutView.children[4].map(RawUnexpectedNodesSyntax.init(raw:)) } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index 2592e549bbd..5910dd955a9 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -247,7 +247,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawAttributeListSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 3, verify(layout[3], as: RawDeclModifierSyntax?.self)) + assertNoError(kind, 3, verify(layout[3], as: RawDeclModifierListSyntax.self)) assertNoError(kind, 4, verify(layout[4], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 5, verify(layout[5], as: RawTokenSyntax.self, tokenChoices: [ .keyword("get"), @@ -887,7 +887,8 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { .keyword("static"), .keyword("unowned"), .keyword("weak"), - .keyword("sending") + .keyword("sending"), + .keyword("yielding") ])) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 3, verify(layout[3], as: RawDeclModifierDetailSyntax?.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index ae96eca8816..acfbe85c452 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -824,7 +824,7 @@ public struct AccessorBlockSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNo /// ### Children /// /// - `attributes`: ``AttributeListSyntax`` -/// - `modifier`: ``DeclModifierSyntax``? +/// - `modifiers`: ``DeclModifierListSyntax`` /// - `accessorSpecifier`: (`get` | `set` | `didSet` | `willSet` | `unsafeAddress` | `addressWithOwner` | `addressWithNativeOwner` | `unsafeMutableAddress` | `mutableAddressWithOwner` | `mutableAddressWithNativeOwner` | `_read` | `read` | `_modify` | `modify` | `init` | `borrow` | `mutate`) /// - `parameters`: ``AccessorParametersSyntax``? /// - `effectSpecifiers`: ``AccessorEffectSpecifiersSyntax``? @@ -850,14 +850,15 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS /// - 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. + /// - modifiers: Modifiers like `mutating` or `yielding` that affect the accessor declaration. /// - 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, _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - _ unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? = nil, - modifier: DeclModifierSyntax? = nil, - _ unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + _ unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, accessorSpecifier: TokenSyntax, _ unexpectedBetweenAccessorSpecifierAndParameters: UnexpectedNodesSyntax? = nil, parameters: AccessorParametersSyntax? = nil, @@ -873,9 +874,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS self = withExtendedLifetime((RawSyntaxArena(), ( unexpectedBeforeAttributes, attributes, - unexpectedBetweenAttributesAndModifier, - modifier, - unexpectedBetweenModifierAndAccessorSpecifier, + unexpectedBetweenAttributesAndModifiers, + modifiers, + unexpectedBetweenModifiersAndAccessorSpecifier, accessorSpecifier, unexpectedBetweenAccessorSpecifierAndParameters, parameters, @@ -888,9 +889,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS let layout: [RawSyntax?] = [ unexpectedBeforeAttributes?.raw, attributes.raw, - unexpectedBetweenAttributesAndModifier?.raw, - modifier?.raw, - unexpectedBetweenModifierAndAccessorSpecifier?.raw, + unexpectedBetweenAttributesAndModifiers?.raw, + modifiers.raw, + unexpectedBetweenModifiersAndAccessorSpecifier?.raw, accessorSpecifier.raw, unexpectedBetweenAccessorSpecifierAndParameters?.raw, parameters?.raw, @@ -956,7 +957,7 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS .cast(AccessorDeclSyntax.self) } - public var unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? { + public var unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 2)?.cast(UnexpectedNodesSyntax.self) } @@ -965,16 +966,44 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS } } - public var modifier: DeclModifierSyntax? { + /// Modifiers like `mutating` or `yielding` that affect the accessor declaration. + public var modifiers: DeclModifierListSyntax { get { - return Syntax(self).child(at: 3)?.cast(DeclModifierSyntax.self) + return Syntax(self).child(at: 3)!.cast(DeclModifierListSyntax.self) } set(value) { self = Syntax(self).replacingChild(at: 3, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(AccessorDeclSyntax.self) } } - public var unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? { + /// Adds the provided `element` to the node's `modifiers` + /// collection. + /// + /// - param element: The new `Modifier` to add to the node's + /// `modifiers` collection. + /// - returns: A copy of the receiver with the provided `Modifier` + /// appended to its `modifiers` collection. + @available(*, deprecated, message: "Use node.modifiers.append(newElement) instead") + public func addModifier(_ element: DeclModifierSyntax) -> AccessorDeclSyntax { + var collection: RawSyntax + let arena = RawSyntaxArena() + if let col = raw.layoutView!.children[3] { + collection = col.layoutView!.appending(element.raw, arena: arena) + } else { + collection = RawSyntax.makeLayout(kind: SyntaxKind.declModifierList, + from: [element.raw], arena: arena) + } + return Syntax(self) + .replacingChild( + at: 3, + with: collection, + rawNodeArena: arena, + rawAllocationArena: arena + ) + .cast(AccessorDeclSyntax.self) + } + + public var unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } @@ -1078,9 +1107,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS public static let structure: SyntaxNodeStructure = .layout([ \Self.unexpectedBeforeAttributes, \Self.attributes, - \Self.unexpectedBetweenAttributesAndModifier, - \Self.modifier, - \Self.unexpectedBetweenModifierAndAccessorSpecifier, + \Self.unexpectedBetweenAttributesAndModifiers, + \Self.modifiers, + \Self.unexpectedBetweenModifiersAndAccessorSpecifier, \Self.accessorSpecifier, \Self.unexpectedBetweenAccessorSpecifierAndParameters, \Self.parameters, diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift index 235fcba86a2..6a6f326f203 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift @@ -171,12 +171,11 @@ public struct DeclModifierDetailSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyn /// ### Children /// -/// - `name`: (`__consuming` | `__setter_access` | `_const` | `_local` | `actor` | `async` | `borrowing` | `class` | `consuming` | `convenience` | `distributed` | `dynamic` | `fileprivate` | `final` | `indirect` | `infix` | `internal` | `isolated` | `lazy` | `mutating` | `nonisolated` | `nonmutating` | `open` | `optional` | `override` | `package` | `postfix` | `prefix` | `private` | `public` | `reasync` | `required` | `static` | `unowned` | `weak` | `sending`) +/// - `name`: (`__consuming` | `__setter_access` | `_const` | `_local` | `actor` | `async` | `borrowing` | `class` | `consuming` | `convenience` | `distributed` | `dynamic` | `fileprivate` | `final` | `indirect` | `infix` | `internal` | `isolated` | `lazy` | `mutating` | `nonisolated` | `nonmutating` | `open` | `optional` | `override` | `package` | `postfix` | `prefix` | `private` | `public` | `reasync` | `required` | `static` | `unowned` | `weak` | `sending` | `yielding`) /// - `detail`: ``DeclModifierDetailSyntax``? /// /// ### Contained in /// -/// - ``AccessorDeclSyntax``.``AccessorDeclSyntax/modifier`` /// - ``DeclModifierListSyntax`` public struct DeclModifierSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { public let _syntaxNode: Syntax @@ -280,6 +279,7 @@ public struct DeclModifierSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNod /// - `unowned` /// - `weak` /// - `sending` + /// - `yielding` public var name: TokenSyntax { get { return Syntax(self).child(at: 1)!.cast(TokenSyntax.self) diff --git a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift index 22a143f7258..40f7ae1c6d9 100644 --- a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift +++ b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift @@ -25,9 +25,9 @@ extension AccessorDeclSyntax { leadingTrivia: Trivia? = nil, unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? = nil, - modifier: DeclModifierSyntax? = nil, - unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, + unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, accessorSpecifier: TokenSyntax, unexpectedBetweenAccessorSpecifierAndParameters: UnexpectedNodesSyntax? = nil, parameters: AccessorParametersSyntax? = nil, @@ -42,9 +42,9 @@ extension AccessorDeclSyntax { leadingTrivia: leadingTrivia, unexpectedBeforeAttributes, attributes: attributes, - unexpectedBetweenAttributesAndModifier, - modifier: modifier, - unexpectedBetweenModifierAndAccessorSpecifier, + unexpectedBetweenAttributesAndModifiers, + modifiers: modifiers, + unexpectedBetweenModifiersAndAccessorSpecifier, accessorSpecifier: accessorSpecifier, unexpectedBetweenAccessorSpecifierAndParameters, parameters: parameters, diff --git a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift index a60a0524b6f..40dbbd08c27 100644 --- a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift +++ b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift @@ -27,9 +27,9 @@ extension AccessorDeclSyntax { leadingTrivia: Trivia? = nil, unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? = nil, - modifier: DeclModifierSyntax? = nil, - unexpectedBetweenModifierAndAccessorKind: UnexpectedNodesSyntax? = nil, + unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax = [], + unexpectedBetweenModifiersAndAccessorKind: UnexpectedNodesSyntax? = nil, accessorKind: TokenSyntax, unexpectedBetweenAccessorKindAndParameter: UnexpectedNodesSyntax? = nil, parameter: AccessorParametersSyntax? = nil, @@ -44,9 +44,9 @@ extension AccessorDeclSyntax { leadingTrivia: leadingTrivia, unexpectedBeforeAttributes, attributes: attributes, - unexpectedBetweenAttributesAndModifier, - modifier: modifier, - unexpectedBetweenModifierAndAccessorKind, + unexpectedBetweenAttributesAndModifiers, + modifiers: modifiers, + unexpectedBetweenModifiersAndAccessorKind, accessorKind: accessorKind, unexpectedBetweenAccessorKindAndParameter, parameter: parameter, diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 44c95f9ed38..9b5576e4aaf 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -3445,6 +3445,24 @@ final class DeclarationTests: ParserTestCase { } func testCoroutineAccessors() { + assertParse( + """ + var i: Int { + yielding borrow { + yield _i + } + yielding mutate { + yield &_i + } + } + """ + ) + } + + func testCoroutineAccessorsLegacyFormat() { + // `read` and `modify` syntax require experimental feature + // flag and always will, since that wasn't the final accepted + // syntax for SE-0474 assertParse( """ var irm: Int { @@ -3513,6 +3531,20 @@ final class DeclarationTests: ParserTestCase { ) } + func testMultipleModifiers() { + assertParse( + """ + public struct S { + var v: Int { + __consuming consuming borrowing mutating nonmutating yielding get { + 0 + } + } + } + """ + ) + } + func testBorrowAndMutateAccessors() { assertParse( """ @@ -3530,8 +3562,7 @@ final class DeclarationTests: ParserTestCase { } } } - """, - experimentalFeatures: .borrowAndMutateAccessors + """ ) }