diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 6cd0a74cb34..87f12d1907e 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -17,11 +17,11 @@ extension DeclarationModifier { switch self { case .__consuming, .__setter_access, ._const, ._local, .async, .borrowing, .class, .consuming, .convenience, .distributed, .dynamic, - .final, .indirect, .infix, .isolated, .lazy, .mutating, .nonisolated, - .nonmutating, .optional, .override, .postfix, .prefix, .reasync, - .required, .rethrows, .static, .weak: + .final, .indirect, .infix, .isolated, .lazy, .mutating, .nonmutating, + .optional, .override, .postfix, .prefix, .reasync, .required, + .rethrows, .static, .weak: return false - case .fileprivate, .internal, .package, .open, .private, + case .fileprivate, .internal, .nonisolated, .package, .open, .private, .public, .unowned: return true } diff --git a/Sources/SwiftParser/Modifiers.swift b/Sources/SwiftParser/Modifiers.swift index a28e44c2343..39588f47b95 100644 --- a/Sources/SwiftParser/Modifiers.swift +++ b/Sources/SwiftParser/Modifiers.swift @@ -60,6 +60,8 @@ extension Parser { } case (.declarationModifier(.unowned), let handle)?: elements.append(self.parseUnownedModifier(handle)) + case (.declarationModifier(.nonisolated), let handle)?: + elements.append(parseNonisolatedModifier(handle)) case (.declarationModifier(.final), let handle)?, (.declarationModifier(.required), let handle)?, (.declarationModifier(.optional), let handle)?, @@ -79,7 +81,6 @@ extension Parser { (.declarationModifier(.indirect), let handle)?, (.declarationModifier(.isolated), let handle)?, (.declarationModifier(.async), let handle)?, - (.declarationModifier(.nonisolated), let handle)?, (.declarationModifier(.distributed), let handle)?, (.declarationModifier(._const), let handle)?, (.declarationModifier(._local), let handle)?, @@ -98,9 +99,9 @@ extension Parser { } extension Parser { - mutating func parseModifierDetail() -> RawDeclModifierDetailSyntax { + mutating func parseModifierDetail(_ keyword: Keyword) -> RawDeclModifierDetailSyntax { let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen) - let (unexpectedBeforeDetailToken, detailToken) = self.expect(.identifier, TokenSpec(.set, remapping: .identifier), default: .identifier) + let (unexpectedBeforeDetailToken, detailToken) = self.expect(.identifier, TokenSpec(keyword, remapping: .identifier), default: .identifier) let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen) return RawDeclModifierDetailSyntax( unexpectedBeforeLeftParen, @@ -118,7 +119,7 @@ extension Parser { let detail: RawDeclModifierDetailSyntax? if self.at(.leftParen) { - detail = self.parseModifierDetail() + detail = self.parseModifierDetail(.set) } else { detail = nil } @@ -217,4 +218,22 @@ extension Parser { arena: self.arena ) } + + mutating func parseNonisolatedModifier(_ handle: RecoveryConsumptionHandle) -> RawDeclModifierSyntax { + let (unexpectedBeforeKeyword, keyword) = self.eat(handle) + + let detail: RawDeclModifierDetailSyntax? + if self.at(.leftParen) { + detail = self.parseModifierDetail(.unsafe) + } else { + detail = nil + } + + return RawDeclModifierSyntax( + unexpectedBeforeKeyword, + name: keyword, + detail: detail, + arena: self.arena + ) + } } diff --git a/Tests/SwiftParserTest/DeclarationTests.swift b/Tests/SwiftParserTest/DeclarationTests.swift index ee24ab0d121..511b980c50a 100644 --- a/Tests/SwiftParserTest/DeclarationTests.swift +++ b/Tests/SwiftParserTest/DeclarationTests.swift @@ -240,6 +240,19 @@ final class DeclarationTests: ParserTestCase { ) } + func testNonisolatedUnsafeParsing() { + assertParse( + """ + nonisolated(unsafe) let a = 0 + + struct A { + nonisolated(unsafe) let b = 0 + nonisolated(unsafe) var c: Int { 0 } + } + """ + ) + } + func testProtocolParsing() { assertParse("protocol Foo {}")