field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

commit 47617a25ad1c38c3e05c3fe7d2680f6c0713559f
parent 31105959da51edd4261b13a55bba5ff320a3e414
Author: triesap <tyson@radroots.org>
Date:   Wed,  9 Sep 2026 06:44:52 +0000

runtime: close task installation cancellation race

- Cancel operations installed after timeout or cancellation wins.
- Preserve completed results and existing abandoned-result cleanup.
- Extract the actual wrapper and cover all six installation orderings.
- Verify the reproduced regression, full native suite and narrower lint debt.

Diffstat:
MPackage.swift | 1+
MTera.xcodeproj/project.pbxproj | 4++++
ATera/Runtime/TeraRuntimeBoundedTask.swift | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTera/Runtime/TeraRuntimeClient.swift | 150-------------------------------------------------------------------------------
ATeraTests/TeraRuntimeBoundedTaskTests.swift | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mproject.yml | 1+
Mrelease/provenance.json | 2+-
Mtest-fixtures/swiftlint-maintainability-baseline.v1.json | 4++--
8 files changed, 305 insertions(+), 153 deletions(-)

diff --git a/Package.swift b/Package.swift @@ -58,6 +58,7 @@ let package = Package( "Runtime/TeraErrorRecovery.swift", "Runtime/TeraGeneratedRuntimeBackend.swift", "Runtime/TeraLifecycleCoordinator.swift", + "Runtime/TeraRuntimeBoundedTask.swift", "Runtime/TeraRuntimeClient.swift", "Runtime/TeraRuntimeModels.swift", "Runtime/TeraSessionGeneration.swift", diff --git a/Tera.xcodeproj/project.pbxproj b/Tera.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1D45B3D566A0A60063190854 /* TeraApp in Frameworks */ = {isa = PBXBuildFile; productRef = E666175A800272732A27CBEB /* TeraApp */; }; + 229C9AC991E67663DA53D339 /* TeraRuntimeBoundedTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */; }; 2479571FA99A7962794999C4 /* TeraSupportingStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0636AEDEB50DDDD328374A9 /* TeraSupportingStoreTests.swift */; }; 2C6DDB502DFA11C2CBCA49C4 /* TeraApp in Frameworks */ = {isa = PBXBuildFile; productRef = A1979630FE6BC343F0E59F24 /* TeraApp */; }; 38EF7FA8874E82B28110A232 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6967B3EAC4CF1A410B26DD1A /* PrivacyInfo.xcprivacy */; }; @@ -54,6 +55,7 @@ /* Begin PBXFileReference section */ 0CDE3D76E1EDF909C19D0506 /* TeraUITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = TeraUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 27D9D40699A01FFB02F30B11 /* local-social-personas.v1.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "local-social-personas.v1.json"; sourceTree = "<group>"; }; + 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraRuntimeBoundedTaskTests.swift; sourceTree = "<group>"; }; 2A506546B0EC1792240C36F7 /* TeraClockTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraClockTests.swift; sourceTree = "<group>"; }; 32CBDAE974FB8D7408108E69 /* TeraRemoteQualificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraRemoteQualificationUITests.swift; sourceTree = "<group>"; }; 3B808E67E85CD36E49C38B6F /* TeraCalendarFFICompatibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraCalendarFFICompatibilityTests.swift; sourceTree = "<group>"; }; @@ -150,6 +152,7 @@ 61B6F0B16BFD8F046E9C163F /* TeraMediaStoreTests.swift */, E351F52E77C74A4E99095E45 /* TeraRemoteQualificationTests.swift */, 6B8677670E203FF68EC88983 /* TeraRootShellTests.swift */, + 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */, 88ED360C84532DA7088BFC6E /* TeraRuntimeClientFixtures.swift */, FB77C087F15C2F42CD959607 /* TeraRuntimeClientTests.swift */, 7C0836F5D5F71F9A54795C57 /* TeraSessionGenerationTests.swift */, @@ -372,6 +375,7 @@ CDBE38E6B521611436F28858 /* TeraMediaStoreTests.swift in Sources */, 81AF9DDA0E64DC4EEFCEF25D /* TeraRemoteQualificationTests.swift in Sources */, 9AD968F0B37C64B5AF8D9A68 /* TeraRootShellTests.swift in Sources */, + 229C9AC991E67663DA53D339 /* TeraRuntimeBoundedTaskTests.swift in Sources */, C219B5F4E24188E1116BF45B /* TeraRuntimeClientFixtures.swift in Sources */, 912C8743116D929BB6A02778 /* TeraRuntimeClientTests.swift in Sources */, 79D06C6BF2B55C0C4104FB91 /* TeraSessionGenerationTests.swift in Sources */, diff --git a/Tera/Runtime/TeraRuntimeBoundedTask.swift b/Tera/Runtime/TeraRuntimeBoundedTask.swift @@ -0,0 +1,160 @@ +import Foundation + +enum TeraRuntimeBoundedOutcome<Value: Sendable>: Sendable { + case completed(Result<Value, TeraRuntimeFailure>) + case timedOut + case cancelled +} + +/// The wrapper has one immutable state owner; every mutable field is protected +/// by its lock. Task cancellation and continuation resumption occur outside it. +final class TeraRuntimeBoundedTask<Value: Sendable>: @unchecked Sendable { + typealias Outcome = TeraRuntimeBoundedOutcome<Value> + + final class State: @unchecked Sendable { + private let lock = NSLock() + private var outcome: Outcome? + private var continuations: [UUID: CheckedContinuation<Outcome, Never>] = [:] + private var cancelledWaiters: Set<UUID> = [] + private var operationTask: Task<Void, Never>? + private var timeoutTask: Task<Void, Never>? + + func install(operationTask: Task<Void, Never>, timeoutTask: Task<Void, Never>) { + let terminal = lock.withLock { () -> Outcome? in + if let outcome { + return outcome + } + self.operationTask = operationTask + self.timeoutTask = timeoutTask + return nil + } + guard let terminal else { return } + timeoutTask.cancel() + switch terminal { + case .cancelled, .timedOut: + operationTask.cancel() + case .completed: + break + } + } + + func value(cancelsOperationWhenWaiterCancelled: Bool) async -> Outcome { + let waiterID = UUID() + return await withTaskCancellationHandler { + await withCheckedContinuation { requestedContinuation in + let immediate = lock.withLock { () -> Outcome? in + if let outcome { + return outcome + } + if cancelledWaiters.remove(waiterID) != nil { + return .cancelled + } + continuations[waiterID] = requestedContinuation + return nil + } + if let immediate { + requestedContinuation.resume(returning: immediate) + } + } + } onCancel: { + if cancelsOperationWhenWaiterCancelled { + cancel() + } else { + cancelWaiter(waiterID) + } + } + } + + func cancel() { + guard resolve(.cancelled) else { return } + let tasks = lock.withLock { (operationTask, timeoutTask) } + tasks.0?.cancel() + tasks.1?.cancel() + } + + func expire() { + guard resolve(.timedOut) else { return } + let taskToCancel: Task<Void, Never>? = lock.withLock { self.operationTask } + taskToCancel?.cancel() + } + + func finishOperation() { + lock.withLock { operationTask = nil } + } + + private func cancelWaiter(_ waiterID: UUID) { + let continuation = lock.withLock { () -> CheckedContinuation<Outcome, Never>? in + guard outcome == nil else { return nil } + guard let continuation = continuations.removeValue(forKey: waiterID) else { + cancelledWaiters.insert(waiterID) + return nil + } + return continuation + } + continuation?.resume(returning: .cancelled) + } + + @discardableResult + func resolve(_ requestedOutcome: Outcome) -> Bool { + var pendingContinuations: [CheckedContinuation<Outcome, Never>] = [] + var timeoutToCancel: Task<Void, Never>? + let accepted = lock.withLock { () -> Bool in + guard outcome == nil else { return false } + outcome = requestedOutcome + pendingContinuations = Array(continuations.values) + continuations.removeAll(keepingCapacity: false) + cancelledWaiters.removeAll(keepingCapacity: false) + timeoutToCancel = timeoutTask + return true + } + if accepted { + timeoutToCancel?.cancel() + for continuation in pendingContinuations { + continuation.resume(returning: requestedOutcome) + } + } + return accepted + } + } + + private let state: State + + init( + deadlineNanoseconds: UInt64, + operation: @escaping @Sendable () async -> Result<Value, TeraRuntimeFailure>, + onAbandonedResult: + @escaping @Sendable ( + Result<Value, TeraRuntimeFailure> + ) async -> Void = { _ in } + ) { + let state = State() + self.state = state + let operationTask = Task { [state] in + let result = await operation() + if !state.resolve(.completed(result)) { + await onAbandonedResult(result) + } + state.finishOperation() + } + + let timeoutTask = Task { [state] in + do { + try await Task.sleep(nanoseconds: deadlineNanoseconds) + } catch { + return + } + state.expire() + } + state.install(operationTask: operationTask, timeoutTask: timeoutTask) + } + + func value(cancelsOperationWhenWaiterCancelled: Bool = true) async -> Outcome { + await state.value( + cancelsOperationWhenWaiterCancelled: cancelsOperationWhenWaiterCancelled + ) + } + + func cancel() { + state.cancel() + } +} diff --git a/Tera/Runtime/TeraRuntimeClient.swift b/Tera/Runtime/TeraRuntimeClient.swift @@ -288,156 +288,6 @@ typealias TeraRuntimeBackendFactory = TeraRuntimeLaunchConfiguration ) async throws -> TeraRuntimeBackendStart -private enum TeraRuntimeBoundedOutcome<Value: Sendable>: Sendable { - case completed(Result<Value, TeraRuntimeFailure>) - case timedOut - case cancelled -} - -private final class TeraRuntimeBoundedTask<Value: Sendable>: @unchecked Sendable { - typealias Outcome = TeraRuntimeBoundedOutcome<Value> - - private final class State: @unchecked Sendable { - private let lock = NSLock() - private var outcome: Outcome? - private var continuations: [UUID: CheckedContinuation<Outcome, Never>] = [:] - private var cancelledWaiters: Set<UUID> = [] - private var operationTask: Task<Void, Never>? - private var timeoutTask: Task<Void, Never>? - - func install(operationTask: Task<Void, Never>, timeoutTask: Task<Void, Never>) { - let shouldCancel = lock.withLock { () -> Bool in - guard outcome == nil else { return true } - self.operationTask = operationTask - self.timeoutTask = timeoutTask - return false - } - if shouldCancel { - timeoutTask.cancel() - } - } - - func value(cancelsOperationWhenWaiterCancelled: Bool) async -> Outcome { - let waiterID = UUID() - return await withTaskCancellationHandler { - await withCheckedContinuation { requestedContinuation in - let immediate = lock.withLock { () -> Outcome? in - if let outcome { - return outcome - } - if cancelledWaiters.remove(waiterID) != nil { - return .cancelled - } - continuations[waiterID] = requestedContinuation - return nil - } - if let immediate { - requestedContinuation.resume(returning: immediate) - } - } - } onCancel: { - if cancelsOperationWhenWaiterCancelled { - cancel() - } else { - cancelWaiter(waiterID) - } - } - } - - func cancel() { - guard resolve(.cancelled) else { return } - let tasks = lock.withLock { (operationTask, timeoutTask) } - tasks.0?.cancel() - tasks.1?.cancel() - } - - func expire() { - guard resolve(.timedOut) else { return } - let taskToCancel: Task<Void, Never>? = lock.withLock { self.operationTask } - taskToCancel?.cancel() - } - - func finishOperation() { - lock.withLock { operationTask = nil } - } - - private func cancelWaiter(_ waiterID: UUID) { - let continuation = lock.withLock { () -> CheckedContinuation<Outcome, Never>? in - guard outcome == nil else { return nil } - guard let continuation = continuations.removeValue(forKey: waiterID) else { - cancelledWaiters.insert(waiterID) - return nil - } - return continuation - } - continuation?.resume(returning: .cancelled) - } - - @discardableResult - func resolve(_ requestedOutcome: Outcome) -> Bool { - var pendingContinuations: [CheckedContinuation<Outcome, Never>] = [] - var timeoutToCancel: Task<Void, Never>? - let accepted = lock.withLock { () -> Bool in - guard outcome == nil else { return false } - outcome = requestedOutcome - pendingContinuations = Array(continuations.values) - continuations.removeAll(keepingCapacity: false) - cancelledWaiters.removeAll(keepingCapacity: false) - timeoutToCancel = timeoutTask - return true - } - if accepted { - timeoutToCancel?.cancel() - for continuation in pendingContinuations { - continuation.resume(returning: requestedOutcome) - } - } - return accepted - } - } - - private let state: State - - init( - deadlineNanoseconds: UInt64, - operation: @escaping @Sendable () async -> Result<Value, TeraRuntimeFailure>, - onAbandonedResult: - @escaping @Sendable ( - Result<Value, TeraRuntimeFailure> - ) async -> Void = { _ in } - ) { - let state = State() - self.state = state - let operationTask = Task { [state] in - let result = await operation() - if !state.resolve(.completed(result)) { - await onAbandonedResult(result) - } - state.finishOperation() - } - - let timeoutTask = Task { [state] in - do { - try await Task.sleep(nanoseconds: deadlineNanoseconds) - } catch { - return - } - state.expire() - } - state.install(operationTask: operationTask, timeoutTask: timeoutTask) - } - - func value(cancelsOperationWhenWaiterCancelled: Bool = true) async -> Outcome { - await state.value( - cancelsOperationWhenWaiterCancelled: cancelsOperationWhenWaiterCancelled - ) - } - - func cancel() { - state.cancel() - } -} - actor TeraRuntimeClient { private struct StartupOperation: Sendable { let identity: TeraRuntimeOperationIdentity diff --git a/TeraTests/TeraRuntimeBoundedTaskTests.swift b/TeraTests/TeraRuntimeBoundedTaskTests.swift @@ -0,0 +1,136 @@ +import Foundation +@testable import TeraApp +import XCTest + +final class TeraRuntimeBoundedTaskTests: XCTestCase { + private typealias Bounded = TeraRuntimeBoundedTask<Int> + + func testCompletionTimeoutAndCancellationBeforeInstallation() async { + for terminal in Terminal.allCases { + await assertInstallation(terminal: terminal, terminalFirst: true) + } + } + + func testCompletionTimeoutAndCancellationAfterInstallation() async { + for terminal in Terminal.allCases { + await assertInstallation(terminal: terminal, terminalFirst: false) + } + } + + func testCompletedFailureDoesNotCancelLateInstalledOperation() async { + let state = Bounded.State() + let gate = BoundedTestGate() + let operation = Task { await gate.wait() } + let timer = Task { await gate.wait() } + let failure = TeraRuntimeFailure.local(operation: "test", code: "test.failure", safeMessage: "Test failure") + XCTAssertTrue(state.resolve(.completed(.failure(failure)))) + state.install(operationTask: operation, timeoutTask: timer) + XCTAssertFalse(operation.isCancelled) + XCTAssertTrue(timer.isCancelled) + if case let .completed(.failure(observed)) = await state.value(cancelsOperationWhenWaiterCancelled: true) { + XCTAssertEqual(observed, failure) + } else { + XCTFail("The first completed result must remain owned by its caller") + } + await gate.open() + await operation.value + await timer.value + } + + func testAbandonedSuccessfulOperationStillRunsItsCleanupExactlyOnce() async { + let started = BoundedTestGate() + let release = BoundedTestGate() + let abandoned = expectation(description: "Abandoned result cleanup") + abandoned.assertForOverFulfill = true + let task = Bounded(deadlineNanoseconds: .max) { + await started.open() + await release.wait() + return .success(42) + } onAbandonedResult: { result in + XCTAssertEqual(try? result.get(), 42) + abandoned.fulfill() + } + await started.wait() + task.cancel() + task.cancel() + if case .cancelled = await task.value() {} else { + XCTFail("Cancellation must resolve the caller before the operation returns") + } + await release.open() + await fulfillment(of: [abandoned], timeout: 2) + } + + func testSuccessfulWrapperKeepsItsResultAfterLaterCancellation() async { + let task = Bounded(deadlineNanoseconds: .max, operation: { .success(42) }) { _ in + XCTFail("A result owned by its caller must not be abandoned") + } + await assertOutcome(task.value(), terminal: .completion) + task.cancel() + await assertOutcome(task.value(), terminal: .completion) + } + + private func assertInstallation(terminal: Terminal, terminalFirst: Bool) async { + let state = Bounded.State() + let gate = BoundedTestGate() + let operation = Task { await gate.wait() } + let timer = Task { await gate.wait() } + if terminalFirst { + terminal.resolve(state) + } + state.install(operationTask: operation, timeoutTask: timer) + if !terminalFirst { + terminal.resolve(state) + } + XCTAssertEqual(operation.isCancelled, terminal != .completion, "\(terminal), before=\(terminalFirst)") + XCTAssertTrue(timer.isCancelled) + await assertOutcome(state.value(cancelsOperationWhenWaiterCancelled: true), terminal: terminal) + XCTAssertFalse(state.resolve(.completed(.success(99)))) + state.cancel() + state.expire() + await assertOutcome(state.value(cancelsOperationWhenWaiterCancelled: true), terminal: terminal) + await gate.open() + await operation.value + await timer.value + state.finishOperation() + } + + private func assertOutcome(_ outcome: Bounded.Outcome, terminal: Terminal) { + switch (terminal, outcome) { + case let (.completion, .completed(.success(value))): XCTAssertEqual(value, 42) + case (.timeout, .timedOut), (.cancellation, .cancelled): break + default: XCTFail("The first terminal outcome must resolve each wait exactly once") + } + } + + private enum Terminal: CaseIterable { + case completion, timeout, cancellation + + func resolve(_ state: Bounded.State) { + switch self { + case .completion: XCTAssertTrue(state.resolve(.completed(.success(42)))) + case .timeout: state.expire() + case .cancellation: state.cancel() + } + } + } +} + +private actor BoundedTestGate { + private var opened = false + private var waiters: [CheckedContinuation<Void, Never>] = [] + + func wait() async { + guard !opened else { return } + await withCheckedContinuation { waiters.append($0) } + } + + func open() { + guard !opened else { return } + opened = true + let pending = waiters + waiters.removeAll() + for waiter in pending { + waiter.resume() + } + } +} diff --git a/project.yml b/project.yml @@ -49,6 +49,7 @@ targets: - path: TeraTests/TeraRuntimeClientFixtures.swift - path: TeraTests/TeraSessionGenerationTests.swift - path: TeraTests/TeraErrorRecoveryTests.swift + - path: TeraTests/TeraRuntimeBoundedTaskTests.swift - path: TeraTests/TeraRootShellTests.swift - path: TeraTests/TeraStateMigrationTests.swift - path: TeraTests/TeraTodayStoreTests.swift diff --git a/release/provenance.json b/release/provenance.json @@ -6,7 +6,7 @@ "info_plist_sha256": "15ef08b1cdd1096cfb9eeaf5be5bf8f814807a7ca9350bbbb47860fa72ec13ef", "privacy_manifest_sha256": "a331d51864743ebe4e00dd22360b4a538b6b3ac26a6b3eb54094e60a36959a12", "sbom_sha256": "6b5ce897d5273290febc8b831663e12dea759cb0084f182ba7949e1c593fc410", - "xcode_project_sha256": "6ff877e0e0a57a08b15c9fa9857e952fd1f1bb566fe3b79b9a4078b8dcb6c80d" + "xcode_project_sha256": "4d8248344c4728688df5b51fc9127b08a50aab252b177956ea76a8ab31ecfb31" }, "disposition": "unsigned", "platforms": [ diff --git a/test-fixtures/swiftlint-maintainability-baseline.v1.json b/test-fixtures/swiftlint-maintainability-baseline.v1.json @@ -1 +1 @@ -[{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/App\/TeraAppModel.swift","character":7,"line":55},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 255 lines"},"text":"final class TeraAppModel: ObservableObject {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/App\/TeraAppModel.swift","character":3,"line":71},"severity":"warning","reason":"Initializer body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines"},"text":" init("},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":1,"line":73},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 427 lines"},"text":"actor TeraAddMediaCoordinator: TeraAddMediaHandling {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":3,"line":192},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 55 lines"},"text":" func uploadInBackground("},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":1,"line":580},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 580"},"text":"#endif"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","character":15,"line":134},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 545 lines"},"text":"private final class TeraGeneratedRuntimeBackend: TeraRuntimeBackend, @unchecked Sendable {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","character":1,"line":1696},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1696"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraLifecycleCoordinator.swift","character":1,"line":434},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 434"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":1,"line":441},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 847 lines"},"text":"actor TeraRuntimeClient {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":11,"line":503},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines"},"text":" private func start("},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":3,"line":881},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 88 lines"},"text":" func changes(bufferCapacity: Int = 16) async throws -> AsyncStream<TeraRuntimeChange> {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":11,"line":1061},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" private func beginShutdown() -> ShutdownOperation {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":1,"line":1371},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1371"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraRuntimeModels.swift","character":1,"line":1234},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1234"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":7,"line":11},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 741 lines"},"text":"final class TeraAddStore: ObservableObject {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":3,"line":280},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" func submit() async {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":3,"line":438},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 51 lines"},"text":" func retract(_ card: TeraTodayCard) async {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":11,"line":524},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines"},"text":" private func uploadPendingMedia(_ initial: TeraDraftStatus) async throws"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraAddStore.swift","character":1,"line":810},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 810"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":1,"line":78},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 468 lines"},"text":"actor TeraConfigurationStore {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":5,"line":148},"severity":"error","reason":"Function body should span 100 lines or less excluding comments and whitespace: currently spans 109 lines"},"text":" func load() throws -> TeraAppConfiguration {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":1,"line":759},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 759"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":1,"line":40},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 431 lines"},"text":"actor TeraSessionStore {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":10,"line":70},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines"},"text":" static func production("},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":182},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 14"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":182},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 64 lines"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":389},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines"},"text":" private func reconcileIdentity(_ identity: TeraAppIdentity) async throws {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":1,"line":493},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 493"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraSupportingStores.swift","character":1,"line":451},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 451"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraTodayStore.swift","character":7,"line":13},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 257 lines"},"text":"final class TeraTodayStore: ObservableObject {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Views\/TeraAddView.swift","character":1,"line":4},"severity":"error","reason":"Struct body should span 350 lines or less excluding comments and whitespace: currently spans 454 lines"},"text":"struct TeraAddView: View {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraAddView.swift","character":1,"line":560},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 560"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","character":1,"line":365},"severity":"warning","reason":"Struct body should span 250 lines or less excluding comments and whitespace: currently spans 259 lines"},"text":"struct TeraSettingsView: View {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","character":1,"line":629},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 629"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraTodayView.swift","character":1,"line":493},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 493"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":7,"line":6},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 665 lines"},"text":"final class TeraAddStoreTests: XCTestCase {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":9,"line":847},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 579 lines"},"text":"private actor AddBackend: TeraRuntimeBackend {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":22,"line":934},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 89 lines"},"text":" nonisolated static func schemas() -> [TeraAddSchema] {"},{"violation":{"ruleName":"Function Parameter Count","ruleIdentifier":"function_parameter_count","ruleDescription":"Number of function parameters should be low.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":11,"line":1371},"severity":"warning","reason":"Function should have 5 parameters or less: it currently has 8"},"text":" private func makeStatus("},{"violation":{"ruleName":"Large Tuple","ruleIdentifier":"large_tuple","ruleDescription":"Tuples shouldn't have too many members. Create a custom type instead.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":15,"line":1635},"severity":"error","reason":"Tuples should have at most 2 members"},"text":" var counts: (enqueue: Int, retry: Int, cancel: Int, acceptedSettlement: Int) {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":1,"line":1784},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1784"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":7,"line":7},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 307 lines"},"text":"final class TeraRemoteQualificationTests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":3,"line":45},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 94 lines"},"text":" func testQualificationRejectsAmbiguousOrUnsafeHarnessValues() {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":3,"line":212},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" func testAuthorizationEvidenceIsRedactedEphemeralAndRelaunchCleaned() throws {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraRuntimeClientTests.swift","character":7,"line":4},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 334 lines"},"text":"final class TeraRuntimeClientTests: XCTestCase {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":7,"line":6},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 580 lines"},"text":"final class TeraStateMigrationTests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":5,"line":7},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines"},"text":" func testRelayValidationMatchesRuntimeProfiles() throws {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":1,"line":718},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 718"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","character":9,"line":207},"severity":"warning","reason":"Actor body should span 250 lines or less excluding comments and whitespace: currently spans 253 lines"},"text":"private actor SupportingBackend: TeraRuntimeBackend {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","character":1,"line":487},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 487"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":7,"line":4},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 1493 lines"},"text":"final class TeraRemoteQualificationUITests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":62},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 73 lines"},"text":" func testLocalSocialFiveFlowScenario() throws {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":174},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines"},"text":" func testLocalSocialDeterministicPersonas() throws {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":247},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 54 lines"},"text":" func testRemoteBlossomUploadAndRecovery() throws {"},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":573},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 18"},"text":" private func expectedAddFieldLabel(_ identifier: String, type: String) -> String {"},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":767},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 11"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":767},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":10,"line":1736},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 67 lines"},"text":" static func environment("},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":1,"line":2212},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 2212"},"text":"}"}] -\ No newline at end of file +[{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/App\/TeraAppModel.swift","line":55,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 255 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAppModel: ObservableObject {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/App\/TeraAppModel.swift","line":71,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Initializer body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" init("},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":73,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 427 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraAddMediaCoordinator: TeraAddMediaHandling {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":192,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 55 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func uploadInBackground("},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":580,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 580","ruleDescription":"Files should not span too many lines."},"text":"#endif"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","line":134,"character":15},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 545 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private final class TeraGeneratedRuntimeBackend: TeraRuntimeBackend, @unchecked Sendable {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","line":1696,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1696","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraLifecycleCoordinator.swift","line":434,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 434","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":291,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 847 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraRuntimeClient {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":353,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func start("},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":731,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 88 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func changes(bufferCapacity: Int = 16) async throws -> AsyncStream<TeraRuntimeChange> {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":911,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func beginShutdown() -> ShutdownOperation {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":1221,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1221","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraRuntimeModels.swift","line":1234,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1234","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":11,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 741 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAddStore: ObservableObject {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":280,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func submit() async {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":438,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 51 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func retract(_ card: TeraTodayCard) async {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":524,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func uploadPendingMedia(_ initial: TeraDraftStatus) async throws"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":810,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 810","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":78,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 468 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraConfigurationStore {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":148,"character":5},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 100 lines or less excluding comments and whitespace: currently spans 109 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func load() throws -> TeraAppConfiguration {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":759,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 759","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":40,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 431 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraSessionStore {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":70,"character":10},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" static func production("},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":182,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 14","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":182,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 64 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":389,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func reconcileIdentity(_ identity: TeraAppIdentity) async throws {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":493,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 493","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraSupportingStores.swift","line":451,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 451","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Views\/TeraAddView.swift","line":4,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Struct body should span 350 lines or less excluding comments and whitespace: currently spans 454 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"struct TeraAddView: View {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraAddView.swift","line":560,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 560","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","line":365,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Struct body should span 250 lines or less excluding comments and whitespace: currently spans 259 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"struct TeraSettingsView: View {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","line":629,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 629","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraTodayView.swift","line":493,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 493","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":6,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 665 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAddStoreTests: XCTestCase {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":847,"character":9},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 579 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private actor AddBackend: TeraRuntimeBackend {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":934,"character":22},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 89 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" nonisolated static func schemas() -> [TeraAddSchema] {"},{"violation":{"ruleIdentifier":"function_parameter_count","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1371,"character":11},"ruleName":"Function Parameter Count","severity":"error","reason":"Function should have 5 parameters or less: it currently has 8","ruleDescription":"Number of function parameters should be low."},"text":" private func makeStatus("},{"violation":{"ruleIdentifier":"large_tuple","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1635,"character":15},"ruleName":"Large Tuple","severity":"error","reason":"Tuples should have at most 2 members","ruleDescription":"Tuples shouldn't have too many members. Create a custom type instead."},"text":" var counts: (enqueue: Int, retry: Int, cancel: Int, acceptedSettlement: Int) {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1784,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1784","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":7,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 307 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRemoteQualificationTests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":45,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 94 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testQualificationRejectsAmbiguousOrUnsafeHarnessValues() {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":212,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testAuthorizationEvidenceIsRedactedEphemeralAndRelaunchCleaned() throws {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraRuntimeClientTests.swift","line":4,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 334 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRuntimeClientTests: XCTestCase {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":6,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 580 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraStateMigrationTests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":7,"character":5},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testRelayValidationMatchesRuntimeProfiles() throws {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":718,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 718","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","line":207,"character":9},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 250 lines or less excluding comments and whitespace: currently spans 253 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private actor SupportingBackend: TeraRuntimeBackend {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","line":487,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 487","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":4,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 1493 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRemoteQualificationUITests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":62,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 73 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testLocalSocialFiveFlowScenario() throws {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":174,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testLocalSocialDeterministicPersonas() throws {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":247,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 54 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testRemoteBlossomUploadAndRecovery() throws {"},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":573,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 18","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func expectedAddFieldLabel(_ identifier: String, type: String) -> String {"},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":767,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 11","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":767,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":1736,"character":10},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 67 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" static func environment("},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":2212,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 2212","ruleDescription":"Files should not span too many lines."},"text":"}"}] +\ No newline at end of file