-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ff4ba14
commit f10598e
Showing
2 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
135 changes: 135 additions & 0 deletions
135
Sources/SwiftDocC/Utility/FoundationExtensions/NoOpSignposterShim.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/* | ||
This source file is part of the Swift.org open source project | ||
|
||
Copyright (c) 2024 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 | ||
*/ | ||
|
||
/// A shim for `OSSignposter` that does nothing, except for running the passed interval task. | ||
/// | ||
/// This type allows calling code to avoid using `#if canImport(os)` throughout the implementation. | ||
package struct NoOpSignposterShim : @unchecked Sendable { | ||
package init() {} | ||
|
||
package var isEnabled: Bool { false } | ||
|
||
package struct ID { | ||
static var exclusive = ID() | ||
} | ||
package func makeSignpostID() -> ID { ID() } | ||
|
||
package struct IntervalState {} | ||
|
||
// Without messages | ||
|
||
package func beginInterval(_ name: StaticString, id: ID = .exclusive) -> IntervalState { | ||
IntervalState() | ||
} | ||
package func endInterval(_ name: StaticString, _ state: IntervalState) {} | ||
|
||
package func withIntervalSignpost<T>(_ name: StaticString, id: ID = .exclusive, around task: () throws -> T) rethrows -> T { | ||
try task() | ||
} | ||
|
||
package func emitEvent(_ name: StaticString, id: ID = .exclusive) {} | ||
|
||
// With messages | ||
|
||
package func beginInterval(_ name: StaticString, id: ID = .exclusive, _ message: NoOpLogMessage) -> IntervalState { | ||
self.beginInterval(name, id: id) | ||
} | ||
package func endInterval(_ name: StaticString, _ state: IntervalState, _ message: NoOpLogMessage) {} | ||
|
||
package func withIntervalSignpost<T>(_ name: StaticString, id: ID = .exclusive, _ message: NoOpLogMessage, around task: () throws -> T) rethrows -> T { | ||
try self.withIntervalSignpost(name, id: id, around: task) | ||
} | ||
|
||
package func emitEvent(_ name: StaticString, id: ID = .exclusive, _ message: NoOpLogMessage) {} | ||
} | ||
|
||
// MARK: Message | ||
|
||
package struct NoOpLogMessage: ExpressibleByStringInterpolation, ExpressibleByStringLiteral { | ||
package let interpolation: Interpolation | ||
|
||
package init(stringInterpolation: Interpolation) { | ||
interpolation = stringInterpolation | ||
} | ||
package init(stringLiteral value: String) { | ||
self.init(stringInterpolation: .init(literalCapacity: 0, interpolationCount: 0)) | ||
} | ||
|
||
package struct Interpolation: StringInterpolationProtocol { | ||
package init(literalCapacity: Int, interpolationCount: Int) {} | ||
|
||
package mutating func appendLiteral(_ literal: String) {} | ||
|
||
// Append string | ||
package mutating func appendInterpolation(_ argumentString: @autoclosure @escaping () -> String, align: NoOpLogStringAlignment = .none, privacy: NoOpLogPrivacy = .auto) {} | ||
package mutating func appendInterpolation(_ value: @autoclosure @escaping () -> some CustomStringConvertible, align: NoOpLogStringAlignment = .none, privacy: NoOpLogPrivacy = .auto) {} | ||
|
||
// Append booleans | ||
package mutating func appendInterpolation(_ boolean: @autoclosure @escaping () -> Bool, format: NoOpLogBoolFormat = .truth, privacy: NoOpLogPrivacy = .auto) {} | ||
|
||
// Append integers | ||
package mutating func appendInterpolation(_ number: @autoclosure @escaping () -> some FixedWidthInteger, format: NoOpLogIntegerFormatting = .decimal, align: NoOpLogStringAlignment = .none, privacy: NoOpLogPrivacy = .auto) {} | ||
|
||
// Append float/double | ||
package mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Float, format: NoOpLogFloatFormatting = .fixed, align: NoOpLogStringAlignment = .none, privacy: NoOpLogPrivacy = .auto) {} | ||
package mutating func appendInterpolation(_ number: @autoclosure @escaping () -> Double, format: NoOpLogFloatFormatting = .fixed, align: NoOpLogStringAlignment = .none, privacy: NoOpLogPrivacy = .auto) {} | ||
|
||
// Add more interpolations here as needed | ||
} | ||
|
||
package struct NoOpLogStringAlignment { | ||
package static var none: Self { .init() } | ||
package static func right(columns: @autoclosure @escaping () -> Int) -> Self { .init() } | ||
package static func left(columns: @autoclosure @escaping () -> Int) -> Self { .init() } | ||
} | ||
|
||
package struct NoOpLogPrivacy { | ||
package enum Mask { | ||
case hash, none | ||
} | ||
package static var `public`: Self { .init() } | ||
package static var `private`: Self { .init() } | ||
package static var sensitive: Self { .init() } | ||
package static var auto: Self { .init() } | ||
package static func `private`(mask: Mask) -> Self { .init() } | ||
package static func sensitive(mask: Mask) -> Self { .init() } | ||
package static func auto(mask: Mask) -> Self { .init() } | ||
} | ||
|
||
package enum NoOpLogBoolFormat { | ||
case truth, answer | ||
} | ||
|
||
public struct NoOpLogIntegerFormatting { | ||
package static var decimal: Self { .init() } | ||
package static var hex: Self { .init() } | ||
package static var octal: Self { .init() } | ||
package static func decimal(explicitPositiveSign: Bool = false) -> Self { .init() } | ||
package static func decimal(explicitPositiveSign: Bool = false, minDigits: @autoclosure @escaping () -> Int) -> Self { .init() } | ||
package static func hex(explicitPositiveSign: Bool = false, includePrefix: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func hex(explicitPositiveSign: Bool = false, includePrefix: Bool = false, uppercase: Bool = false, minDigits: @autoclosure @escaping () -> Int) -> Self { .init() } | ||
package static func octal(explicitPositiveSign: Bool = false, includePrefix: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func octal(explicitPositiveSign: Bool = false, includePrefix: Bool = false, uppercase: Bool = false, minDigits: @autoclosure @escaping () -> Int) -> Self { .init() } | ||
} | ||
|
||
package struct NoOpLogFloatFormatting { | ||
package static var fixed: Self { .init() } | ||
package static var hex: Self { .init() } | ||
package static var exponential: Self { .init() } | ||
package static var hybrid: Self { .init() } | ||
package static func fixed(precision: @autoclosure @escaping () -> Int, explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func fixed(explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func hex(explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func exponential(precision: @autoclosure @escaping () -> Int, explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func exponential(explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func hybrid(precision: @autoclosure @escaping () -> Int, explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
package static func hybrid(explicitPositiveSign: Bool = false, uppercase: Bool = false) -> Self { .init() } | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
Tests/SwiftDocCTests/Utility/NoOpSignposterShimTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
This source file is part of the Swift.org open source project | ||
|
||
Copyright (c) 2024 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 | ||
*/ | ||
|
||
import Foundation | ||
import SwiftDocC | ||
import XCTest | ||
|
||
final class NoOpSignposterShimTests: XCTestCase { | ||
func testRunsIntervalVoidWork() { | ||
let signposter = NoOpSignposterShim() | ||
|
||
let didPerformWork = expectation(description: "Did perform work") | ||
signposter.withIntervalSignpost("Something") { | ||
didPerformWork.fulfill() | ||
} | ||
|
||
wait(for: [didPerformWork], timeout: 10.0) | ||
} | ||
|
||
func testReturnsIntervalWorkResult() { | ||
let signposter = NoOpSignposterShim() | ||
|
||
let didPerformWork = expectation(description: "Did perform work") | ||
let number = signposter.withIntervalSignpost("Something") { | ||
didPerformWork.fulfill() | ||
return 7 | ||
} | ||
XCTAssertEqual(number, 7) | ||
|
||
wait(for: [didPerformWork], timeout: 10.0) | ||
} | ||
|
||
func testCanAcceptMessageInputs() { | ||
let signposter = NoOpSignposterShim() | ||
|
||
let handle = signposter.beginInterval("Some interval", "Some message") | ||
signposter.endInterval("Some interval", handle, "Another message") | ||
|
||
signposter.emitEvent("Some event", id: signposter.makeSignpostID(), "Some static string") | ||
signposter.emitEvent("Some event", "Some formatted bool \(true, format: .answer)") | ||
signposter.emitEvent("Some event", "Some formatted integer \(12, format: .decimal)") | ||
signposter.emitEvent("Some event", "Some formatted float \(7.0, format: .exponential)") | ||
signposter.emitEvent("Some event", "Some sensitive string \("my secret", privacy: .sensitive(mask: .hash))") | ||
signposter.emitEvent("Some event", "Some non-secret string \("my secret", privacy: .public)") | ||
|
||
signposter.emitEvent("Some event", "Some aligned values \(12, align: .right(columns: 5)) \("some text", align: .left(columns: 10))") | ||
} | ||
} |