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

Fix Log.ItemFormat result builders in Swift 5.8 🪵 #263

Merged
merged 1 commit into from
Apr 6, 2023
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
28 changes: 26 additions & 2 deletions Alicerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@
0AE188C122E49DFF00153A36 /* Route+TrieNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE188C022E49DFF00153A36 /* Route+TrieNode.swift */; };
0AE188C522E4D54500153A36 /* Route+TrieRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE188C422E4D54500153A36 /* Route+TrieRouter.swift */; };
0AE330961EBB71F8003E8506 /* Cancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE330951EBB71F8003E8506 /* Cancelable.swift */; };
0AE44DE629DE288D0078EBAE /* ItemFormat+GroupBuilderTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE44DE529DE288D0078EBAE /* ItemFormat+GroupBuilderTestCase.swift */; };
0AE44DE829DE29530078EBAE /* Log+ItemFormat.GroupBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE44DE729DE29530078EBAE /* Log+ItemFormat.GroupBuilder.swift */; };
0AECE67E21776E22003A2509 /* WeakCancelableTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AECE67D21776E22003A2509 /* WeakCancelableTestCase.swift */; };
0AECE6812177741A003A2509 /* MockCancelable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AECE67F217773EA003A2509 /* MockCancelable.swift */; };
0AECE6832177799C003A2509 /* DummyCancelableTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AECE6822177799C003A2509 /* DummyCancelableTestCase.swift */; };
Expand Down Expand Up @@ -601,6 +603,8 @@
0AE188C022E49DFF00153A36 /* Route+TrieNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Route+TrieNode.swift"; sourceTree = "<group>"; };
0AE188C422E4D54500153A36 /* Route+TrieRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Route+TrieRouter.swift"; sourceTree = "<group>"; };
0AE330951EBB71F8003E8506 /* Cancelable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cancelable.swift; sourceTree = "<group>"; };
0AE44DE529DE288D0078EBAE /* ItemFormat+GroupBuilderTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ItemFormat+GroupBuilderTestCase.swift"; sourceTree = "<group>"; };
0AE44DE729DE29530078EBAE /* Log+ItemFormat.GroupBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Log+ItemFormat.GroupBuilder.swift"; sourceTree = "<group>"; };
0AECE67D21776E22003A2509 /* WeakCancelableTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakCancelableTestCase.swift; sourceTree = "<group>"; };
0AECE67F217773EA003A2509 /* MockCancelable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCancelable.swift; sourceTree = "<group>"; };
0AECE6822177799C003A2509 /* DummyCancelableTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyCancelableTestCase.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1292,7 +1296,7 @@
0ABEC1EC284FDB3400043288 /* ItemFormat */ = {
isa = PBXGroup;
children = (
0AA03EAD284698EA009635BD /* Log+ItemFormat.Builder.swift */,
0AE44DE929DE296D0078EBAE /* Builders */,
0AA03EAB284698BA009635BD /* Log+ItemFormat.Formatting.swift */,
0ABEC1EA284EAE6400043288 /* Log+ItemFormat+GenericComponents.swift */,
0ABEC1EE284FDE3900043288 /* Log+ItemFormat+ItemComponents.swift */,
Expand All @@ -1304,7 +1308,7 @@
0ABEC1ED284FDB5400043288 /* ItemFormat */ = {
isa = PBXGroup;
children = (
0A5ECF87283ECBBB0001437D /* ItemFormat+BuilderTestCase.swift */,
0AE44DEA29DE297D0078EBAE /* Builders */,
0A9035D6283E87860041642B /* ItemFormat+FormattingTestCase.swift */,
0ABEC1F0284FE00800043288 /* ItemFormat+GenericComponentsTestCase.swift */,
0ABEC1F2284FE0DD00043288 /* ItemFormat+ItemComponentsTestCase.swift */,
Expand Down Expand Up @@ -1335,6 +1339,24 @@
path = Shared;
sourceTree = "<group>";
};
0AE44DE929DE296D0078EBAE /* Builders */ = {
isa = PBXGroup;
children = (
0AA03EAD284698EA009635BD /* Log+ItemFormat.Builder.swift */,
0AE44DE729DE29530078EBAE /* Log+ItemFormat.GroupBuilder.swift */,
);
path = Builders;
sourceTree = "<group>";
};
0AE44DEA29DE297D0078EBAE /* Builders */ = {
isa = PBXGroup;
children = (
0A5ECF87283ECBBB0001437D /* ItemFormat+BuilderTestCase.swift */,
0AE44DE529DE288D0078EBAE /* ItemFormat+GroupBuilderTestCase.swift */,
);
path = Builders;
sourceTree = "<group>";
};
0AECE67C21776DF9003A2509 /* Shared */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1859,6 +1881,7 @@
0A3236E720D88ED400D225CB /* LoggerTestCase.swift in Sources */,
0A266F9C1ED59FB6009CD0D7 /* FileLogDestinationTestCase.swift in Sources */,
73C6051D20F3BD0E00D0B643 /* TokenTests.swift in Sources */,
0AE44DE629DE288D0078EBAE /* ItemFormat+GroupBuilderTestCase.swift in Sources */,
0AFB4538250FC33C00698CBB /* URLSessionResourceInterceptorTestCase.swift in Sources */,
1B4033621ED8C9D400B4B03D /* MockReusableViewModelView.swift in Sources */,
0A266F9D1ED59FB6009CD0D7 /* JSONLogItemFormatterTestCase.swift in Sources */,
Expand Down Expand Up @@ -1987,6 +2010,7 @@
0A721A5323F0B1FC006A91BD /* URLSessionResourceInterceptor.swift in Sources */,
0A6BD638228876A10063CEAB /* Network+URLSessionError.swift in Sources */,
0A708F6620E97B6E001784DA /* AnyAnalyticsTracker.swift in Sources */,
0AE44DE829DE29530078EBAE /* Log+ItemFormat.GroupBuilder.swift in Sources */,
1B667A0A20127C1600A8CD5A /* StackOrchestrator+Store.swift in Sources */,
0A708F6220E96CD1001784DA /* Analytics.swift in Sources */,
0A9E25BC26ADE3100096D006 /* Routable.swift in Sources */,
Expand Down
54 changes: 54 additions & 0 deletions Sources/Logging/ItemFormat/Builders/Log+ItemFormat.Builder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
extension Log.ItemFormat {

/// A result builder to build string log formatting witnesses.
@resultBuilder
public enum Builder {

public typealias Formatting<Output> = Log.ItemFormat.Formatting<Output>

@inlinable
public static func buildExpression<F: LogItemFormatComponent>(_ formatter: F) -> Formatting<F.Output> {

formatter.formatting
}

@inlinable
public static func buildExpression<O: RangeReplaceableCollection>(_ kp: KeyPath<Log.Item, O>) -> Formatting<O> {

.keyPath(kp)
}

@inlinable
public static func buildExpression<O: RangeReplaceableCollection>(_ value: O) -> Formatting<O> {

.value(value)
}

@inlinable
public static func buildExpression<O>(_ formatting: Formatting<O>) -> Formatting<O> { formatting }

@inlinable
public static func buildBlock<O>(_ formattings: Formatting<O>...) -> Formatting<O> {

formattings.reduce(into: .empty, +=)
}

@inlinable
public static func buildOptional<O>(_ formatting: Formatting<O>?) -> Formatting<O> { formatting ?? .empty }

@inlinable
public static func buildEither<O>(first formatting: Formatting<O>) -> Formatting<O> { formatting }

@inlinable
public static func buildEither<O>(second formatting: Formatting<O>) -> Formatting<O> { formatting }

@inlinable
public static func buildArray<O>(_ formattings: [Formatting<O>]) -> Formatting<O> {

formattings.reduce(into: .empty, +=)
}

@inlinable
public static func buildLimitedAvailability<O>(_ formatting: Formatting<O>) -> Formatting<O> { formatting }
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
extension Log.ItemFormat {

/// A result builder to build string log formatting witnesses.
/// A result builder to build string log formatting witness _groups_, allowing iterating over the group's elements
/// as an array, to provide functionality like adding separators in between elements.
@resultBuilder
public enum Builder {
public enum GroupBuilder {

public typealias Formatting<Output> = Log.ItemFormat.Formatting<Output>

Expand Down Expand Up @@ -30,12 +31,9 @@ extension Log.ItemFormat {
public static func buildExpression<O>(_ formatting: Formatting<O>) -> [Formatting<O>] { [formatting] }

@inlinable
public static func buildExpression<O>(_ formattings: [Formatting<O>]) -> [Formatting<O>] { formattings }
public static func buildBlock<O>(_ formattings: [Formatting<O>]...) -> [Formatting<O>] {

@inlinable
public static func buildBlock<O>(_ formatting: [Formatting<O>]...) -> [Formatting<O>] {

formatting.flatMap { $0 }
formattings.flatMap { $0 }
}

@inlinable
Expand All @@ -55,15 +53,5 @@ extension Log.ItemFormat {

@inlinable
public static func buildLimitedAvailability<O>(_ formatting: [Formatting<O>]) -> [Formatting<O>] { formatting }

// used in Group()
@inlinable
public static func buildFinalResult<O>(_ formattings: [Formatting<O>]) -> [Formatting<O>] { formattings }

@inlinable
public static func buildFinalResult<O>(_ formattings: [Formatting<O>]) -> Formatting<O> {

formattings.reduce(into: .empty, +=)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ extension Log.ItemFormat {
suffix: Output? = nil,
empty: Output,
append: @escaping (inout Output, Output) -> Void,
@Log.ItemFormat.Builder builder: () -> [Formatting<Output>]
@Log.ItemFormat.GroupBuilder builder: () -> [Formatting<Output>]
) {

let prefix = prefix.map { Formatting.value($0, append) } ?? .empty
Expand Down Expand Up @@ -215,7 +215,7 @@ extension Log.ItemFormat.Group where Output == String {
prefix: Output? = nil,
separator: Output? = nil,
suffix: Output? = nil,
@Log.ItemFormat.Builder builder: () -> [Log.ItemFormat.Formatting<Output>]
@Log.ItemFormat.GroupBuilder builder: () -> [Log.ItemFormat.Formatting<Output>]
) {

self.init(prefix: prefix, separator: separator, suffix: suffix, empty: "", append: +=, builder: builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ extension Log.ItemFormat {
/// - separator: The separator string.
/// - builder: The formatting witness group array result builder.
@inlinable
public init(separator: String? = nil, @Log.ItemFormat.Builder builder: () -> [Formatting<String>]) {
public init(separator: String? = nil, @Log.ItemFormat.GroupBuilder builder: () -> [Formatting<String>]) {

let separator = separator.map(Formatting.value) ?? .empty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ class ItemFormat_BuilderTestCase: XCTestCase {
try XCTAssertFormattingBuilder({ .value("💪") }, returns: "💪")
}

func test_buildExpression_WithFormattingArray_ShouldBuildFormatting() throws {

try XCTAssertFormattingBuilder({ [.value("🤜"), .value("🤛")] }, returns: "🤜🤛")
}

// buildOptional

func test_buildOptional_WithTruePredicate_ShouldBuildBody() throws {
Expand Down Expand Up @@ -108,17 +103,6 @@ class ItemFormat_BuilderTestCase: XCTestCase {

// buildFinalResult

func test_buildFinalResult_WithFormattingArray_ShouldBuildFormattingArray() throws {

try XCTAssertFormattingArrayBuilder(
{
Formatting.value("🤜")
Formatting.value("🤛")
},
returns: "🤜🤛"
)
}

func test_buildFinalResult_WithFormatting_ShouldBuildFormatting() throws {

try XCTAssertFormattingBuilder(
Expand Down Expand Up @@ -146,18 +130,4 @@ class ItemFormat_BuilderTestCase: XCTestCase {
try formatting()(item, &string)
XCTAssertEqual(string, expected, file: file, line: line)
}

private func XCTAssertFormattingArrayBuilder(
@Log.ItemFormat.Builder _ formattingArray: () -> [Formatting],
item: Log.Item = .dummy(),
initial: String = "",
returns expected: String,
file: StaticString = #file,
line: UInt = #line
) throws {

var string = initial
try formattingArray().reduce(into: Formatting.empty, +=)(item, &string)
XCTAssertEqual(string, expected, file: file, line: line)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import XCTest
@testable import Alicerce

class ItemFormat_GroupBuilderTestCase: XCTestCase {

typealias Formatting = Log.ItemFormat.Formatting<String>

// buildExpression

func test_buildExpression_WithFormatComponent_ShouldBuildComponentFormatting() throws {

try XCTAssertFormattingBuilder({ Log.ItemFormat.Value("test") }, returns: "test")
}

func test_buildExpression_WithKeyPath_ShouldBuildTextFormatting() throws {

try XCTAssertFormattingBuilder({ \.message }, item: .dummy(message: "✉️"), returns: "✉️")
}

func test_buildExpression_WithString_ShouldBuildValueFormatting() throws {

try XCTAssertFormattingBuilder({ "test" }, returns: "test")
}

func test_buildExpression_WithFormatting_ShouldBuildFormatting() throws {

try XCTAssertFormattingBuilder({ .value("💪") }, returns: "💪")
}

// buildOptional

func test_buildOptional_WithTruePredicate_ShouldBuildBody() throws {

let trueFlag = true

try XCTAssertFormattingBuilder({ if trueFlag { .value("👍") } }, returns: "👍")
}

func test_buildOptional_WithFalsePredicate_ShouldNotBuildBody() throws {

let falseFlag = false
try XCTAssertFormattingBuilder({ if falseFlag { .value("👎") } }, returns: "")
}

// buildEither

func test_buildEither_WithTruePredicate_ShouldBuildFirst() throws {

let flag = true

try XCTAssertFormattingBuilder(
{
if flag { .value("👍") }
else { .value("👎") }
},
returns: "👍"
)
}

func test_buildEither_WithFalsePredicate_ShouldBuildSecond() throws {

let flag = false

try XCTAssertFormattingBuilder(
{
if flag { .value("👍") }
else { .value("👎") }
},
returns: "👎"
)
}

// buildArray

func test_buildArray_ShouldBuildFormatting() throws {

try XCTAssertFormattingBuilder({ for text in ["💃", "🪩", "🕺"] { .value(text) } }, returns: "💃🪩🕺")
}

// buildLimitedAvailability

func test_buildLimitedAvailability_WithTruePredicate_ShouldBuildFirstFormatting() throws {

try XCTAssertFormattingBuilder(
{
if #available(iOS 10, *) { .value("👍") }
else { .value("👎") }
},
returns: "👍"
)
}

func test_buildLimitedAvailability_WithFalsePredicate_ShouldBuildSecondFormatting() throws {

try XCTAssertFormattingBuilder(
{
if #available(iOS 1337, *) { .value("👍") }
else { .value("👎") }
},
returns: "👎"
)
}

// buildFinalResult

func test_buildFinalResult_WithFormatting_ShouldBuildFormatting() throws {

try XCTAssertFormattingBuilder(
{
Formatting.value("🤜")
Formatting.value("🤛")
},
returns: "🤜🤛"
)
}


// MARK: - Helpers

private func XCTAssertFormattingBuilder(
@Log.ItemFormat.GroupBuilder _ formattingArray: () -> [Formatting],
item: Log.Item = .dummy(),
initial: String = "",
returns expected: String,
file: StaticString = #file,
line: UInt = #line
) throws {

var string = initial
try formattingArray().reduce(into: Formatting.empty, +=)(item, &string)
XCTAssertEqual(string, expected, file: file, line: line)
}
}