diff --git a/CHANGELOG.md b/CHANGELOG.md index f5d1506bc..9493c2859 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ ### Bug Fixes +* Retain `async` initializers in actors in `async_without_await` rule. + [SimplyDanny](https://github.com/SimplyDanny) + [#6423](https://github.com/realm/SwiftLint/issues/6423) + * Ignore `override` functions in `async_without_await` rule. [SimplyDanny](https://github.com/SimplyDanny) [#6416](https://github.com/realm/SwiftLint/issues/6416) diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRule.swift index b1be636fc..fd1ade585 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRule.swift @@ -23,6 +23,7 @@ private extension AsyncWithoutAwaitRule { final class Visitor: ViolationsSyntaxVisitor { private var functionScopes = Stack() + private var actorTypeStack = Stack() private var pendingAsync: TokenSyntax? override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { @@ -72,7 +73,9 @@ private extension AsyncWithoutAwaitRule { override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { if node.body != nil { - let asyncToken = node.needsToKeepAsync ? nil : node.signature.effectSpecifiers?.asyncSpecifier + let asyncToken = node.needsToKeepAsync || actorTypeStack.peek() == true + ? nil + : node.signature.effectSpecifiers?.asyncSpecifier functionScopes.push(.init(asyncToken: asyncToken)) } return .visitChildren @@ -113,6 +116,42 @@ private extension AsyncWithoutAwaitRule { } } + override func visit(_: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + actorTypeStack.push(true) + return .visitChildren + } + + override func visitPost(_: ActorDeclSyntax) { + actorTypeStack.pop() + } + + override func visit(_: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + actorTypeStack.push(false) + return .visitChildren + } + + override func visitPost(_: ClassDeclSyntax) { + actorTypeStack.pop() + } + + override func visit(_: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + actorTypeStack.push(false) + return .visitChildren + } + + override func visitPost(_: EnumDeclSyntax) { + actorTypeStack.pop() + } + + override func visit(_: StructDeclSyntax) -> SyntaxVisitorContinueKind { + actorTypeStack.push(false) + return .visitChildren + } + + override func visitPost(_: StructDeclSyntax) { + actorTypeStack.pop() + } + override func visit(_: FunctionParameterSyntax) -> SyntaxVisitorContinueKind { .skipChildren } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRuleExamples.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRuleExamples.swift index f1bdd3244..6a141ae58 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRuleExamples.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/AsyncWithoutAwaitRuleExamples.swift @@ -1,5 +1,13 @@ internal struct AsyncWithoutAwaitRuleExamples { static let nonTriggeringExamples = [ + Example(""" + actor A { + init() async { + foo() + } + func foo() {} + } + """), Example(""" func test() { func test() async {