diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 53f430923fe..1e13bce46d2 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -113,7 +113,9 @@ public let DECL_NODES: [Node] = [ .keyword(.mutableAddressWithOwner), .keyword(.mutableAddressWithNativeOwner), .keyword(._read), + .keyword(.read), .keyword(._modify), + .keyword(.modify), .keyword(.`init`), ]) ), diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index 22d4ee6d59c..35fadbc0f2f 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -18,6 +18,7 @@ public enum ExperimentalFeature: String, CaseIterable { case doExpressions case nonescapableTypes case trailingComma + case coroutineAccessors /// The name of the feature, which is used in the doc comment. public var featureName: String { @@ -32,6 +33,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "NonEscableTypes" case .trailingComma: return "trailing comma" + case .coroutineAccessors: + return "CoroutineAccessors" } } diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 8cfbc5d93cf..b1f35ef6433 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -218,6 +218,7 @@ public enum Keyword: CaseIterable { case macro case message case metadata + case modify case module case mutableAddressWithNativeOwner case mutableAddressWithOwner @@ -245,6 +246,7 @@ public enum Keyword: CaseIterable { case `Protocol` case `protocol` case `public` + case read case reasync case renamed case `repeat` @@ -576,6 +578,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("message") case .metadata: return KeywordSpec("metadata") + case .modify: + return KeywordSpec("modify", experimentalFeature: .coroutineAccessors) case .module: return KeywordSpec("module") case .mutableAddressWithNativeOwner: @@ -628,6 +632,8 @@ public enum Keyword: CaseIterable { return KeywordSpec("protocol", isLexerClassified: true) case .public: return KeywordSpec("public", isLexerClassified: true) + case .read: + return KeywordSpec("read", experimentalFeature: .coroutineAccessors) case .reasync: return KeywordSpec("reasync") case .renamed: diff --git a/Sources/SwiftParser/TokenPrecedence.swift b/Sources/SwiftParser/TokenPrecedence.swift index c179c7e4566..1cc318aedfa 100644 --- a/Sources/SwiftParser/TokenPrecedence.swift +++ b/Sources/SwiftParser/TokenPrecedence.swift @@ -239,7 +239,7 @@ enum TokenPrecedence: Comparable { .dependsOn, .scoped, .sending, // Accessors .get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress, - .mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, ._modify, + .mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, // Misc .import: self = .declKeyword diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index d6ab6357575..63fe9639d8f 100644 --- a/Sources/SwiftParser/generated/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -38,4 +38,7 @@ extension Parser.ExperimentalFeatures { /// Whether to enable the parsing of trailing comma. public static let trailingComma = Self (rawValue: 1 << 4) + + /// Whether to enable the parsing of CoroutineAccessors. + public static let coroutineAccessors = Self (rawValue: 1 << 5) } diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index a0a3f85350a..0ddbdbd54c0 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -32,7 +32,15 @@ extension AccessorDeclSyntax { case mutableAddressWithOwner case mutableAddressWithNativeOwner case _read + #if compiler(>=5.8) + @_spi(ExperimentalLanguageFeatures) + #endif + case read case _modify + #if compiler(>=5.8) + @_spi(ExperimentalLanguageFeatures) + #endif + case modify case `init` init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { @@ -59,8 +67,12 @@ extension AccessorDeclSyntax { self = .mutableAddressWithNativeOwner case TokenSpec(._read): self = ._read + case TokenSpec(.read) where experimentalFeatures.contains(.coroutineAccessors): + self = .read case TokenSpec(._modify): self = ._modify + case TokenSpec(.modify) where experimentalFeatures.contains(.coroutineAccessors): + self = .modify case TokenSpec(.`init`): self = .`init` default: @@ -92,8 +104,12 @@ extension AccessorDeclSyntax { self = .mutableAddressWithNativeOwner case TokenSpec(._read): self = ._read + case TokenSpec(.read): + self = .read case TokenSpec(._modify): self = ._modify + case TokenSpec(.modify): + self = .modify case TokenSpec(.`init`): self = .`init` default: @@ -125,8 +141,12 @@ extension AccessorDeclSyntax { return .keyword(.mutableAddressWithNativeOwner) case ._read: return .keyword(._read) + case .read: + return .keyword(.read) case ._modify: return .keyword(._modify) + case .modify: + return .keyword(.modify) case .`init`: return .keyword(.`init`) } @@ -160,8 +180,12 @@ extension AccessorDeclSyntax { return .keyword(.mutableAddressWithNativeOwner) case ._read: return .keyword(._read) + case .read: + return .keyword(.read) case ._modify: return .keyword(._modify) + case .modify: + return .keyword(.modify) case .`init`: return .keyword(.`init`) } diff --git a/Sources/SwiftSyntax/generated/Keyword.swift b/Sources/SwiftSyntax/generated/Keyword.swift index af85e854e48..2ce15cdf90c 100644 --- a/Sources/SwiftSyntax/generated/Keyword.swift +++ b/Sources/SwiftSyntax/generated/Keyword.swift @@ -161,6 +161,10 @@ public enum Keyword: UInt8, Hashable, Sendable { case macro case message case metadata + #if compiler(>=5.8) + @_spi(ExperimentalLanguageFeatures) + #endif + case modify case module case mutableAddressWithNativeOwner case mutableAddressWithOwner @@ -188,6 +192,10 @@ public enum Keyword: UInt8, Hashable, Sendable { case `Protocol` case `protocol` case `public` + #if compiler(>=5.8) + @_spi(ExperimentalLanguageFeatures) + #endif + case read case reasync case renamed case `repeat` @@ -322,6 +330,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = .objc case "open": self = .open + case "read": + self = .read case "safe": self = .safe case "self": @@ -416,6 +426,8 @@ public enum Keyword: UInt8, Hashable, Sendable { self = .inline case "linear": self = .linear + case "modify": + self = .modify case "module": self = .module case "prefix": @@ -946,6 +958,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "macro", "message", "metadata", + "modify", "module", "mutableAddressWithNativeOwner", "mutableAddressWithOwner", @@ -973,6 +986,7 @@ public enum Keyword: UInt8, Hashable, Sendable { "Protocol", "protocol", "public", + "read", "reasync", "renamed", "repeat", diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index db818f92ff5..a5430c16f4a 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -242,7 +242,9 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { .keyword("mutableAddressWithOwner"), .keyword("mutableAddressWithNativeOwner"), .keyword("_read"), + .keyword("read"), .keyword("_modify"), + .keyword("modify"), .keyword("init") ])) assertNoError(kind, 6, verify(layout[6], as: RawUnexpectedNodesSyntax?.self)) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index d1ba89089a0..f6519df7524 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -251,7 +251,7 @@ public struct AccessorBlockSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNo /// /// - `attributes`: ``AttributeListSyntax`` /// - `modifier`: ``DeclModifierSyntax``? -/// - `accessorSpecifier`: (`get` | `set` | `didSet` | `willSet` | `unsafeAddress` | `addressWithOwner` | `addressWithNativeOwner` | `unsafeMutableAddress` | `mutableAddressWithOwner` | `mutableAddressWithNativeOwner` | `_read` | `_modify` | `init`) +/// - `accessorSpecifier`: (`get` | `set` | `didSet` | `willSet` | `unsafeAddress` | `addressWithOwner` | `addressWithNativeOwner` | `unsafeMutableAddress` | `mutableAddressWithOwner` | `mutableAddressWithNativeOwner` | `_read` | `read` | `_modify` | `modify` | `init`) /// - `parameters`: ``AccessorParametersSyntax``? /// - `effectSpecifiers`: ``AccessorEffectSpecifiersSyntax``? /// - `body`: ``CodeBlockSyntax``? @@ -418,7 +418,9 @@ public struct AccessorDeclSyntax: DeclSyntaxProtocol, SyntaxHashable, _LeafDeclS /// - `mutableAddressWithOwner` /// - `mutableAddressWithNativeOwner` /// - `_read` + /// - `read` /// - `_modify` + /// - `modify` /// - `init` public var accessorSpecifier: TokenSyntax { get { diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index f5c70fe4a3d..345ca2739e9 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -3334,4 +3334,73 @@ final class DeclarationTests: ParserTestCase { ) ) } + + func testCoroutineAccessors() { + assertParse( + """ + var irm: Int { + read { + yield _i + } + modify { + yield &_i + } + } + """, + experimentalFeatures: .coroutineAccessors + ) + assertParse( + """ + public var i: Int { + _read { + yield _i + } + read { + yield _i + } + _modify { + yield &_i + } + modify { + yield &_i + } + } + """, + experimentalFeatures: .coroutineAccessors + ) + assertParse( + """ + var i_rm: Int { + _read { + yield _i + } + 1️⃣modify { + yield &_i + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code in variable" + ) + ] + ) + assertParse( + """ + var ir_m: Int { + _modify { + yield &_i + } + 1️⃣read { + yield _i + } + } + """, + diagnostics: [ + DiagnosticSpec( + message: "unexpected code in variable" + ) + ] + ) + } }