Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public struct EffectSpecifiers: Hashable, Equatable, CustomStringConvertible {
/// Indicates whether the function can throw an error.
public let throwsSpecifier: String?

/// The identifier type within a `throws` keyword, if any.
/// Indicates the specific error type the `throws` will produce. i.e `throws(SpecificErrorType)`
public let throwsIdentifier: String?

/// The `asyncSpecifier` specifier, if any.
/// Indicates whether the function supports structured concurrency.
public let asyncSpecifier: String?
Expand All @@ -41,20 +45,23 @@ public struct EffectSpecifiers: Hashable, Equatable, CustomStringConvertible {
public init(node: AccessorEffectSpecifiersSyntax) {
self.node = node
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
asyncSpecifier = node.asyncSpecifier?.text.trimmed
}

/// Creates a new ``SyntaxSparrow/EffectSpecifiers`` instance from an `TypeEffectSpecifiersSyntax` node.
public init(node: TypeEffectSpecifiersSyntax) {
self.node = node
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
asyncSpecifier = node.asyncSpecifier?.text.trimmed
}

/// Creates a new ``SyntaxSparrow/EffectSpecifiers`` instance from an `FunctionEffectSpecifiersSyntax` node.
public init(node: FunctionEffectSpecifiersSyntax) {
self.node = node
throwsSpecifier = node.throwsClause?.throwsSpecifier.text.trimmed
throwsIdentifier = node.throwsClause?.type?.as(IdentifierTypeSyntax.self)?.name.text.trimmed
asyncSpecifier = node.asyncSpecifier?.text.trimmed
}

Expand Down
10 changes: 10 additions & 0 deletions Sources/SyntaxSparrow/Public/Semantics/Declarations/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ public struct Function: Declaration, SyntaxChildCollecting {
return signature.effectSpecifiers?.throwsSpecifier != nil
}

/// Returns the specific error type that is declared within the ``Function/Signature/effectSpecifiers`` when using the `throw` keyword.
///
/// For example, the following would return `"SpecificErrorType"`:
/// ```swift
/// func example() throws(SpecificErrorType)
/// ```
public var throwsIdentifier: String? {
return signature.effectSpecifiers?.throwsIdentifier
}

/// Returns `true` when the ``Function/Signature/effectSpecifiers`` has the `throw` keyword.
///
/// For example, the following would return `true`:
Expand Down
24 changes: 19 additions & 5 deletions Tests/SyntaxSparrowTests/Declarations/FunctionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,41 @@ final class FunctionTests: XCTestCase {
let source = #"""
func executeOrder66() {}
func executeOrder66() throws {}
func executeOrder66() throws(SpecificErrorType) {}
func executeOrder66() async {}
func executeOrder66() async throws {}
func executeOrder66() async throws(SpecificErrorType) {}
"""#
instanceUnderTest.updateToSource(source)
XCTAssertTrue(instanceUnderTest.isStale)
instanceUnderTest.collectChildren()
XCTAssertFalse(instanceUnderTest.isStale)
XCTAssertEqual(instanceUnderTest.functions.count, 4)
XCTAssertEqual(instanceUnderTest.functions.count, 6)

// None
XCTAssertFalse(instanceUnderTest.functions[0].isThrowing)
XCTAssertFalse(instanceUnderTest.functions[0].isAsync)
XCTAssertNil(instanceUnderTest.functions[0].throwsIdentifier)
// Throwing only
XCTAssertTrue(instanceUnderTest.functions[1].isThrowing)
XCTAssertFalse(instanceUnderTest.functions[1].isAsync)
XCTAssertNil(instanceUnderTest.functions[1].throwsIdentifier)
// Throwing only - specific error
XCTAssertTrue(instanceUnderTest.functions[2].isThrowing)
XCTAssertEqual(instanceUnderTest.functions[2].throwsIdentifier, "SpecificErrorType")
XCTAssertFalse(instanceUnderTest.functions[2].isAsync)
// Async only
XCTAssertFalse(instanceUnderTest.functions[2].isThrowing)
XCTAssertTrue(instanceUnderTest.functions[2].isAsync)
// Both
XCTAssertTrue(instanceUnderTest.functions[3].isThrowing)
XCTAssertFalse(instanceUnderTest.functions[3].isThrowing)
XCTAssertTrue(instanceUnderTest.functions[3].isAsync)
XCTAssertNil(instanceUnderTest.functions[3].throwsIdentifier)
// Both
XCTAssertTrue(instanceUnderTest.functions[4].isThrowing)
XCTAssertTrue(instanceUnderTest.functions[4].isAsync)
XCTAssertNil(instanceUnderTest.functions[4].throwsIdentifier)
// Both - Specific Error
XCTAssertTrue(instanceUnderTest.functions[5].isThrowing)
XCTAssertTrue(instanceUnderTest.functions[5].isAsync)
XCTAssertEqual(instanceUnderTest.functions[5].throwsIdentifier, "SpecificErrorType")
}

func test_function_withChildDeclarations_willResolveExpectedChildDeclarations() throws {
Expand Down
Loading