Skip to content

Commit

Permalink
Fix parsing async keywords in void methods (#290)
Browse files Browse the repository at this point in the history
## Overview

Methods returning `Void` implicitly aren’t parsed correctly for
declaration keywords like `throws` and `async` which can lead to
malformed code if the method body contains “async.”

```swift
func notAsync() {
  DispatchQueue.main.async {}
}
```

## Test Plan

Added an additional test case to check for async false positives.
  • Loading branch information
andrewchang-bird committed Jan 29, 2022
1 parent 81067ca commit 6e0d473
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
1 change: 1 addition & 0 deletions Sources/MockingbirdGenerator/Parser/Models/Method.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ struct Method {
// Parse return type attributes.
let returnAttributesStartIndex = parametersEndIndex ?? declaration.startIndex
let returnAttributesEndIndex = declaration.firstIndex(of: "-", excluding: .allGroups)
?? declaration.firstIndex(of: "{", excluding: .allGroups) // Void methods
?? declaration.endIndex
let returnAttributes = declaration[returnAttributesStartIndex..<returnAttributesEndIndex]
if returnAttributes.range(of: #"\basync\b"#, options: .regularExpression) != nil {
Expand Down
27 changes: 27 additions & 0 deletions Sources/MockingbirdTestsHost/AsyncMethods.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,31 @@ protocol AsyncProtocol {
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncClosureThrowingMethod(block: () async throws -> Bool) async throws -> Bool
}

class AsyncClass {
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncMethodVoid() async { fatalError() }

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncMethod() async -> Bool { fatalError() }

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncMethod(parameter: String) async -> Int { fatalError() }

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncThrowingMethod() async throws -> Int { fatalError() }

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncClosureMethod(block: () async -> Bool) async { fatalError() }

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
func asyncClosureThrowingMethod(block: () async throws -> Bool) async throws -> Bool {
fatalError()
}

// Test for false positives.
func notAsync() {
DispatchQueue.main.async {}
}
}
#endif

0 comments on commit 6e0d473

Please sign in to comment.