Skip to content

Commit 9dc2916

Browse files
mobrien-ghostMichael O’Brien
andauthored
[CHORE] Add support for throws clauese identifier type (#68)
Co-authored-by: Michael O’Brien <obrien.michael1@police.qld.gov.au>
1 parent 2e290f9 commit 9dc2916

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

Sources/SyntaxSparrow/Public/Semantics/Components/EffectsSpecifiers.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public struct EffectSpecifiers: Hashable, Equatable, CustomStringConvertible {
3131
/// Indicates whether the function can throw an error.
3232
public let throwsSpecifier: String?
3333

34+
/// The identifier type within a `throws` keyword, if any.
35+
/// Indicates the specific error type the `throws` will produce. i.e `throws(SpecificErrorType)`
36+
public let throwsIdentifier: String?
37+
3438
/// The `asyncSpecifier` specifier, if any.
3539
/// Indicates whether the function supports structured concurrency.
3640
public let asyncSpecifier: String?
@@ -41,20 +45,23 @@ public struct EffectSpecifiers: Hashable, Equatable, CustomStringConvertible {
4145
public init(node: AccessorEffectSpecifiersSyntax) {
4246
self.node = node
4347
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
48+
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
4449
asyncSpecifier = node.asyncSpecifier?.text.trimmed
4550
}
4651

4752
/// Creates a new ``SyntaxSparrow/EffectSpecifiers`` instance from an `TypeEffectSpecifiersSyntax` node.
4853
public init(node: TypeEffectSpecifiersSyntax) {
4954
self.node = node
5055
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
56+
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
5157
asyncSpecifier = node.asyncSpecifier?.text.trimmed
5258
}
5359

5460
/// Creates a new ``SyntaxSparrow/EffectSpecifiers`` instance from an `FunctionEffectSpecifiersSyntax` node.
5561
public init(node: FunctionEffectSpecifiersSyntax) {
5662
self.node = node
5763
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
64+
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
5865
asyncSpecifier = node.asyncSpecifier?.text.trimmed
5966
}
6067

Sources/SyntaxSparrow/Public/Semantics/Declarations/Function.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,16 @@ public struct Function: Declaration, SyntaxChildCollecting {
199199
return signature.effectSpecifiers?.throwsSpecifier != nil
200200
}
201201

202+
/// Returns the specific error type that is declared within the ``Function/Signature/effectSpecifiers`` when using the `throw` keyword.
203+
///
204+
/// For example, the following would return `"SpecificErrorType"`:
205+
/// ```swift
206+
/// func example() throws(SpecificErrorType)
207+
/// ```
208+
public var throwsIdentifier: String? {
209+
return signature.effectSpecifiers?.throwsIdentifier
210+
}
211+
202212
/// Returns `true` when the ``Function/Signature/effectSpecifiers`` has the `throw` keyword.
203213
///
204214
/// For example, the following would return `true`:

Tests/SyntaxSparrowTests/Declarations/FunctionTests.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,41 @@ final class FunctionTests: XCTestCase {
6161
let source = #"""
6262
func executeOrder66() {}
6363
func executeOrder66() throws {}
64+
func executeOrder66() throws(SpecificErrorType) {}
6465
func executeOrder66() async {}
6566
func executeOrder66() async throws {}
67+
func executeOrder66() async throws(SpecificErrorType) {}
6668
"""#
6769
instanceUnderTest.updateToSource(source)
6870
XCTAssertTrue(instanceUnderTest.isStale)
6971
instanceUnderTest.collectChildren()
7072
XCTAssertFalse(instanceUnderTest.isStale)
71-
XCTAssertEqual(instanceUnderTest.functions.count, 4)
73+
XCTAssertEqual(instanceUnderTest.functions.count, 6)
7274

7375
// None
7476
XCTAssertFalse(instanceUnderTest.functions[0].isThrowing)
7577
XCTAssertFalse(instanceUnderTest.functions[0].isAsync)
78+
XCTAssertNil(instanceUnderTest.functions[0].throwsIdentifier)
7679
// Throwing only
7780
XCTAssertTrue(instanceUnderTest.functions[1].isThrowing)
7881
XCTAssertFalse(instanceUnderTest.functions[1].isAsync)
82+
XCTAssertNil(instanceUnderTest.functions[1].throwsIdentifier)
83+
// Throwing only - specific error
84+
XCTAssertTrue(instanceUnderTest.functions[2].isThrowing)
85+
XCTAssertEqual(instanceUnderTest.functions[2].throwsIdentifier, "SpecificErrorType")
86+
XCTAssertFalse(instanceUnderTest.functions[2].isAsync)
7987
// Async only
80-
XCTAssertFalse(instanceUnderTest.functions[2].isThrowing)
81-
XCTAssertTrue(instanceUnderTest.functions[2].isAsync)
82-
// Both
83-
XCTAssertTrue(instanceUnderTest.functions[3].isThrowing)
88+
XCTAssertFalse(instanceUnderTest.functions[3].isThrowing)
8489
XCTAssertTrue(instanceUnderTest.functions[3].isAsync)
90+
XCTAssertNil(instanceUnderTest.functions[3].throwsIdentifier)
91+
// Both
92+
XCTAssertTrue(instanceUnderTest.functions[4].isThrowing)
93+
XCTAssertTrue(instanceUnderTest.functions[4].isAsync)
94+
XCTAssertNil(instanceUnderTest.functions[4].throwsIdentifier)
95+
// Both - Specific Error
96+
XCTAssertTrue(instanceUnderTest.functions[5].isThrowing)
97+
XCTAssertTrue(instanceUnderTest.functions[5].isAsync)
98+
XCTAssertEqual(instanceUnderTest.functions[5].throwsIdentifier, "SpecificErrorType")
8599
}
86100

87101
func test_function_withChildDeclarations_willResolveExpectedChildDeclarations() throws {

0 commit comments

Comments
 (0)