From 8f04c49e4f4a4dbacd6e4b7f835ef4de914eb334 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 14 Nov 2025 17:14:06 -0800 Subject: [PATCH 01/13] [SE-0474] Support `yielding borrow` and `yielding mutate` accessors `yielding borrow` and `yielding mutate` are the final approved names for the accessors previously known as `read` and `modify` (which are themselves improvements over the earlier non-standard `_read` and `_modify` accessors). Since some people are already using these under the `read` and `modify` names, we want to support the old and new names as synonyms for a transition period until everyone has had a chance to migrate. --- .../Sources/SyntaxSupport/KeywordSpec.swift | 5 +++- Sources/SwiftParser/Declarations.swift | 24 ++++++++++++++++++- Sources/SwiftParser/TokenPrecedence.swift | 2 +- Sources/SwiftSyntax/generated/Keyword.swift | 4 ++++ Tests/SwiftParserTest/DeclarationTests.swift | 6 +++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 2b1809ae634..c1522a51f45 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 { @@ -691,7 +692,9 @@ public enum Keyword: CaseIterable { case .wrt: return KeywordSpec("wrt") case .yield: - return KeywordSpec("yield") + return KeywordSpec("yield") + case .yielding: + return KeywordSpec("yielding") } } } diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index bfe5d3022e1..eaccb8408ec 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1671,9 +1671,14 @@ extension Parser { var look = self.lookahead() let _ = look.consumeAttributeList() let hasModifier = look.consume(ifAnyIn: AccessorModifier.self) != nil + let yielding = look.consume(if: TokenSpec(.yielding)) != nil guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else { return nil } + guard !yielding || [AccessorDeclSyntax.AccessorSpecifierOptions.borrow, .mutate].contains(kind) else { + // `yielding` can only be followed by `borrow` or `mutate` + return nil + } let attrs = self.parseAttributeList() @@ -1692,11 +1697,28 @@ extension Parser { modifier = nil } + if yielding { + _ = self.expect(TokenSpec(.yielding)) + } + let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) + + // Map `yielding borrow` => `read`, etc. + let resolvedKind : AccessorDeclSyntax.AccessorSpecifierOptions + if yielding { + switch kind { + case .borrow: resolvedKind = .read // `yielding borrow` == `read` + case .mutate: resolvedKind = .modify // `yielding mutate` == `modify` + default: resolvedKind = kind + } + } else { + resolvedKind = kind + } + return AccessorIntroducer( attributes: attrs, modifier: modifier, - kind: kind, + kind: resolvedKind, unexpectedBeforeToken: unexpectedBeforeIntroducer, token: introducer ) 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/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 31007c1ade1..73951d95115 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -226,6 +226,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 +591,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = .rethrows case "Sendable": self = .Sendable + case "yielding": + self = .yielding default: return nil } @@ -1053,6 +1056,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "willSet", "wrt", "yield", + "yielding", ] @_spi(RawSyntax) diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index 44c95f9ed38..c4b4144db76 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -3467,12 +3467,18 @@ final class DeclarationTests: ParserTestCase { read { yield _i } + yielding borrow { + yield _i + } _modify { yield &_i } modify { yield &_i } + yielding mutate { + yield &_i + } } """, experimentalFeatures: .coroutineAccessors From db41cc5bfad187f2875b89f2a590fd2d547c0e1f Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 17 Nov 2025 14:14:22 -0800 Subject: [PATCH 02/13] whitespace --- CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift | 4 ++-- Sources/SwiftParser/Declarations.swift | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index c1522a51f45..7212da1ce73 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -692,9 +692,9 @@ public enum Keyword: CaseIterable { case .wrt: return KeywordSpec("wrt") case .yield: - return KeywordSpec("yield") + return KeywordSpec("yield") case .yielding: - return KeywordSpec("yielding") + return KeywordSpec("yielding") } } } diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index eaccb8408ec..7a2f520ae0d 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1704,11 +1704,11 @@ extension Parser { let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) // Map `yielding borrow` => `read`, etc. - let resolvedKind : AccessorDeclSyntax.AccessorSpecifierOptions + let resolvedKind: AccessorDeclSyntax.AccessorSpecifierOptions if yielding { switch kind { - case .borrow: resolvedKind = .read // `yielding borrow` == `read` - case .mutate: resolvedKind = .modify // `yielding mutate` == `modify` + case .borrow: resolvedKind = .read // `yielding borrow` == `read` + case .mutate: resolvedKind = .modify // `yielding mutate` == `modify` default: resolvedKind = kind } } else { From 498f54e9f03b33037809633ac44dcb53d9efa75a Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 05:59:49 -0800 Subject: [PATCH 03/13] Sketch adding a new `yielding` field to AccessorIntroducer to track the presence/absence of the `yielding` token. --- Sources/SwiftParser/Declarations.swift | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 7a2f520ae0d..4861ed970cc 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1659,6 +1659,7 @@ extension Parser { struct AccessorIntroducer { var attributes: RawAttributeListSyntax var modifier: RawDeclModifierSyntax? + var yielding: RawAccessorYieldingModifierSyntax? var kind: AccessorDeclSyntax.AccessorSpecifierOptions var unexpectedBeforeToken: RawUnexpectedNodesSyntax? var token: RawTokenSyntax @@ -1671,7 +1672,7 @@ extension Parser { var look = self.lookahead() let _ = look.consumeAttributeList() let hasModifier = look.consume(ifAnyIn: AccessorModifier.self) != nil - let yielding = look.consume(if: TokenSpec(.yielding)) != nil + let hasYielding = look.consume(if: TokenSpec(.yielding)) != nil guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else { return nil } @@ -1697,27 +1698,24 @@ extension Parser { modifier = nil } - if yielding { - _ = self.expect(TokenSpec(.yielding)) + let yielding: RawAccessorYieldingModifierSyntax? + if hasYielding { + let (unexpectedBeforeYieldingName, yieldingName) = self.expect(TokenSpec(.yielding)) + yielding = RawAccessorYieldingModifierSyntax( + unexpectedBeforeYieldingName, + name: yieldingName, + arena: self.arena + ) + } else { + yielding = nil } let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) - // Map `yielding borrow` => `read`, etc. - let resolvedKind: AccessorDeclSyntax.AccessorSpecifierOptions - if yielding { - switch kind { - case .borrow: resolvedKind = .read // `yielding borrow` == `read` - case .mutate: resolvedKind = .modify // `yielding mutate` == `modify` - default: resolvedKind = kind - } - } else { - resolvedKind = kind - } - return AccessorIntroducer( attributes: attrs, modifier: modifier, + yielding: yielding, kind: resolvedKind, unexpectedBeforeToken: unexpectedBeforeIntroducer, token: introducer From 3254ca1387009bcc8e83fc6532b40facd9d923e4 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 06:00:40 -0800 Subject: [PATCH 04/13] Complete guess how to add a new Node type --- CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 50daee24036..cd47443880e 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -180,6 +180,14 @@ public let DECL_NODES: [Node] = [ ] ), + Node( + kind: .accessorYieldingModifier, + base: .syntax, + nameForDiagnostics: nil, + traits: [], + children: [ ??? ], + ), + Node( kind: .actorDecl, base: .decl, From 07dde5d9584f4c7d7d1b7281ec5b4d2226e8c424 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 06:03:35 -0800 Subject: [PATCH 05/13] Back out old experiment. --- Sources/SwiftParser/Declarations.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 4861ed970cc..51ee8007e00 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1716,7 +1716,7 @@ extension Parser { attributes: attrs, modifier: modifier, yielding: yielding, - kind: resolvedKind, + kind: kind, unexpectedBeforeToken: unexpectedBeforeIntroducer, token: introducer ) From 3303255279e3c8b66ff1c8992b02702c1ce42038 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 06:14:41 -0800 Subject: [PATCH 06/13] Change stuff to make the compiler happy --- CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift | 2 -- CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index cd47443880e..ac6e1758298 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -184,8 +184,6 @@ public let DECL_NODES: [Node] = [ kind: .accessorYieldingModifier, base: .syntax, nameForDiagnostics: nil, - traits: [], - children: [ ??? ], ), Node( diff --git a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift index 70eae620e70..f23b8f2f7ce 100644 --- a/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift +++ b/CodeGeneration/Sources/SyntaxSupport/SyntaxNodeKind.swift @@ -29,6 +29,7 @@ public enum SyntaxNodeKind: String, CaseIterable, IdentifierConvertible, TypeCon case accessorDeclList case accessorEffectSpecifiers case accessorParameters + case accessorYieldingModifier case actorDecl case arrayElement case arrayElementList From c26399cc3f5dbaddeb0471d3ab9d52436702ec3f Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 06:42:55 -0800 Subject: [PATCH 07/13] Make `yielding` a plain decl modifier instead of a new node type --- CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index ac6e1758298..b47a4afd05d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -180,12 +180,6 @@ public let DECL_NODES: [Node] = [ ] ), - Node( - kind: .accessorYieldingModifier, - base: .syntax, - nameForDiagnostics: nil, - ), - Node( kind: .actorDecl, base: .decl, @@ -501,6 +495,7 @@ public let DECL_NODES: [Node] = [ .keyword(.unowned), .keyword(.weak), .keyword(.sending), + .keyword(.yielding), ]) ), Child( From 1281ae4757ded56528a076c0070fd38882384fb5 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 07:15:42 -0800 Subject: [PATCH 08/13] Try making AccessorDecl take a list of modifiers --- .../Sources/SyntaxSupport/DeclNodes.swift | 4 +- .../CollectionNodes+Parsable.swift | 2 +- Sources/SwiftParser/Declarations.swift | 45 +++---------------- Sources/SwiftParser/Lookahead.swift | 9 ++++ .../generated/Parser+TokenSpecSet.swift | 9 ++++ .../generated/ChildNameForDiagnostics.swift | 2 +- .../generated/ChildNameForKeyPath.swift | 12 ++--- .../RenamedChildrenCompatibility.swift | 22 ++++----- .../generated/SyntaxCollections.swift | 1 + .../generated/raw/RawSyntaxNodesAB.swift | 20 ++++----- .../generated/raw/RawSyntaxValidation.swift | 5 ++- .../generated/syntaxNodes/SyntaxNodesAB.swift | 34 +++++++------- .../generated/syntaxNodes/SyntaxNodesD.swift | 4 +- .../generated/BuildableNodes.swift | 12 ++--- .../RenamedChildrenBuilderCompatibility.swift | 12 ++--- 15 files changed, 90 insertions(+), 103 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index b47a4afd05d..5b7ab6ea8f7 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -97,8 +97,8 @@ public let DECL_NODES: [Node] = [ nameForDiagnostics: "attributes" ), Child( - name: "modifier", - kind: .node(kind: .declModifier), + name: "modifiers", + kind: .node(kind: .declModifierList), nameForDiagnostics: "modifiers", isOptional: true ), 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 51ee8007e00..a05cc689108 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1658,8 +1658,7 @@ extension Parser { struct AccessorIntroducer { var attributes: RawAttributeListSyntax - var modifier: RawDeclModifierSyntax? - var yielding: RawAccessorYieldingModifierSyntax? + var modifiers: RawDeclModifierListSyntax var kind: AccessorDeclSyntax.AccessorSpecifierOptions var unexpectedBeforeToken: RawUnexpectedNodesSyntax? var token: RawTokenSyntax @@ -1668,54 +1667,22 @@ extension Parser { mutating func parseAccessorIntroducer( forcedKind: (AccessorDeclSyntax.AccessorSpecifierOptions, TokenConsumptionHandle)? = nil ) -> 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 hasYielding = look.consume(if: TokenSpec(.yielding)) != nil + let _ = look.consume(anySequence: AccessorModifier.self) guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else { return nil } - guard !yielding || [AccessorDeclSyntax.AccessorSpecifierOptions.borrow, .mutate].contains(kind) else { - // `yielding` can only be followed by `borrow` or `mutate` - 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 yielding: RawAccessorYieldingModifierSyntax? - if hasYielding { - let (unexpectedBeforeYieldingName, yieldingName) = self.expect(TokenSpec(.yielding)) - yielding = RawAccessorYieldingModifierSyntax( - unexpectedBeforeYieldingName, - name: yieldingName, - arena: self.arena - ) - } else { - yielding = nil - } + let modifiers = self.parseDeclModifierList() let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) return AccessorIntroducer( attributes: attrs, - modifier: modifier, - yielding: yielding, + modifiers: modifiers, kind: kind, unexpectedBeforeToken: unexpectedBeforeIntroducer, token: introducer @@ -1758,7 +1725,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..4c67070e9c5 100644 --- a/Sources/SwiftParser/Lookahead.swift +++ b/Sources/SwiftParser/Lookahead.swift @@ -160,6 +160,15 @@ extension Parser.Lookahead { } } +// MARK: Skipping a sequence of tokens + +extension Parser.Lookahead { + mutating func consume(anySequence: SpecSet.Type) { + while consume(ifAnyIn: SpecSet.self) != nil { + } + } +} + // MARK: Skipping Tokens extension Parser.Lookahead { diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index 92d9b8d96a4..29471550d45 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -951,6 +951,7 @@ extension DeclModifierSyntax { case unowned case weak case sending + case yielding init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { @@ -1026,6 +1027,8 @@ extension DeclModifierSyntax { self = .weak case TokenSpec(.sending): self = .sending + case TokenSpec(.yielding): + self = .yielding default: return nil } @@ -1105,6 +1108,8 @@ extension DeclModifierSyntax { self = .weak case TokenSpec(.sending): self = .sending + case TokenSpec(.yielding): + self = .yielding default: return nil } @@ -1184,6 +1189,8 @@ extension DeclModifierSyntax { return .keyword(.weak) case .sending: return .keyword(.sending) + case .yielding: + return .keyword(.yielding) } } @@ -1265,6 +1272,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/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/RenamedChildrenCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift index 1d82e4cbad3..08f5d52b9c1 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? = nil, + _ 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/raw/RawSyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesAB.swift index a04d4c66d1a..d01bc125175 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..95443f02643 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..8f6a3ebeb43 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``? @@ -855,9 +855,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS leadingTrivia: Trivia? = nil, _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], - _ unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? = nil, - modifier: DeclModifierSyntax? = nil, - _ unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, + modifiers: DeclModifierListSyntax? = nil, + _ unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, accessorSpecifier: TokenSyntax, _ unexpectedBetweenAccessorSpecifierAndParameters: UnexpectedNodesSyntax? = nil, parameters: AccessorParametersSyntax? = nil, @@ -873,9 +873,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS self = withExtendedLifetime((RawSyntaxArena(), ( unexpectedBeforeAttributes, attributes, - unexpectedBetweenAttributesAndModifier, - modifier, - unexpectedBetweenModifierAndAccessorSpecifier, + unexpectedBetweenAttributesAndModifiers, + modifiers, + unexpectedBetweenModifiersAndAccessorSpecifier, accessorSpecifier, unexpectedBetweenAccessorSpecifierAndParameters, parameters, @@ -888,9 +888,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 +956,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 +965,16 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS } } - public var modifier: DeclModifierSyntax? { + 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? { + public var unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 4)?.cast(UnexpectedNodesSyntax.self) } @@ -1078,9 +1078,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..e79c28b31ea 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? = nil, + 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..3faeff52764 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? = nil, + 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, From 41478f4591794a927db44d16c2b8863eda7c033a Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 09:10:55 -0800 Subject: [PATCH 09/13] Refactor the logic to parse the accessor modifier list --- Sources/SwiftParser/Declarations.swift | 28 +++++++++++++++++--- Sources/SwiftParser/Lookahead.swift | 5 +++- Sources/SwiftParser/TokenSpecSet.swift | 3 +++ Tests/SwiftParserTest/DeclarationTests.swift | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index a05cc689108..5cdf8c3cc9b 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1658,25 +1658,47 @@ extension Parser { struct AccessorIntroducer { var attributes: RawAttributeListSyntax - var modifiers: RawDeclModifierListSyntax + var modifiers: RawDeclModifierListSyntax? var kind: AccessorDeclSyntax.AccessorSpecifierOptions var unexpectedBeforeToken: RawUnexpectedNodesSyntax? var token: RawTokenSyntax } + mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax? { + if count == 0 { return nil } + + var elements = [RawDeclModifierSyntax]() + + for _ in 0.. AccessorIntroducer? { // Look ahead to verify attributes/modifiers/kind var look = self.lookahead() let _ = look.consumeAttributeList() - let _ = look.consume(anySequence: AccessorModifier.self) + let modifierCount = look.consume(anySequence: AccessorModifier.self) guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else { return nil } let attrs = self.parseAttributeList() - let modifiers = self.parseDeclModifierList() + let modifiers = self.parseAccessorModifierList(count: modifierCount) let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec) diff --git a/Sources/SwiftParser/Lookahead.swift b/Sources/SwiftParser/Lookahead.swift index 4c67070e9c5..f40ecd44c7c 100644 --- a/Sources/SwiftParser/Lookahead.swift +++ b/Sources/SwiftParser/Lookahead.swift @@ -163,9 +163,12 @@ extension Parser.Lookahead { // MARK: Skipping a sequence of tokens extension Parser.Lookahead { - mutating func consume(anySequence: SpecSet.Type) { + mutating func consume(anySequence: SpecSet.Type) -> Int { + var count = 0 while consume(ifAnyIn: SpecSet.self) != nil { + count += 1 } + return count } } 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/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index c4b4144db76..fc8136cb441 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -3481,7 +3481,7 @@ final class DeclarationTests: ParserTestCase { } } """, - experimentalFeatures: .coroutineAccessors + experimentalFeatures: [.coroutineAccessors, .borrowAndMutateAccessors] ) assertParse( """ From e513ec50271c96782968e97361ba294803e90264 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 09:19:55 -0800 Subject: [PATCH 10/13] Make `yielding` contingent on CoroutineAccessors feature --- CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift | 2 +- Sources/SwiftParser/generated/Parser+TokenSpecSet.swift | 3 ++- Sources/SwiftSyntax/generated/Keyword.swift | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 7212da1ce73..3596c2e4784 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -694,7 +694,7 @@ public enum Keyword: CaseIterable { case .yield: return KeywordSpec("yield") case .yielding: - return KeywordSpec("yielding") + return KeywordSpec("yielding", experimentalFeature: .coroutineAccessors) } } } diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index 29471550d45..c0e81fc605a 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -951,6 +951,7 @@ extension DeclModifierSyntax { case unowned case weak case sending + @_spi(ExperimentalLanguageFeatures) case yielding init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { @@ -1027,7 +1028,7 @@ extension DeclModifierSyntax { self = .weak case TokenSpec(.sending): self = .sending - case TokenSpec(.yielding): + case TokenSpec(.yielding) where experimentalFeatures.contains(.coroutineAccessors): self = .yielding default: return nil diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index 73951d95115..8fe2f505ec5 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -226,6 +226,7 @@ public enum Keyword: UInt8, Hashable, Sendable { case willSet case wrt case yield + @_spi(ExperimentalLanguageFeatures) case yielding @_spi(RawSyntax) public init?(_ text: SyntaxText) { From 159d886d6f8cb406f5190aa7c123c24bbb898723 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 09:25:49 -0800 Subject: [PATCH 11/13] Whitespace --- Sources/SwiftParser/Declarations.swift | 30 +++++++++++++------------- Sources/SwiftParser/Lookahead.swift | 12 +++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 5cdf8c3cc9b..019b70ecc04 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1665,25 +1665,25 @@ extension Parser { } mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax? { - if count == 0 { return nil } + if count == 0 { return nil } - var elements = [RawDeclModifierSyntax]() + var elements = [RawDeclModifierSyntax]() - for _ in 0..(anySequence: SpecSet.Type) -> Int { - var count = 0 - while consume(ifAnyIn: SpecSet.self) != nil { - count += 1 - } - return count + mutating func consume(anySequence: SpecSet.Type) -> Int { + var count = 0 + while consume(ifAnyIn: SpecSet.self) != nil { + count += 1 } + return count + } } // MARK: Skipping Tokens From 57e865e5a8e935867dcbb3e9b64d4acc73345b54 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 12:15:25 -0800 Subject: [PATCH 12/13] Make the modifier list a collection --- .../Sources/SyntaxSupport/DeclNodes.swift | 5 +-- Sources/SwiftParser/Declarations.swift | 6 +-- .../RenamedChildrenCompatibility.swift | 2 +- .../generated/raw/RawSyntaxNodesAB.swift | 8 ++-- .../generated/raw/RawSyntaxValidation.swift | 2 +- .../generated/syntaxNodes/SyntaxNodesAB.swift | 39 ++++++++++++++++--- .../generated/BuildableNodes.swift | 2 +- .../RenamedChildrenBuilderCompatibility.swift | 2 +- 8 files changed, 46 insertions(+), 20 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 5b7ab6ea8f7..77e4739b9ff 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -98,10 +98,9 @@ public let DECL_NODES: [Node] = [ ), Child( name: "modifiers", - kind: .node(kind: .declModifierList), + 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", kind: .token(choices: [ diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 019b70ecc04..8f4731a7871 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -1658,15 +1658,13 @@ extension Parser { struct AccessorIntroducer { var attributes: RawAttributeListSyntax - var modifiers: RawDeclModifierListSyntax? + var modifiers: RawDeclModifierListSyntax var kind: AccessorDeclSyntax.AccessorSpecifierOptions var unexpectedBeforeToken: RawUnexpectedNodesSyntax? var token: RawTokenSyntax } - mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax? { - if count == 0 { return nil } - + mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax { var elements = [RawDeclModifierSyntax]() for _ in 0.. 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) diff --git a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift index e79c28b31ea..40f7ae1c6d9 100644 --- a/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift +++ b/Sources/SwiftSyntaxBuilder/generated/BuildableNodes.swift @@ -26,7 +26,7 @@ extension AccessorDeclSyntax { unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, - modifiers: DeclModifierListSyntax? = nil, + modifiers: DeclModifierListSyntax = [], unexpectedBetweenModifiersAndAccessorSpecifier: UnexpectedNodesSyntax? = nil, accessorSpecifier: TokenSyntax, unexpectedBetweenAccessorSpecifierAndParameters: UnexpectedNodesSyntax? = nil, diff --git a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift index 3faeff52764..40dbbd08c27 100644 --- a/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift +++ b/Sources/SwiftSyntaxBuilder/generated/RenamedChildrenBuilderCompatibility.swift @@ -28,7 +28,7 @@ extension AccessorDeclSyntax { unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], unexpectedBetweenAttributesAndModifiers: UnexpectedNodesSyntax? = nil, - modifiers: DeclModifierListSyntax? = nil, + modifiers: DeclModifierListSyntax = [], unexpectedBetweenModifiersAndAccessorKind: UnexpectedNodesSyntax? = nil, accessorKind: TokenSyntax, unexpectedBetweenAccessorKindAndParameter: UnexpectedNodesSyntax? = nil, From 83de7dc4d47f6c25e46eef0321c3f57e6854151b Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 18 Nov 2025 12:35:59 -0800 Subject: [PATCH 13/13] Whitespace --- CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 77e4739b9ff..064dfd0fb3d 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -100,7 +100,8 @@ public let DECL_NODES: [Node] = [ name: "modifiers", kind: .collection(kind: .declModifierList, collectionElementName: "Modifier", defaultsToEmpty: true), nameForDiagnostics: "modifiers", - documentation: "Modifiers like `mutating` or `yielding` that affect the accessor declaration." ), + documentation: "Modifiers like `mutating` or `yielding` that affect the accessor declaration." + ), Child( name: "accessorSpecifier", kind: .token(choices: [