Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.0 required] Replace #fileID, #filePath, #line, and #column with a single macro. #304

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 14 additions & 14 deletions Sources/Testing/Expectations/Expectation+Macro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@freestanding(expression) public macro expect(
_ condition: Bool,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation()
sourceLocation: SourceLocation = #here
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")

/// Check that an expectation has passed after a condition has been evaluated
Expand All @@ -44,7 +44,7 @@
@freestanding(expression) public macro require(
_ condition: Bool,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation()
sourceLocation: SourceLocation = #here
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")

// MARK: - Optional checking
Expand All @@ -68,7 +68,7 @@
@freestanding(expression) public macro require<T>(
_ optionalValue: T?,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation()
sourceLocation: SourceLocation = #here
) -> T = #externalMacro(module: "TestingMacros", type: "RequireMacro")

/// Unwrap an optional boolean value or, if it is `nil`, fail and throw an
Expand Down Expand Up @@ -98,7 +98,7 @@
public macro require(
_ optionalValue: Bool?,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation()
sourceLocation: SourceLocation = #here
) -> Bool = #externalMacro(module: "TestingMacros", type: "AmbiguousRequireMacro")

// MARK: - Matching errors by type
Expand Down Expand Up @@ -136,7 +136,7 @@ public macro require(
@freestanding(expression) public macro expect<E, R>(
throws errorType: E.Type,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro") where E: Error

Expand Down Expand Up @@ -175,7 +175,7 @@ public macro require(
@freestanding(expression) public macro expect<R>(
throws _: Never.Type,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")

Expand Down Expand Up @@ -217,7 +217,7 @@ public macro require(
@freestanding(expression) public macro require<E, R>(
throws errorType: E.Type,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "RequireMacro") where E: Error

Expand All @@ -236,7 +236,7 @@ public macro require(
@freestanding(expression) public macro require<R>(
throws _: Never.Type,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")

Expand Down Expand Up @@ -272,7 +272,7 @@ public macro require(
@freestanding(expression) public macro expect<E, R>(
throws error: E,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro") where E: Error & Equatable

Expand Down Expand Up @@ -309,7 +309,7 @@ public macro require(
@freestanding(expression) public macro require<E, R>(
throws error: E,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R
) = #externalMacro(module: "TestingMacros", type: "RequireMacro") where E: Error & Equatable

Expand Down Expand Up @@ -352,7 +352,7 @@ public macro require(
/// ``expect(throws:_:sourceLocation:performing:)-5lzjz`` instead.
@freestanding(expression) public macro expect<R>(
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R,
throws errorMatcher: (any Error) async throws -> Bool
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")
Expand Down Expand Up @@ -400,7 +400,7 @@ public macro require(
/// this macro. The test will then fail if an error is thrown.
@freestanding(expression) public macro require<R>(
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: () async throws -> R,
throws errorMatcher: (any Error) async throws -> Bool
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")
Expand Down Expand Up @@ -474,7 +474,7 @@ public macro require(
@freestanding(expression) public macro expect(
exitsWith expectedExitCondition: ExitCondition,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: @convention(thin) () async throws -> Void
) = #externalMacro(module: "TestingMacros", type: "ExitTestExpectMacro")

Expand Down Expand Up @@ -549,6 +549,6 @@ public macro require(
@freestanding(expression) public macro require(
exitsWith expectedExitCondition: ExitCondition,
_ comment: @autoclosure () -> Comment? = nil,
sourceLocation: SourceLocation = SourceLocation(),
sourceLocation: SourceLocation = #here,
performing expression: @convention(thin) () async -> Void
) = #externalMacro(module: "TestingMacros", type: "ExitTestRequireMacro")
7 changes: 2 additions & 5 deletions Sources/Testing/Issues/Confirmation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,7 @@ extension Confirmation {
public func confirmation<R>(
_ comment: Comment? = nil,
expectedCount: Int = 1,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column,
sourceLocation: SourceLocation = #here,
_ body: (Confirmation) async throws -> R
) async rethrows -> R {
let confirmation = Confirmation()
Expand All @@ -106,7 +103,7 @@ public func confirmation<R>(
.confirmationMiscounted(actual: actualCount, expected: expectedCount),
comments: Array(comment),
backtrace: .current(),
sourceLocation: SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
sourceLocation: sourceLocation
)
}
}
Expand Down
12 changes: 2 additions & 10 deletions Sources/Testing/Issues/Issue+Recording.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,8 @@ extension Issue {
/// or ``require(_:_:sourceLocation:)-5l63q`` macros.)
@discardableResult public static func record(
_ comment: Comment? = nil,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column
sourceLocation: SourceLocation = #here
) -> Self {
let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
let sourceContext = SourceContext(backtrace: .current(), sourceLocation: sourceLocation)
let issue = Issue(kind: .unconditional, comments: Array(comment), sourceContext: sourceContext)
return issue.record()
Expand All @@ -137,12 +133,8 @@ extension Issue {
@discardableResult public static func record(
_ error: any Error,
_ comment: Comment? = nil,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column
sourceLocation: SourceLocation = #here
) -> Self {
let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
let backtrace = Backtrace(forFirstThrowOf: error) ?? Backtrace.current()
let sourceContext = SourceContext(backtrace: backtrace, sourceLocation: sourceLocation)
let issue = Issue(kind: .errorCaught(error), comments: Array(comment), sourceContext: sourceContext)
Expand Down
16 changes: 8 additions & 8 deletions Sources/Testing/Issues/Issue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public struct Issue: Sendable {
/// Kinds of issues which may be recorded.
public enum Kind: Sendable {
/// An issue which occurred unconditionally, for example by using
/// ``Issue/record(_:fileID:filePath:line:column:)``.
/// ``Issue/record(_:sourceLocation:)``.
case unconditional

/// An issue due to a failed expectation, such as those produced by
Expand All @@ -33,9 +33,9 @@ public struct Issue: Sendable {
/// ``Confirmation/confirm(count:)`` should have been called.
///
/// This issue can occur when calling
/// ``confirmation(_:expectedCount:fileID:filePath:line:column:_:)`` when
/// the confirmation passed to these functions' `body` closures is confirmed
/// too few or too many times.
/// ``confirmation(_:expectedCount:sourceLocation:_:)`` when the
/// confirmation passed to these functions' `body` closures is confirmed too
/// few or too many times.
indirect case confirmationMiscounted(actual: Int, expected: Int)

/// An issue due to an `Error` being thrown by a test function and caught by
Expand Down Expand Up @@ -235,7 +235,7 @@ extension Issue.Kind {
@_spi(ForToolsIntegrationOnly)
public enum Snapshot: Sendable, Codable {
/// An issue which occurred unconditionally, for example by using
/// ``Issue/record(_:fileID:filePath:line:column:)``.
/// ``Issue/record(_:sourceLocation:)``.
case unconditional

/// An issue due to a failed expectation, such as those produced by
Expand All @@ -255,9 +255,9 @@ extension Issue.Kind {
/// ``Confirmation/confirm(count:)`` should have been called.
///
/// This issue can occur when calling
/// ``confirmation(_:expectedCount:fileID:filePath:line:column:_:)`` when
/// the confirmation passed to these functions' `body` closures is confirmed
/// too few or too many times.
/// ``confirmation(_:expectedCount:sourceLocation:_:)`` when the
/// confirmation passed to these functions' `body` closures is confirmed too
/// few or too many times.
indirect case confirmationMiscounted(actual: Int, expected: Int)

/// An issue due to an `Error` being thrown by a test function and caught by
Expand Down
34 changes: 10 additions & 24 deletions Sources/Testing/Issues/KnownIssue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,15 @@ public typealias KnownIssueMatcher = @Sendable (_ issue: Issue) -> Bool
/// Because all errors thrown by `body` are caught as known issues, this
/// function is not throwing. If only some errors or issues are known to occur
/// while others should continue to cause test failures, use
/// ``withKnownIssue(_:isIntermittent:fileID:filePath:line:column:_:when:matching:)-68e5g``
/// ``withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)-5vi5n``
/// instead.
public func withKnownIssue(
_ comment: Comment? = nil,
isIntermittent: Bool = false,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column,
sourceLocation: SourceLocation = #here,
_ body: () throws -> Void
) {
try? withKnownIssue(comment, isIntermittent: isIntermittent, fileID: fileID, filePath: filePath, line: line, column: column, body, matching: { _ in true })
try? withKnownIssue(comment, isIntermittent: isIntermittent, sourceLocation: sourceLocation, body, matching: { _ in true })
}

/// Invoke a function that has a known issue that is expected to occur during
Expand Down Expand Up @@ -164,17 +161,14 @@ public func withKnownIssue(
///
/// It is not necessary to specify both `precondition` and `issueMatcher` if
/// only one is relevant. If all errors and issues should be considered known
/// issues, use ``withKnownIssue(_:isIntermittent:fileID:filePath:line:column:_:)-5pxnd``
/// issues, use ``withKnownIssue(_:isIntermittent:sourceLocation:_:)-95r6o``
/// instead.
///
/// - Note: `issueMatcher` may be invoked more than once for the same issue.
public func withKnownIssue(
_ comment: Comment? = nil,
isIntermittent: Bool = false,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column,
sourceLocation: SourceLocation = #here,
_ body: () throws -> Void,
when precondition: () -> Bool = { true },
matching issueMatcher: @escaping KnownIssueMatcher = { _ in true }
Expand All @@ -183,7 +177,6 @@ public func withKnownIssue(
return try body()
}
let matchCounter = Locked(rawValue: 0)
let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
let issueMatcher = _combineIssueMatcher(issueMatcher, matchesCountedBy: matchCounter)
defer {
if !isIntermittent {
Expand Down Expand Up @@ -225,18 +218,15 @@ public func withKnownIssue(
/// Because all errors thrown by `body` are caught as known issues, this
/// function is not throwing. If only some errors or issues are known to occur
/// while others should continue to cause test failures, use
/// ``withKnownIssue(_:isIntermittent:fileID:filePath:line:column:_:when:matching:)-7azqg``
/// ``withKnownIssue(_:isIntermittent:sourceLocation:_:when:matching:)-47y3z``
/// instead.
public func withKnownIssue(
_ comment: Comment? = nil,
isIntermittent: Bool = false,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column,
sourceLocation: SourceLocation = #here,
_ body: () async throws -> Void
) async {
try? await withKnownIssue(comment, isIntermittent: isIntermittent, fileID: fileID, filePath: filePath, line: line, column: column, body, matching: { _ in true })
try? await withKnownIssue(comment, isIntermittent: isIntermittent, sourceLocation: sourceLocation, body, matching: { _ in true })
}

/// Invoke a function that has a known issue that is expected to occur during
Expand Down Expand Up @@ -279,17 +269,14 @@ public func withKnownIssue(
///
/// It is not necessary to specify both `precondition` and `issueMatcher` if
/// only one is relevant. If all errors and issues should be considered known
/// issues, use ``withKnownIssue(_:isIntermittent:fileID:filePath:line:column:_:)-30kgk``
/// issues, use ``withKnownIssue(_:isIntermittent:sourceLocation:_:)-3g6b7``
/// instead.
///
/// - Note: `issueMatcher` may be invoked more than once for the same issue.
public func withKnownIssue(
_ comment: Comment? = nil,
isIntermittent: Bool = false,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column,
sourceLocation: SourceLocation = #here,
_ body: () async throws -> Void,
when precondition: () async -> Bool = { true },
matching issueMatcher: @escaping KnownIssueMatcher = { _ in true }
Expand All @@ -298,7 +285,6 @@ public func withKnownIssue(
return try await body()
}
let matchCounter = Locked(rawValue: 0)
let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
let issueMatcher = _combineIssueMatcher(issueMatcher, matchesCountedBy: matchCounter)
defer {
if !isIntermittent {
Expand Down
37 changes: 37 additions & 0 deletions Sources/Testing/SourceAttribution/SourceLocation+Macro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
//

#if compiler(>=5.11)
/// Get the current source location as a compile-time constant.
///
/// - Returns: The source location at which this macro is applied.
///
/// This macro can be used in place of `#fileID`, `#line`, and `#column` as a
/// default argument to a function. It expands to an instance of
/// ``SourceLocation`` referring to the location of the macro invocation itself
/// (similar to how `#fileID` expands to the ID of the file containing the
/// `#fileID` invocation.)
@freestanding(expression) public macro here() -> SourceLocation = #externalMacro(module: "TestingMacros", type: "SourceLocationMacro")

extension SourceLocation {
/// Get the current source location as an instance of ``SourceLocation``.
///
/// - Warning: This function is used to implement the `#here` macro. Do not
/// call it directly.
public static func __here(
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column
) -> Self {
Self(fileID: fileID, filePath: filePath, line: line, column: column)
}
}
#endif
7 changes: 1 addition & 6 deletions Sources/Testing/SourceAttribution/SourceLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,7 @@ public struct SourceLocation: Sendable {
}
}

public init(
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column
) {
public init(fileID: String, filePath: String, line: Int, column: Int) {
self.fileID = fileID
self._filePath = filePath
self.line = line
Expand Down
6 changes: 3 additions & 3 deletions Sources/Testing/Testing.docc/EnablingAndDisabling.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ automatically skip them if conditions like these are not met.
### Disable a test

If you need to disable a test unconditionally, use the
``Trait/disabled(_:fileID:filePath:line:column:)`` function. Given the following
test function:
``Trait/disabled(_:sourceLocation:)`` function. Given the following test
function:

```swift
@Test("Food truck sells burritos")
Expand Down Expand Up @@ -62,7 +62,7 @@ func isCold() async throws { ... }

If it's currently winter, then presumably ice cream won't be available for
sale and this test will fail. It therefore makes sense to only enable it if it's currently summer. You can conditionally enable a test with
``Trait/enabled(if:_:fileID:filePath:line:column:)``:
``Trait/enabled(if:_:sourceLocation:)``:

```swift
@Test("Ice cream is cold", .enabled(if: Season.current == .summer))
Expand Down