diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..556cff3d2 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,68 @@ +included: + - Sources + - Tests + - Package.swift +excluded: + - Tests/Fixtures + - Tests/AccessibilityTests/AccessibilityProject + - Tests/XcodeTests/UIKitProject + +# Enabled/disabled rules +analyzer_rules: + - all +opt_in_rules: + - all +disabled_rules: + - anyobject_protocol + - inert_defer + - unused_capture_list + - explicit_acl + - explicit_type_interface + - missing_docs + - required_deinit + - line_length + - type_contents_order + - prefer_nimble + - explicit_top_level_acl + - anonymous_argument_in_multiline_closure + - one_declaration_per_file + - conditional_returns_on_newline + - vertical_whitespace_between_cases + - no_grouping_extension + - explicit_enum_raw_value + - file_types_order + - indentation_width + - identifier_name + - trailing_closure + - multiline_arguments_brackets + - multiline_function_chains + - no_extension_access_modifier + - force_try + - switch_case_on_newline + - sorted_enum_cases + - prefer_self_in_static_references + - superfluous_else + - force_unwrapping + - file_name + - todo + - no_magic_numbers + - prefixed_toplevel_constant + - untyped_error_in_catch + - cyclomatic_complexity + - closure_body_length + - function_body_length + - type_body_length + - file_length + - contrasted_opening_brace + - unused_parameter + - no_empty_block + - prefer_key_path + +balanced_xctest_lifecycle: &unit_test_configuration + test_parent_classes: + - SourceGraphTestCase + - FixtureSourceGraphTestCase + - XCTestCase +empty_xctest_method: *unit_test_configuration +final_test_case: *unit_test_configuration +single_test_class: *unit_test_configuration diff --git a/Sources/Frontend/Commands/CheckUpdateCommand.swift b/Sources/Frontend/Commands/CheckUpdateCommand.swift index d44fed161..6c222645e 100644 --- a/Sources/Frontend/Commands/CheckUpdateCommand.swift +++ b/Sources/Frontend/Commands/CheckUpdateCommand.swift @@ -1,5 +1,5 @@ -import Foundation import ArgumentParser +import Foundation import Shared struct CheckUpdateCommand: FrontendCommand { diff --git a/Sources/Frontend/Commands/ClearCacheCommand.swift b/Sources/Frontend/Commands/ClearCacheCommand.swift index 921ad4b44..1309171a7 100644 --- a/Sources/Frontend/Commands/ClearCacheCommand.swift +++ b/Sources/Frontend/Commands/ClearCacheCommand.swift @@ -1,5 +1,5 @@ -import Foundation import ArgumentParser +import Foundation import Shared struct ClearCacheCommand: FrontendCommand { diff --git a/Sources/Frontend/Commands/ScanBehavior.swift b/Sources/Frontend/Commands/ScanBehavior.swift index cefb2dfc8..6bbf9ddde 100644 --- a/Sources/Frontend/Commands/ScanBehavior.swift +++ b/Sources/Frontend/Commands/ScanBehavior.swift @@ -1,7 +1,7 @@ import Foundation -import SystemPackage -import Shared import PeripheryKit +import Shared +import SystemPackage final class ScanBehavior { private let configuration: Configuration @@ -16,7 +16,7 @@ final class ScanBehavior { do { var path: FilePath? - if let configPath = configPath { + if let configPath { path = FilePath(configPath) } try configuration.load(from: path) @@ -90,7 +90,7 @@ final class ScanBehavior { logger.info(output, canQuiet: false) logger.endInterval(interval) - if filteredResults.count > 0, + if !filteredResults.isEmpty, configuration.outputFormat.supportsAuxiliaryOutput { logger.info( colorize("\n* ", .boldGreen) + diff --git a/Sources/Frontend/Commands/ScanCommand.swift b/Sources/Frontend/Commands/ScanCommand.swift index 7a03ebba5..b83b88fcb 100644 --- a/Sources/Frontend/Commands/ScanCommand.swift +++ b/Sources/Frontend/Commands/ScanCommand.swift @@ -1,7 +1,7 @@ -import Foundation import ArgumentParser -import SystemPackage +import Foundation import Shared +import SystemPackage struct ScanCommand: FrontendCommand { static let configuration = CommandConfiguration( diff --git a/Sources/Frontend/Commands/VersionCommand.swift b/Sources/Frontend/Commands/VersionCommand.swift index 47311dd97..4cbf76923 100644 --- a/Sources/Frontend/Commands/VersionCommand.swift +++ b/Sources/Frontend/Commands/VersionCommand.swift @@ -1,5 +1,5 @@ -import Foundation import ArgumentParser +import Foundation struct VersionCommand: FrontendCommand { static let configuration = CommandConfiguration( diff --git a/Sources/Frontend/Project.swift b/Sources/Frontend/Project.swift index 4a4fd9ef6..7f723ce60 100644 --- a/Sources/Frontend/Project.swift +++ b/Sources/Frontend/Project.swift @@ -1,7 +1,7 @@ import Foundation -import SystemPackage import PeripheryKit import Shared +import SystemPackage #if canImport(XcodeSupport) import XcodeSupport diff --git a/Sources/Frontend/SPMProjectSetupGuide.swift b/Sources/Frontend/SPMProjectSetupGuide.swift index e9d8b4b54..cef94391c 100644 --- a/Sources/Frontend/SPMProjectSetupGuide.swift +++ b/Sources/Frontend/SPMProjectSetupGuide.swift @@ -1,7 +1,7 @@ import Foundation -import SystemPackage import PeripheryKit import Shared +import SystemPackage final class SPMProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide { private let configuration: Configuration @@ -51,5 +51,4 @@ final class SPMProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide { let targetNames = targets.map { $0.name }.sorted() return select(multiple: targetNames, allowAll: true) } - } diff --git a/Sources/Frontend/Scan.swift b/Sources/Frontend/Scan.swift index 1d4da9985..ec80638f8 100644 --- a/Sources/Frontend/Scan.swift +++ b/Sources/Frontend/Scan.swift @@ -1,6 +1,6 @@ import Foundation -import Shared import PeripheryKit +import Shared import SourceGraph final class Scan { diff --git a/Sources/Frontend/UpdateChecker.swift b/Sources/Frontend/UpdateChecker.swift index 5da276fe0..dbd7db27d 100644 --- a/Sources/Frontend/UpdateChecker.swift +++ b/Sources/Frontend/UpdateChecker.swift @@ -39,9 +39,10 @@ final class UpdateChecker { urlRequest.setValue("application/vnd.github.v3+json", forHTTPHeaderField: "Accept") let task = urlSession.dataTask(with: urlRequest) { [weak self] data, _, error in + // swiftlint:disable:next self_binding guard let strongSelf = self else { return } - if let error = error { + if let error { strongSelf.debugLogger.debug("error: \(error.localizedDescription)") strongSelf.error = error strongSelf.semaphore.signal() @@ -53,8 +54,11 @@ final class UpdateChecker { let tagName = jsonObject["tag_name"] as? String else { var json = "N/A" - if let data = data { - json = String(data: data, encoding: .utf8) ?? "N/A" + if let data { + let decoded = String(decoding: data, as: UTF8.self) + if !decoded.isEmpty { + json = decoded + } } let message = "Failed to identify latest release tag in: \(json)" @@ -72,7 +76,7 @@ final class UpdateChecker { } func notifyIfAvailable() { - guard let latestVersion = latestVersion else { return } + guard let latestVersion else { return } debugLogger.debug("latest: \(latestVersion)") @@ -91,7 +95,7 @@ final class UpdateChecker { func wait() -> Result { let waitResult = semaphore.wait(timeout: .now() + 60) - if let error = error { + if let error { return .failure(.underlyingError(error)) } @@ -99,7 +103,7 @@ final class UpdateChecker { return .failure(PeripheryError.updateCheckError(message: "Timed out while checking for update.")) } - if let latestVersion = latestVersion { + if let latestVersion { return .success(latestVersion) } diff --git a/Sources/Frontend/main.swift b/Sources/Frontend/main.swift index eec43590d..91289fe80 100644 --- a/Sources/Frontend/main.swift +++ b/Sources/Frontend/main.swift @@ -1,5 +1,5 @@ -import Foundation import ArgumentParser +import Foundation import Shared Logger.configureBuffering() diff --git a/Sources/Indexer/Indexer.swift b/Sources/Indexer/Indexer.swift index 686ef3a2d..d0cd41764 100644 --- a/Sources/Indexer/Indexer.swift +++ b/Sources/Indexer/Indexer.swift @@ -1,7 +1,7 @@ +import FilenameMatcher import Foundation -import SystemPackage import Shared -import FilenameMatcher +import SystemPackage public class Indexer { private let configuration: Configuration diff --git a/Sources/Indexer/InfoPlistIndexer.swift b/Sources/Indexer/InfoPlistIndexer.swift index 6050b731a..140b45dbf 100644 --- a/Sources/Indexer/InfoPlistIndexer.swift +++ b/Sources/Indexer/InfoPlistIndexer.swift @@ -1,6 +1,6 @@ import Shared -import SystemPackage import SourceGraph +import SystemPackage public final class InfoPlistIndexer: Indexer { private let infoPlistFiles: Set @@ -19,15 +19,15 @@ public final class InfoPlistIndexer: Indexer { excludedFiles.forEach { self.logger.debug("Excluding \($0.string)") } try JobPool(jobs: Array(includedFiles)).forEach { [weak self] path in - guard let self = self else { return } + guard let self else { return } let elapsed = try Benchmark.measure { try InfoPlistParser(path: path) .parse() - .forEach { self.graph.add($0) } + .forEach { self.graph.add($0) } } - self.logger.debug("\(path.string) (\(elapsed)s)") + logger.debug("\(path.string) (\(elapsed)s)") } } } diff --git a/Sources/Indexer/InfoPlistParser.swift b/Sources/Indexer/InfoPlistParser.swift index 6cf44d03f..a1fe0c9f3 100644 --- a/Sources/Indexer/InfoPlistParser.swift +++ b/Sources/Indexer/InfoPlistParser.swift @@ -1,13 +1,14 @@ -import Foundation -import SystemPackage import AEXML +import Foundation import Shared import SourceGraph +import SystemPackage final class InfoPlistParser { private static let elements = [ "UISceneClassName", "UISceneDelegateClassName", "NSPrincipalClass", - "NSExtensionPrincipalClass", "CLKComplicationPrincipalClass", "WKExtensionDelegateClassName"] + "NSExtensionPrincipalClass", "CLKComplicationPrincipalClass", "WKExtensionDelegateClassName" + ] private let path: FilePath required init(path: FilePath) { diff --git a/Sources/Indexer/JobPool.swift b/Sources/Indexer/JobPool.swift index acc213779..84b92d016 100644 --- a/Sources/Indexer/JobPool.swift +++ b/Sources/Indexer/JobPool.swift @@ -18,7 +18,7 @@ struct JobPool { } } - if let error = error { + if let error { throw error } } @@ -43,7 +43,7 @@ struct JobPool { } } - if let error = error { + if let error { throw error } diff --git a/Sources/Indexer/SwiftIndexer.swift b/Sources/Indexer/SwiftIndexer.swift index 83c342982..9ad1aea3b 100644 --- a/Sources/Indexer/SwiftIndexer.swift +++ b/Sources/Indexer/SwiftIndexer.swift @@ -1,9 +1,9 @@ import Foundation -import SwiftIndexStore -import SystemPackage import Shared import SourceGraph +import SwiftIndexStore import SyntaxAnalysis +import SystemPackage public final class SwiftIndexer: Indexer { private let sourceFiles: [FilePath: Set] @@ -39,6 +39,7 @@ public final class SwiftIndexer: Indexer { let indexStore = try IndexStore.open(store: URL(fileURLWithPath: indexStorePath.string), lib: .open()) let units = indexStore.units(includeSystem: false) + // swiftlint:disable:next large_tuple return try units.compactMap { unit -> (FilePath, IndexStore, IndexStoreUnit)? in guard let filePath = try indexStore.mainFilePath(for: unit) else { return nil } @@ -71,8 +72,8 @@ public final class SwiftIndexer: Indexer { retainedFiles = allSourceFiles.filter { configuration.retainFilesMatchers.anyMatch(filename: $0.string) } } - let jobs = unitsByFile.map { (file, units) -> Job in - return Job( + let jobs = unitsByFile.map { file, units -> Job in + Job( file: file, units: units, retainAllDeclarations: retainedFiles.contains(file), @@ -128,7 +129,6 @@ public final class SwiftIndexer: Indexer { graph: SourceGraph, logger: ContextualLogger, configuration: Configuration - ) { self.file = file self.units = units @@ -138,6 +138,7 @@ public final class SwiftIndexer: Indexer { self.configuration = configuration } + // swiftlint:disable nesting struct RawRelation { struct Symbol { let name: String? @@ -170,6 +171,7 @@ public final class SwiftIndexer: Indexer { Key(kind: kind, name: name, isImplicit: isImplicit, isObjcAccessible: isObjcAccessible, location: location) } } + // swiftlint:enable nesting /// Phase one reads the index store and establishes the declaration hierarchy and the majority of references. /// Some references may depend upon declarations in other files, and thus their association is deferred until @@ -280,7 +282,7 @@ public final class SwiftIndexer: Indexer { private func getSourceFile() throws -> SourceFile { if let sourceFile { return sourceFile } - let modules = try units.reduce(into: Set()) { (set, tuple) in + let modules = try units.reduce(into: Set()) { set, tuple in let (indexStore, unit) = tuple if let name = try indexStore.moduleName(for: unit) { set.insert(name) @@ -340,11 +342,11 @@ public final class SwiftIndexer: Indexer { let explicitDeclarations = declarations.filter { !$0.isImplicit } let declsByLocation = explicitDeclarations - .reduce(into: [Location: [Declaration]]()) { (result, decl) in + .reduce(into: [Location: [Declaration]]()) { result, decl in result[decl.location, default: []].append(decl) } let declsByLine = explicitDeclarations - .reduce(into: [Int: [Declaration]]()) { (result, decl) in + .reduce(into: [Int: [Declaration]]()) { result, decl in result[decl.location.line, default: []].append(decl) } let sortedDeclLines = declsByLine.keys.sorted().reversed() @@ -370,7 +372,7 @@ public final class SwiftIndexer: Indexer { // a decl without a parent, as the reference may be a related type of a class/struct/etc. if let decl = candidateDecls.first(where: { $0.parent == nil }) { associate(ref, with: decl) - } else if let decl = candidateDecls.sorted().first { + } else if let decl = candidateDecls.min() { // Fallback to using the first declaration. // Sorting the declarations helps in the situation where the candidate declarations includes a // property/subscript, and a getter on the same line. The property/subscript is more likely to be @@ -694,7 +696,7 @@ public final class SwiftIndexer: Indexer { } private func transformLocation(_ input: IndexStoreOccurrence.Location) throws -> Location? { - return Location(file: try getSourceFile(), line: Int(input.line), column: Int(input.column)) + Location(file: try getSourceFile(), line: Int(input.line), column: Int(input.column)) } private func transformDeclarationKind(_ kind: IndexStoreSymbol.Kind, _ subKind: IndexStoreSymbol.SubKind) -> Declaration.Kind? { diff --git a/Sources/Indexer/XCDataModelIndexer.swift b/Sources/Indexer/XCDataModelIndexer.swift index d16f4a0c9..5613e2b43 100644 --- a/Sources/Indexer/XCDataModelIndexer.swift +++ b/Sources/Indexer/XCDataModelIndexer.swift @@ -1,6 +1,6 @@ import Shared -import SystemPackage import SourceGraph +import SystemPackage public final class XCDataModelIndexer: Indexer { private let files: Set @@ -19,7 +19,7 @@ public final class XCDataModelIndexer: Indexer { excludedFiles.forEach { self.logger.debug("Excluding \($0.string)") } try JobPool(jobs: Array(includedFiles)).forEach { [weak self] path in - guard let self = self else { return } + guard let self else { return } let elapsed = try Benchmark.measure { try XCDataModelParser(path: path) @@ -27,7 +27,7 @@ public final class XCDataModelIndexer: Indexer { .forEach { self.graph.add($0) } } - self.logger.debug("\(path.string) (\(elapsed)s)") + logger.debug("\(path.string) (\(elapsed)s)") } } } diff --git a/Sources/Indexer/XCDataModelParser.swift b/Sources/Indexer/XCDataModelParser.swift index 3a634941b..993b2a5c4 100644 --- a/Sources/Indexer/XCDataModelParser.swift +++ b/Sources/Indexer/XCDataModelParser.swift @@ -1,7 +1,7 @@ -import Foundation import AEXML -import SystemPackage +import Foundation import SourceGraph +import SystemPackage final class XCDataModelParser { private let path: FilePath diff --git a/Sources/Indexer/XCMappingModelIndexer.swift b/Sources/Indexer/XCMappingModelIndexer.swift index ae5eff88a..045d97099 100644 --- a/Sources/Indexer/XCMappingModelIndexer.swift +++ b/Sources/Indexer/XCMappingModelIndexer.swift @@ -1,6 +1,6 @@ import Shared -import SystemPackage import SourceGraph +import SystemPackage public final class XCMappingModelIndexer: Indexer { private let files: Set @@ -19,7 +19,7 @@ public final class XCMappingModelIndexer: Indexer { excludedFiles.forEach { self.logger.debug("Excluding \($0.string)") } try JobPool(jobs: Array(includedFiles)).forEach { [weak self] path in - guard let self = self else { return } + guard let self else { return } let elapsed = try Benchmark.measure { try XCMappingModelParser(path: path) @@ -27,7 +27,7 @@ public final class XCMappingModelIndexer: Indexer { .forEach { self.graph.add($0) } } - self.logger.debug("\(path.string) (\(elapsed)s)") + logger.debug("\(path.string) (\(elapsed)s)") } } } diff --git a/Sources/Indexer/XCMappingModelParser.swift b/Sources/Indexer/XCMappingModelParser.swift index 56f5564b0..e478265e9 100644 --- a/Sources/Indexer/XCMappingModelParser.swift +++ b/Sources/Indexer/XCMappingModelParser.swift @@ -1,7 +1,7 @@ -import Foundation import AEXML -import SystemPackage +import Foundation import SourceGraph +import SystemPackage final class XCMappingModelParser { private let path: FilePath diff --git a/Sources/Indexer/XibIndexer.swift b/Sources/Indexer/XibIndexer.swift index 0459f1629..6c96ded55 100644 --- a/Sources/Indexer/XibIndexer.swift +++ b/Sources/Indexer/XibIndexer.swift @@ -1,6 +1,6 @@ import Shared -import SystemPackage import SourceGraph +import SystemPackage public final class XibIndexer: Indexer { private let xibFiles: Set @@ -19,7 +19,7 @@ public final class XibIndexer: Indexer { excludedFiles.forEach { self.logger.debug("Excluding \($0.string)") } try JobPool(jobs: Array(includedFiles)).forEach { [weak self] xibPath in - guard let self = self else { return } + guard let self else { return } let elapsed = try Benchmark.measure { try XibParser(path: xibPath) @@ -27,7 +27,7 @@ public final class XibIndexer: Indexer { .forEach { self.graph.add($0) } } - self.logger.debug("\(xibPath.string) (\(elapsed)s)") + logger.debug("\(xibPath.string) (\(elapsed)s)") } } } diff --git a/Sources/Indexer/XibParser.swift b/Sources/Indexer/XibParser.swift index 6273ac550..54e003b87 100644 --- a/Sources/Indexer/XibParser.swift +++ b/Sources/Indexer/XibParser.swift @@ -1,7 +1,7 @@ -import Foundation import AEXML -import SystemPackage +import Foundation import SourceGraph +import SystemPackage final class XibParser { private let path: FilePath diff --git a/Sources/PeripheryKit/Generic/GenericProjectDriver.swift b/Sources/PeripheryKit/Generic/GenericProjectDriver.swift index f31488fd9..8f5936909 100644 --- a/Sources/PeripheryKit/Generic/GenericProjectDriver.swift +++ b/Sources/PeripheryKit/Generic/GenericProjectDriver.swift @@ -1,8 +1,8 @@ import Foundation -import SystemPackage import Indexer import Shared import SourceGraph +import SystemPackage public final class GenericProjectDriver { private enum FileKind: String { diff --git a/Sources/PeripheryKit/Results/CheckstyleFormatter.swift b/Sources/PeripheryKit/Results/CheckstyleFormatter.swift index 75d4a5c40..6e1b2fee8 100644 --- a/Sources/PeripheryKit/Results/CheckstyleFormatter.swift +++ b/Sources/PeripheryKit/Results/CheckstyleFormatter.swift @@ -1,7 +1,7 @@ import Foundation import Shared -import SystemPackage import SourceGraph +import SystemPackage final class CheckstyleFormatter: OutputFormatter { let configuration: Configuration @@ -13,7 +13,7 @@ final class CheckstyleFormatter: OutputFormatter { func format(_ results: [ScanResult]) -> String { let parts = results.flatMap { describe($0, colored: false) } - let xml = [ + return [ "\n", parts .group(by: { outputPath($0.0).string.escapedForXML() }) @@ -21,13 +21,12 @@ final class CheckstyleFormatter: OutputFormatter { .map(generateForFile).joined(), "\n" ].joined() - return xml } // MARK: - Private private func generateForFile(_ file: String, results: [(Location, String)]) -> String { - return [ + [ "\n\t\n", results.map(generateForResult).joined(), "\t" diff --git a/Sources/PeripheryKit/Results/CodeClimateFormatter.swift b/Sources/PeripheryKit/Results/CodeClimateFormatter.swift index 54fd74f65..b7f901274 100644 --- a/Sources/PeripheryKit/Results/CodeClimateFormatter.swift +++ b/Sources/PeripheryKit/Results/CodeClimateFormatter.swift @@ -49,7 +49,6 @@ final class CodeClimateFormatter: OutputFormatter { } let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted, .withoutEscapingSlashes]) - let json = String(data: data, encoding: .utf8) - return json ?? "" + return String(decoding: data, as: UTF8.self) } } diff --git a/Sources/PeripheryKit/Results/CsvFormatter.swift b/Sources/PeripheryKit/Results/CsvFormatter.swift index ea1a2e1f6..5a674dc0f 100644 --- a/Sources/PeripheryKit/Results/CsvFormatter.swift +++ b/Sources/PeripheryKit/Results/CsvFormatter.swift @@ -1,7 +1,7 @@ import Foundation import Shared -import SystemPackage import SourceGraph +import SystemPackage final class CsvFormatter: OutputFormatter { let configuration: Configuration @@ -51,6 +51,7 @@ final class CsvFormatter: OutputFormatter { // MARK: - Private + // swiftlint:disable:next function_parameter_count private func format( kind: String, name: String?, diff --git a/Sources/PeripheryKit/Results/GitHubActionsFormatter.swift b/Sources/PeripheryKit/Results/GitHubActionsFormatter.swift index 3398edc18..89a57bf7e 100644 --- a/Sources/PeripheryKit/Results/GitHubActionsFormatter.swift +++ b/Sources/PeripheryKit/Results/GitHubActionsFormatter.swift @@ -1,7 +1,7 @@ import Foundation import Shared -import SystemPackage import SourceGraph +import SystemPackage final class GitHubActionsFormatter: OutputFormatter { let configuration: Configuration @@ -12,11 +12,11 @@ final class GitHubActionsFormatter: OutputFormatter { } func format(_ results: [ScanResult]) throws -> String { - guard results.count > 0 else { return "" } + guard !results.isEmpty else { return "" } guard configuration.relativeResults else { throw PeripheryError.usageError("`periphery scan` must be ran with `--relative-results` when using the GitHub Actions formatter")} return results.flatMap { result in - describe(result, colored: false).map { (location, description) in + describe(result, colored: false).map { location, description in prefix(for: location, result: result) + description } } diff --git a/Sources/PeripheryKit/Results/JsonFormatter.swift b/Sources/PeripheryKit/Results/JsonFormatter.swift index a2ae362fc..1eaa6e02c 100644 --- a/Sources/PeripheryKit/Results/JsonFormatter.swift +++ b/Sources/PeripheryKit/Results/JsonFormatter.swift @@ -48,7 +48,6 @@ final class JsonFormatter: OutputFormatter { } let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted, .withoutEscapingSlashes]) - let json = String(data: data, encoding: .utf8) - return json ?? "" + return String(decoding: data, as: UTF8.self) } } diff --git a/Sources/PeripheryKit/Results/OutputDeclarationFilter.swift b/Sources/PeripheryKit/Results/OutputDeclarationFilter.swift index 745a24ff7..89361c1a5 100644 --- a/Sources/PeripheryKit/Results/OutputDeclarationFilter.swift +++ b/Sources/PeripheryKit/Results/OutputDeclarationFilter.swift @@ -1,7 +1,7 @@ +import FilenameMatcher import Foundation -import SystemPackage import Shared -import FilenameMatcher +import SystemPackage public final class OutputDeclarationFilter { private let configuration: Configuration diff --git a/Sources/PeripheryKit/Results/OutputFormatter.swift b/Sources/PeripheryKit/Results/OutputFormatter.swift index 8a7d7f7eb..6493623e4 100644 --- a/Sources/PeripheryKit/Results/OutputFormatter.swift +++ b/Sources/PeripheryKit/Results/OutputFormatter.swift @@ -1,11 +1,12 @@ import Foundation import Shared -import SystemPackage import SourceGraph +import SystemPackage public protocol OutputFormatter: AnyObject { var configuration: Configuration { get } var currentFilePath: FilePath { get } + init(configuration: Configuration) func format(_ results: [ScanResult]) throws -> String } @@ -38,6 +39,7 @@ extension OutputFormatter { var secondaryResults: [(Location, String)] = [] if var name = result.declaration.name { + // swiftlint:disable:next identifier_name if let kind = result.declaration.kind.displayName, let first_ = kind.first { let first = String(first_) description += "\(first.uppercased())\(kind.dropFirst()) " @@ -93,6 +95,7 @@ extension OutputFormatter { } } +// swiftlint:disable:next no_extension_access_modifier public extension OutputFormat { var formatter: OutputFormatter.Type { switch self { diff --git a/Sources/PeripheryKit/Results/XcodeFormatter.swift b/Sources/PeripheryKit/Results/XcodeFormatter.swift index 9a610f833..b96a30ef8 100644 --- a/Sources/PeripheryKit/Results/XcodeFormatter.swift +++ b/Sources/PeripheryKit/Results/XcodeFormatter.swift @@ -1,7 +1,7 @@ import Foundation import Shared -import SystemPackage import SourceGraph +import SystemPackage final class XcodeFormatter: OutputFormatter { let configuration: Configuration @@ -12,12 +12,12 @@ final class XcodeFormatter: OutputFormatter { } func format(_ results: [ScanResult]) throws -> String { - guard results.count > 0 else { + guard !results.isEmpty else { return colorize("* ", .boldGreen) + colorize("No unused code detected.", .bold) } return results.flatMap { result in - describe(result, colored: true).map { (location, description) in + describe(result, colored: true).map { location, description in prefix(for: location) + description } } diff --git a/Sources/PeripheryKit/SPM/SPM.swift b/Sources/PeripheryKit/SPM/SPM.swift index cdd447d19..4c3408fc8 100644 --- a/Sources/PeripheryKit/SPM/SPM.swift +++ b/Sources/PeripheryKit/SPM/SPM.swift @@ -1,8 +1,8 @@ import Foundation -import SystemPackage import Shared +import SystemPackage -public struct SPM { +public enum SPM { static let packageFile = "Package.swift" public static var isSupported: Bool { @@ -29,7 +29,7 @@ public struct SPM { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase - return try decoder.decode(Package.self, from: jsonData) + return try decoder.decode(Self.self, from: jsonData) } public let name: String diff --git a/Sources/PeripheryKit/SPM/SPMProjectDriver.swift b/Sources/PeripheryKit/SPM/SPMProjectDriver.swift index 85b3b7206..3efa2513c 100644 --- a/Sources/PeripheryKit/SPM/SPMProjectDriver.swift +++ b/Sources/PeripheryKit/SPM/SPMProjectDriver.swift @@ -1,8 +1,8 @@ import Foundation -import SystemPackage +import Indexer import Shared import SourceGraph -import Indexer +import SystemPackage public final class SPMProjectDriver { public static func build() throws -> Self { diff --git a/Sources/PeripheryKit/ScanResultBuilder.swift b/Sources/PeripheryKit/ScanResultBuilder.swift index 731157452..6355858c9 100644 --- a/Sources/PeripheryKit/ScanResultBuilder.swift +++ b/Sources/PeripheryKit/ScanResultBuilder.swift @@ -1,7 +1,7 @@ import Foundation import SourceGraph -public struct ScanResultBuilder { +public enum ScanResultBuilder { public static func build(for graph: SourceGraph) -> [ScanResult] { let assignOnlyProperties = graph.assignOnlyProperties let removableDeclarations = graph.unusedDeclarations @@ -10,13 +10,13 @@ public struct ScanResultBuilder { let redundantProtocols = graph.redundantProtocols.filter { !removableDeclarations.contains($0.0) } let redundantPublicAccessibility = graph.redundantPublicAccessibility.filter { !removableDeclarations.contains($0.0) } - let annotatedRemovableDeclarations: [ScanResult] = removableDeclarations.flatMap { + let annotatedRemovableDeclarations: [ScanResult] = removableDeclarations.flatMap { removableDeclaration in var extensionResults = [ScanResult]() - if $0.kind.isExtendableKind, - !graph.retainedDeclarations.contains($0), - !graph.ignoredDeclarations.contains($0) { - let decls = $0.descendentDeclarations.union([$0]) + if removableDeclaration.kind.isExtendableKind, + !graph.retainedDeclarations.contains(removableDeclaration), + !graph.ignoredDeclarations.contains(removableDeclaration) { + let decls = removableDeclaration.descendentDeclarations.union([removableDeclaration]) for decl in decls { let extensions = graph.extensions[decl, default: []] @@ -26,7 +26,7 @@ public struct ScanResultBuilder { } } - return [ScanResult(declaration: $0, annotation: .unused)] + extensionResults + return [ScanResult(declaration: removableDeclaration, annotation: .unused)] + extensionResults } let annotatedAssignOnlyProperties: [ScanResult] = assignOnlyProperties.map { .init(declaration: $0, annotation: .assignOnlyProperty) @@ -44,14 +44,12 @@ public struct ScanResultBuilder { annotatedRedundantProtocols + annotatedRedundantPublicAccessibility - let result = allAnnotatedDeclarations + return allAnnotatedDeclarations .filter { !$0.declaration.isImplicit && !$0.declaration.kind.isAccessorKind && !graph.ignoredDeclarations.contains($0.declaration) && !graph.retainedDeclarations.contains($0.declaration) } - - return result } } diff --git a/Sources/Shared/Benchmark.swift b/Sources/Shared/Benchmark.swift index f574b0a34..08b845579 100644 --- a/Sources/Shared/Benchmark.swift +++ b/Sources/Shared/Benchmark.swift @@ -1,6 +1,6 @@ import Foundation -public final class Benchmark { +public enum Benchmark { @inlinable public static func measure(block: () throws -> Void) rethrows -> String { let start = Date() diff --git a/Sources/Shared/Configuration.swift b/Sources/Shared/Configuration.swift index a4803d0c2..d5a4a986f 100644 --- a/Sources/Shared/Configuration.swift +++ b/Sources/Shared/Configuration.swift @@ -1,7 +1,7 @@ +import FilenameMatcher import Foundation import SystemPackage import Yams -import FilenameMatcher public final class Configuration { public static var defaultConfigurationFile = ".periphery.yml" @@ -435,6 +435,7 @@ public final class Configuration { } } + // swiftlint:disable:next discouraged_optional_collection private var _indexExcludeMatchers: [FilenameMatcher]? public var indexExcludeMatchers: [FilenameMatcher] { if let _indexExcludeMatchers { @@ -446,6 +447,7 @@ public final class Configuration { return matchers } + // swiftlint:disable:next discouraged_optional_collection private var _retainFilesMatchers: [FilenameMatcher]? public var retainFilesMatchers: [FilenameMatcher] { if let _retainFilesMatchers { @@ -479,7 +481,7 @@ public final class Configuration { } private func configurationPath(withUserProvided path: FilePath?) throws -> FilePath? { - if let path = path { + if let path { if !path.exists { throw PeripheryError.pathDoesNotExist(path: path.lexicallyNormalized().string) } @@ -491,21 +493,26 @@ public final class Configuration { } } -@propertyWrapper public final class Setting { +@propertyWrapper +public final class Setting { typealias ValueConverter = (Any) -> Value? typealias ValueSanitizer = (Value) -> Value public let defaultValue: Value + // swiftlint:disable:next strict_fileprivate fileprivate let key: String private let valueConverter: ValueConverter private let valueSanitizer: ValueSanitizer private var value: Value - fileprivate init(key: String, - defaultValue: Value, - valueConverter: @escaping ValueConverter = { $0 as? Value }, - valueSanitizer: @escaping ValueSanitizer = { $0 }) { + // swiftlint:disable:next strict_fileprivate + fileprivate init( + key: String, + defaultValue: Value, + valueConverter: @escaping ValueConverter = { $0 as? Value }, + valueSanitizer: @escaping ValueSanitizer = { $0 } + ) { self.key = key self.value = defaultValue self.defaultValue = defaultValue @@ -520,6 +527,7 @@ public final class Configuration { public var projectedValue: Setting { self } + // swiftlint:disable strict_fileprivate fileprivate var hasNonDefaultValue: Bool { value != defaultValue } @@ -531,8 +539,10 @@ public final class Configuration { fileprivate func reset() { wrappedValue = defaultValue } + // swiftlint:enable strict_fileprivate } +// swiftlint:disable:next discouraged_optional_collection private let filePathConverter: (Any) -> [FilePath]? = { value in if let path = value as? String { return [FilePath(path)] diff --git a/Sources/Shared/Constants.swift b/Sources/Shared/Constants.swift index 3ec61dc5e..c5d08c756 100644 --- a/Sources/Shared/Constants.swift +++ b/Sources/Shared/Constants.swift @@ -1,7 +1,7 @@ import Foundation import SystemPackage -public struct Constants { +public enum Constants { public static func cachePath() throws -> FilePath { let url = try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) return FilePath(url.appendingPathComponent("com.github.peripheryapp").path) diff --git a/Sources/Shared/Extensions/Array+Extension.swift b/Sources/Shared/Extensions/Array+Extension.swift index 984892e88..ed0a26c21 100644 --- a/Sources/Shared/Extensions/Array+Extension.swift +++ b/Sources/Shared/Extensions/Array+Extension.swift @@ -3,7 +3,8 @@ import Foundation public extension Array { @inlinable func group(by transform: (Element) -> U) -> [U: [Element]] { - return reduce([:]) { dictionary, element in + // swiftlint:disable:next reduce_into + reduce([:]) { dictionary, element in var dictionary = dictionary let key = transform(element) dictionary[key] = (dictionary[key] ?? []) + [element] diff --git a/Sources/Shared/Extensions/Collection+Extension.swift b/Sources/Shared/Extensions/Collection+Extension.swift index 5dd5374b1..8a30d6810 100644 --- a/Sources/Shared/Extensions/Collection+Extension.swift +++ b/Sources/Shared/Extensions/Collection+Extension.swift @@ -4,6 +4,6 @@ public extension Collection { /// Returns the element at the specified index iff it is within bounds, otherwise nil. @inlinable subscript (safe index: Index) -> Element? { - return indices.contains(index) ? self[index] : nil + indices.contains(index) ? self[index] : nil } } diff --git a/Sources/Shared/Extensions/FilePath+Extension.swift b/Sources/Shared/Extensions/FilePath+Extension.swift index 5984ca95f..30a252d7f 100644 --- a/Sources/Shared/Extensions/FilePath+Extension.swift +++ b/Sources/Shared/Extensions/FilePath+Extension.swift @@ -2,8 +2,7 @@ import Foundation import SystemPackage public extension FilePath { - @inlinable - static var current: FilePath { + @inlinable static var current: FilePath { Self(fileManager.currentDirectoryPath) } @@ -22,13 +21,11 @@ public extension FilePath { return filePath } - @inlinable - var exists: Bool { + @inlinable var exists: Bool { fileManager.fileExists(atPath: lexicallyNormalized().string) } - @inlinable - var url: URL { + @inlinable var url: URL { URL(fileURLWithPath: lexicallyNormalized().string) } @@ -65,19 +62,17 @@ public extension FilePath { // MARK: - Private - @usableFromInline - internal static var fileManager: FileManager { + @usableFromInline internal static var fileManager: FileManager { FileManager.default } - @usableFromInline - internal var fileManager: FileManager { + @usableFromInline internal var fileManager: FileManager { Self.fileManager } } extension FilePath: Comparable { public static func < (lhs: FilePath, rhs: FilePath) -> Bool { - return lhs.lexicallyNormalized().string < rhs.lexicallyNormalized().string + lhs.lexicallyNormalized().string < rhs.lexicallyNormalized().string } } diff --git a/Sources/Shared/Extensions/FilePath+Glob.swift b/Sources/Shared/Extensions/FilePath+Glob.swift index 98f24a5d3..43250c20c 100644 --- a/Sources/Shared/Extensions/FilePath+Glob.swift +++ b/Sources/Shared/Extensions/FilePath+Glob.swift @@ -1,4 +1,4 @@ -// +// swiftlint:disable file_header // Created by Eric Firestone on 3/22/16. // Copyright © 2016 Square, Inc. All rights reserved. // Released under the Apache v2 License. @@ -31,6 +31,7 @@ private class Glob { private let logger: Logger private var isDirectoryCache: [String: Bool] = [:] + // swiftlint:disable:next strict_fileprivate fileprivate var paths: Set = [] init( @@ -98,6 +99,7 @@ private class Glob { for directory in directories { let partiallyResolvedPattern = directory.appendingPathComponent(lastPart) + // swiftlint:disable:next legacy_objc_type let standardizedPattern = (partiallyResolvedPattern.relativePath as NSString).standardizingPath results.append(contentsOf: expandGlobstar(pattern: standardizedPattern)) } diff --git a/Sources/Shared/Extensions/FilenameMatcher+Extension.swift b/Sources/Shared/Extensions/FilenameMatcher+Extension.swift index dae6482ab..02bcc9df9 100644 --- a/Sources/Shared/Extensions/FilenameMatcher+Extension.swift +++ b/Sources/Shared/Extensions/FilenameMatcher+Extension.swift @@ -1,5 +1,5 @@ -import Foundation import FilenameMatcher +import Foundation public extension FilenameMatcher { @inlinable diff --git a/Sources/Shared/Extensions/String+Extension.swift b/Sources/Shared/Extensions/String+Extension.swift index bf92cc831..07852c8e9 100644 --- a/Sources/Shared/Extensions/String+Extension.swift +++ b/Sources/Shared/Extensions/String+Extension.swift @@ -1,9 +1,8 @@ import Foundation public extension String { - @inlinable - var trimmed: String { - return trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + @inlinable var trimmed: String { + trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) } @inlinable @@ -24,15 +23,13 @@ public extension String { } // http://www.cse.yorku.ca/~oz/hash.html - @inlinable - var djb2: Int { + @inlinable var djb2: Int { unicodeScalars .map { $0.value } - .reduce(5381) { ($0 << 5) &+ $0 &+ Int($1) } + .reduce(5_381) { ($0 << 5) &+ $0 &+ Int($1) } } - @inlinable - var djb2Hex: String { + @inlinable var djb2Hex: String { String(format: "%02x", djb2) } } diff --git a/Sources/Shared/Extensions/String+Version.swift b/Sources/Shared/Extensions/String+Version.swift index 5e9217714..42006b3f3 100644 --- a/Sources/Shared/Extensions/String+Version.swift +++ b/Sources/Shared/Extensions/String+Version.swift @@ -7,7 +7,6 @@ public typealias VersionString = String public extension VersionString { /// Inner comparison utility to handle same versions with different length. (Ex: "1.0.0" & "1.0") private func compare(toVersion targetVersion: String) -> ComparisonResult { - let versionDelimiter = "." var result: ComparisonResult = .orderedSame var versionComponents = components(separatedBy: versionDelimiter) @@ -29,9 +28,9 @@ public extension VersionString { return result } - func isVersion(equalTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedSame } - func isVersion(greaterThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedDescending } - func isVersion(greaterThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedAscending } - func isVersion(lessThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedAscending } - func isVersion(lessThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedDescending } + func isVersion(equalTo targetVersion: String) -> Bool { compare(toVersion: targetVersion) == .orderedSame } + func isVersion(greaterThan targetVersion: String) -> Bool { compare(toVersion: targetVersion) == .orderedDescending } + func isVersion(greaterThanOrEqualTo targetVersion: String) -> Bool { compare(toVersion: targetVersion) != .orderedAscending } + func isVersion(lessThan targetVersion: String) -> Bool { compare(toVersion: targetVersion) == .orderedAscending } + func isVersion(lessThanOrEqualTo targetVersion: String) -> Bool { compare(toVersion: targetVersion) != .orderedDescending } } diff --git a/Sources/Shared/Logger.swift b/Sources/Shared/Logger.swift index 075e39c42..240086e36 100644 --- a/Sources/Shared/Logger.swift +++ b/Sources/Shared/Logger.swift @@ -21,8 +21,7 @@ public enum ANSIColor: String { case gray = "\u{001B}[0;1;30m" } -@usableFromInline -var isColorOutputCapable: Bool = { +@usableFromInline var isColorOutputCapable: Bool = { guard let term = ProcessInfo.processInfo.environment["TERM"], term.lowercased() != "dumb", isatty(fileno(stdout)) != 0 else { @@ -41,8 +40,7 @@ public func colorize(_ text: String, _ color: ANSIColor) -> String { public final class BaseLogger { public static let shared = BaseLogger() - @usableFromInline - let outputQueue: DispatchQueue + @usableFromInline let outputQueue: DispatchQueue private init() { self.outputQueue = DispatchQueue(label: "BaseLogger.outputQueue") @@ -146,7 +144,6 @@ public final class Logger { #if canImport(os) signposter.endInterval(interval.name, interval.state) #endif - } } @@ -194,6 +191,8 @@ public struct SignpostInterval { } #else public struct SignpostInterval { - @usableFromInline init() {} + // swiftlint:disable:next unneeded_synthesized_initializer + @usableFromInline + init() {} } #endif diff --git a/Sources/Shared/OutputFormat.swift b/Sources/Shared/OutputFormat.swift index 77b508216..8c82cc460 100644 --- a/Sources/Shared/OutputFormat.swift +++ b/Sources/Shared/OutputFormat.swift @@ -14,8 +14,7 @@ public enum OutputFormat: String, CaseIterable { self.init(rawValue: anyValue as? String ?? "") } - @inlinable - public var supportsAuxiliaryOutput: Bool { + @inlinable public var supportsAuxiliaryOutput: Bool { self == .xcode } } diff --git a/Sources/Shared/PeripheryError.swift b/Sources/Shared/PeripheryError.swift index 0428f888e..d2dc38cab 100644 --- a/Sources/Shared/PeripheryError.swift +++ b/Sources/Shared/PeripheryError.swift @@ -72,7 +72,7 @@ public enum PeripheryError: Error, LocalizedError, CustomStringConvertible { } public var description: String { - return errorDescription! + errorDescription! } // MARK: - Private diff --git a/Sources/Shared/PropertyTypeSanitizer.swift b/Sources/Shared/PropertyTypeSanitizer.swift index efcc3847b..3785aebc5 100644 --- a/Sources/Shared/PropertyTypeSanitizer.swift +++ b/Sources/Shared/PropertyTypeSanitizer.swift @@ -1,6 +1,6 @@ import Foundation -public struct PropertyTypeSanitizer { +public enum PropertyTypeSanitizer { @inlinable public static func sanitize(_ types: [String]) -> [String] { types.map { sanitize($0) } diff --git a/Sources/Shared/SetupGuide.swift b/Sources/Shared/SetupGuide.swift index f741156c2..64c629637 100644 --- a/Sources/Shared/SetupGuide.swift +++ b/Sources/Shared/SetupGuide.swift @@ -1,8 +1,9 @@ import Foundation public protocol SetupGuide { - func perform() throws var commandLineOptions: [String] { get } + + func perform() throws } public enum SetupSelection { diff --git a/Sources/Shared/Shell.swift b/Sources/Shared/Shell.swift index 1d4d2393f..778439e06 100644 --- a/Sources/Shared/Shell.swift +++ b/Sources/Shared/Shell.swift @@ -46,7 +46,7 @@ final class ReadableStream { open class Shell { public static let shared: Shell = { - return Shell(environment: ProcessInfo.processInfo.environment, logger: Logger()) + Shell(environment: ProcessInfo.processInfo.environment, logger: Logger()) }() private var tasks: Set = [] @@ -55,7 +55,7 @@ open class Shell { private let environment: [String: String] private let logger: ContextualLogger - required public init(environment: [String: String], logger: Logger) { + public required init(environment: [String: String], logger: Logger) { self.environment = environment self.logger = logger.contextualized(with: "shell") } @@ -75,7 +75,7 @@ open class Shell { let pair = line.split(separator: "=", maxSplits: 1) return (String(pair.first ?? ""), String(pair.last ?? "")) } - .reduce(into: [String: String]()) { (result, pair) in + .reduce(into: [String: String]()) { result, pair in result[pair.0] = pair.1 } diff --git a/Sources/Shared/SwiftVersionParser.swift b/Sources/Shared/SwiftVersionParser.swift index 8757b52b9..c0092a5e7 100644 --- a/Sources/Shared/SwiftVersionParser.swift +++ b/Sources/Shared/SwiftVersionParser.swift @@ -1,6 +1,6 @@ import Foundation -public struct SwiftVersionParser { +public enum SwiftVersionParser { public static func parse(_ fullVersion: String) throws -> VersionString { guard let rawVersion = fullVersion.components(separatedBy: "Swift version").last?.split(separator: " ").first else { throw PeripheryError.swiftVersionParseError(fullVersion: fullVersion) diff --git a/Sources/Shared/UnfairLock.swift b/Sources/Shared/UnfairLock.swift index 7e502cd0f..21cedae30 100644 --- a/Sources/Shared/UnfairLock.swift +++ b/Sources/Shared/UnfairLock.swift @@ -9,12 +9,14 @@ public final class UnfairLock { private var _osAllocatedUnfairLock: Any? private var osAllocatedUnfairLock: OSAllocatedUnfairLock { + // swiftlint:disable:next force_cast _osAllocatedUnfairLock as! OSAllocatedUnfairLock } #else private var _nsLock: Any? private var nsLock: NSLock { + // swiftlint:disable:next force_cast _nsLock as! NSLock } #endif diff --git a/Sources/SourceGraph/Elements/CommentCommand.swift b/Sources/SourceGraph/Elements/CommentCommand.swift index 45f85cef9..6b2e671c7 100644 --- a/Sources/SourceGraph/Elements/CommentCommand.swift +++ b/Sources/SourceGraph/Elements/CommentCommand.swift @@ -4,7 +4,7 @@ public enum CommentCommand: CustomStringConvertible, Hashable { case ignore case ignoreAll case ignoreParameters([String]) - + public var description: String { switch self { case .ignore: diff --git a/Sources/SourceGraph/Elements/Declaration.swift b/Sources/SourceGraph/Elements/Declaration.swift index 4c2e0636a..9ddd4149a 100644 --- a/Sources/SourceGraph/Elements/Declaration.swift +++ b/Sources/SourceGraph/Elements/Declaration.swift @@ -145,7 +145,7 @@ public final class Declaration { } static var discreteConformableKinds: Set { - return [.class, .struct, .enum] + [.class, .struct, .enum] } public var isConcreteTypeDeclarableKind: Bool { @@ -153,7 +153,7 @@ public final class Declaration { } static var concreteTypeDeclarableKinds: Set { - return [.class, .struct, .enum, .typealias] + [.class, .struct, .enum, .typealias] } static var accessorKinds: Set { @@ -257,9 +257,11 @@ public final class Declaration { } public var isComplexProperty: Bool { - return declarations.contains { - if [.functionAccessorWillset, - .functionAccessorDidset].contains($0.kind) { + declarations.contains { + if [ + .functionAccessorWillset, + .functionAccessorDidset + ].contains($0.kind) { return true } @@ -287,7 +289,7 @@ public final class Declaration { } func isDeclaredInExtension(kind: Declaration.Kind) -> Bool { - guard let parent = parent else { return false } + guard let parent else { return false } return parent.kind == kind } } @@ -316,15 +318,17 @@ extension Declaration: CustomStringConvertible { let formattedCommentCommands = "[" + commentCommands.map { $0.description }.sorted().joined(separator: ", ") + "]" let formattedUsrs = "[" + usrs.sorted().joined(separator: ", ") + "]" let implicitOrExplicit = isImplicit ? "implicit" : "explicit" - return [kind.rawValue, - formattedName, - implicitOrExplicit, - accessibility.value.rawValue, - formattedModifiers, - formattedAttributes, - formattedCommentCommands, - formattedUsrs, - location.shortDescription] + return [ + kind.rawValue, + formattedName, + implicitOrExplicit, + accessibility.value.rawValue, + formattedModifiers, + formattedAttributes, + formattedCommentCommands, + formattedUsrs, + location.shortDescription + ] } } diff --git a/Sources/SourceGraph/Elements/SourceLocation.swift b/Sources/SourceGraph/Elements/Location.swift similarity index 96% rename from Sources/SourceGraph/Elements/SourceLocation.swift rename to Sources/SourceGraph/Elements/Location.swift index fa8f5c60f..4ac23dad4 100644 --- a/Sources/SourceGraph/Elements/SourceLocation.swift +++ b/Sources/SourceGraph/Elements/Location.swift @@ -51,11 +51,11 @@ extension Location: Hashable { extension Location: CustomStringConvertible { public var description: String { - return descriptionInternal + descriptionInternal } public var shortDescription: String { - return shortDescriptionInternal + shortDescriptionInternal } } diff --git a/Sources/SourceGraph/Mutators/DefaultConstructorReferenceBuilder.swift b/Sources/SourceGraph/Mutators/DefaultConstructorReferenceBuilder.swift index 3ca9313ef..4466c371f 100644 --- a/Sources/SourceGraph/Mutators/DefaultConstructorReferenceBuilder.swift +++ b/Sources/SourceGraph/Mutators/DefaultConstructorReferenceBuilder.swift @@ -19,7 +19,7 @@ final class DefaultConstructorReferenceBuilder: SourceGraphMutator { let defaultConstructors = graph.declarations(ofKind: .functionConstructor).filter { // Some initializers are referenced internally, e.g by JSONEncoder/Decoder so we need // to assume they are referenced. - $0.name == "init()" || $0.isImplicit + $0.name == "init()" || $0.isImplicit } defaultConstructors.forEach { constructor in diff --git a/Sources/SourceGraph/Mutators/EntryPointAttributeRetainer.swift b/Sources/SourceGraph/Mutators/EntryPointAttributeRetainer.swift index 981ea1b39..835717439 100644 --- a/Sources/SourceGraph/Mutators/EntryPointAttributeRetainer.swift +++ b/Sources/SourceGraph/Mutators/EntryPointAttributeRetainer.swift @@ -28,7 +28,7 @@ final class EntryPointAttributeRetainer: SourceGraphMutator { if $0.attributes.contains("main") { // @main requires a static main() function. $0.declarations - .filter { $0.kind == .functionMethodStatic && $0.name == "main()"} + .filter { $0.kind == .functionMethodStatic && $0.name == "main()" } .forEach { graph.markRetained($0) } } } diff --git a/Sources/SourceGraph/Mutators/ExternalTypeProtocolConformanceReferenceRemover.swift b/Sources/SourceGraph/Mutators/ExternalTypeProtocolConformanceReferenceRemover.swift index b7720b0ad..7db00498b 100644 --- a/Sources/SourceGraph/Mutators/ExternalTypeProtocolConformanceReferenceRemover.swift +++ b/Sources/SourceGraph/Mutators/ExternalTypeProtocolConformanceReferenceRemover.swift @@ -1,6 +1,7 @@ import Foundation import Shared +// swiftlint:disable:next type_name final class ExternalTypeProtocolConformanceReferenceRemover: SourceGraphMutator { private let graph: SourceGraph diff --git a/Sources/SourceGraph/Mutators/GenericClassAndStructConstructorReferenceBuilder.swift b/Sources/SourceGraph/Mutators/GenericClassAndStructConstructorReferenceBuilder.swift index cf60875d9..be1baa8fb 100644 --- a/Sources/SourceGraph/Mutators/GenericClassAndStructConstructorReferenceBuilder.swift +++ b/Sources/SourceGraph/Mutators/GenericClassAndStructConstructorReferenceBuilder.swift @@ -5,6 +5,8 @@ import Shared /// Constructors on a class/struct with generic type parameters are not referenced despite being used. /// We therefore must reference the constructor from the class/struct. final class GenericClassAndStructConstructorReferenceBuilder: SourceGraphMutator { + // swiftlint:disable:previous type_name + private let graph: SourceGraph required init(graph: SourceGraph, configuration: Configuration) { diff --git a/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift b/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift index 3af7a38c4..ede3f04a7 100644 --- a/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift +++ b/Sources/SourceGraph/Mutators/ProtocolConformanceReferenceBuilder.swift @@ -53,7 +53,7 @@ final class ProtocolConformanceReferenceBuilder: SourceGraphMutator { $0.name == unimplementedProtoDecl.name } - if let declInSuperclass = declInSuperclass { + if let declInSuperclass { // Build a reference from the protocol declarations to the // declaration implemented by the superclass. for usr in declInSuperclass.usrs { diff --git a/Sources/SourceGraph/Mutators/RedundantExplicitPublicAccessibilityMarker.swift b/Sources/SourceGraph/Mutators/RedundantExplicitPublicAccessibilityMarker.swift index 7fb4a4f2b..086ec79a4 100644 --- a/Sources/SourceGraph/Mutators/RedundantExplicitPublicAccessibilityMarker.swift +++ b/Sources/SourceGraph/Mutators/RedundantExplicitPublicAccessibilityMarker.swift @@ -1,5 +1,6 @@ import Shared +// swiftlint:disable:next type_name final class RedundantExplicitPublicAccessibilityMarker: SourceGraphMutator { private let graph: SourceGraph private let configuration: Configuration @@ -37,8 +38,7 @@ final class RedundantExplicitPublicAccessibilityMarker: SourceGraphMutator { if !graph.isRetained(decl) && !isReferencedCrossModule(decl) && !isExposedPubliclyByAnotherDeclaration(decl) && - !isProtocolIndirectlyReferencedCrossModuleByExtensionMember(decl) - { + !isProtocolIndirectlyReferencedCrossModuleByExtensionMember(decl) { // Public accessibility is redundant. mark(decl) markExplicitPublicDescendentDeclarations(from: decl) @@ -164,7 +164,7 @@ final class RedundantExplicitPublicAccessibilityMarker: SourceGraphMutator { private func nonTestableModulesReferencing(_ decl: Declaration) -> Set { let referenceFiles = graph.references(to: decl).map { $0.location.file } - let referenceModules = referenceFiles.flatMapSet { file -> Set in + return referenceFiles.flatMapSet { file -> Set in let importsDeclModuleTestable = file.importStatements.contains(where: { $0.isTestable && decl.location.file.modules.contains($0.module) }) @@ -175,8 +175,6 @@ final class RedundantExplicitPublicAccessibilityMarker: SourceGraphMutator { return [] } - - return referenceModules } private func descendentPublicDeclarations(from decl: Declaration) -> Set { diff --git a/Sources/SourceGraph/Mutators/StringInterpolationAppendInterpolationRetainer.swift b/Sources/SourceGraph/Mutators/StringInterpolationAppendInterpolationRetainer.swift index 9904e26de..9ac1dec64 100644 --- a/Sources/SourceGraph/Mutators/StringInterpolationAppendInterpolationRetainer.swift +++ b/Sources/SourceGraph/Mutators/StringInterpolationAppendInterpolationRetainer.swift @@ -4,6 +4,7 @@ import Shared // https://github.com/apple/swift/issues/56189 // The index store does not contain references to `appendInterpolation` functions from their use in string literals. final class StringInterpolationAppendInterpolationRetainer: SourceGraphMutator { + // swiftlint:disable:previous type_name private let graph: SourceGraph required init(graph: SourceGraph, configuration: Configuration) { diff --git a/Sources/SourceGraph/Mutators/StructImplicitInitializerReferenceBuilder.swift b/Sources/SourceGraph/Mutators/StructImplicitInitializerReferenceBuilder.swift index a9681b9ce..365e9ca6d 100644 --- a/Sources/SourceGraph/Mutators/StructImplicitInitializerReferenceBuilder.swift +++ b/Sources/SourceGraph/Mutators/StructImplicitInitializerReferenceBuilder.swift @@ -3,6 +3,7 @@ import Shared /// Builds references from struct implicit initializers to the properties it assigns. final class StructImplicitInitializerReferenceBuilder: SourceGraphMutator { + // swiftlint:disable:previous type_name private let graph: SourceGraph init(graph: SourceGraph, configuration: Configuration) { diff --git a/Sources/SourceGraph/SourceGraph.swift b/Sources/SourceGraph/SourceGraph.swift index c17fe43bc..f7b4a3120 100644 --- a/Sources/SourceGraph/SourceGraph.swift +++ b/Sources/SourceGraph/SourceGraph.swift @@ -253,7 +253,7 @@ public final class SourceGraph { // Recursively check if the module is exported transitively. return exportingModules.contains { nestedExportingModule in - return isModuleUnsafe(nestedExportingModule, exportedBy: exportingModule) && + isModuleUnsafe(nestedExportingModule, exportedBy: exportingModule) && isModuleUnsafe(module, exportedBy: nestedExportingModule) } } @@ -344,7 +344,7 @@ public final class SourceGraph { .compactMap { $0.parent } .first - guard let baseDecl = baseDecl else { + guard let baseDecl else { // Base reference is external, return the current function as it's the closest. return (decl, false) } diff --git a/Sources/SyntaxAnalysis/DeclarationSyntaxVisitor.swift b/Sources/SyntaxAnalysis/DeclarationSyntaxVisitor.swift index 5690b84b1..36f177e18 100644 --- a/Sources/SyntaxAnalysis/DeclarationSyntaxVisitor.swift +++ b/Sources/SyntaxAnalysis/DeclarationSyntaxVisitor.swift @@ -1,8 +1,9 @@ import Foundation -import SwiftSyntax import SourceGraph +import SwiftSyntax public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { + // swiftlint:disable:next large_tuple public typealias Result = ( location: Location, accessibility: Accessibility?, @@ -29,7 +30,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { private var didVisitCapitalSelfFunctionCall: Bool = false public var resultsByLocation: [Location: Result] { - results.reduce(into: [Location: Result]()) { (dict, result) in + results.reduce(into: [Location: Result]()) { dict, result in dict[result.location] = result } } @@ -217,9 +218,11 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } func visitVariableTupleBinding(node: VariableDeclSyntax, pattern: TuplePatternSyntax, typeTuple: TupleTypeElementListSyntax?, initializerTuple: LabeledExprListSyntax?) { - let elements = pattern.elements.map { $0 } + let elements = Array(pattern.elements) + // swiftlint:disable array_init let types: [TupleTypeElementSyntax?] = typeTuple?.map { $0 } ?? Array(repeating: nil, count: elements.count) let initializers: [LabeledExprSyntax?] = initializerTuple?.map { $0 } ?? Array(repeating: nil, count: elements.count) + // swiftlint:enable array_init for (element, (type, initializer)) in zip(elements, zip(types, initializers)) { if let elementTuplePattern = element.pattern.as(TuplePatternSyntax.self) { @@ -294,6 +297,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { // MARK: - Private + // swiftlint:disable:next function_default_parameter_at_end private func parse( modifiers: DeclModifierListSyntax?, attributes: AttributeListSyntax?, @@ -377,8 +381,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { .contains { if let baseTypeName = $0.as(MetatypeTypeSyntax.self)?.baseType.trimmedDescription, genericParameterNames.contains(baseTypeName), - returnClauseTypeLocations.contains(where: { $0.name == baseTypeName }) - { + returnClauseTypeLocations.contains(where: { $0.name == baseTypeName }) { return true } @@ -387,17 +390,17 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func type(for typeSyntax: TypeSyntax?) -> String? { - guard let typeSyntax = typeSyntax else { return nil } + guard let typeSyntax else { return nil } return typeSyntaxInspector.type(for: typeSyntax) } private func typeLocations(for typeSyntax: TypeSyntax?) -> Set { - guard let typeSyntax = typeSyntax else { return [] } + guard let typeSyntax else { return [] } return typeSyntaxInspector.typeLocations(for: typeSyntax) } private func typeLocations(for clause: FunctionParameterClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.parameters.reduce(into: .init(), { result, param in result.formUnion(typeSyntaxInspector.typeLocations(for: param.type)) @@ -421,7 +424,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: ClosureParameterClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.parameters.reduce(into: .init(), { result, param in if let type = param.type { @@ -431,7 +434,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: EnumCaseParameterClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.parameters.reduce(into: .init(), { result, param in result.formUnion(typeSyntaxInspector.typeLocations(for: param.type)) @@ -449,7 +452,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: GenericParameterClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.parameters.reduce(into: .init()) { result, param in if let inheritedType = param.inheritedType { @@ -459,7 +462,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: GenericArgumentClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.arguments.reduce(into: .init()) { result, param in result.formUnion(typeSyntaxInspector.typeLocations(for: param.argument)) @@ -467,7 +470,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: GenericWhereClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.requirements.reduce(into: .init()) { result, requirement in if let conformanceRequirementType = requirement.requirement.as(ConformanceRequirementSyntax.self) { @@ -477,7 +480,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func typeLocations(for clause: InheritanceClauseSyntax?) -> Set { - guard let clause = clause else { return [] } + guard let clause else { return [] } return clause.inheritedTypes.reduce(into: .init()) { result, type in result.formUnion(typeSyntaxInspector.typeLocations(for: type.type)) @@ -485,7 +488,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { } private func locations(for call: FunctionCallExprSyntax?) -> Set { - guard let call = call else { return [] } + guard let call else { return [] } var locations = Set([sourceLocationBuilder.location(at: call.positionAfterSkippingLeadingTrivia)]) @@ -504,8 +507,7 @@ public final class DeclarationSyntaxVisitor: PeripherySyntaxVisitor { .reduce(into: .init(), { result, argument in if let memberExpr = argument.expression.as(MemberAccessExprSyntax.self), memberExpr.declName.baseName.tokenKind == .keyword(.`self`), - let baseIdentifier = memberExpr.base?.as(DeclReferenceExprSyntax.self) - { + let baseIdentifier = memberExpr.base?.as(DeclReferenceExprSyntax.self) { let location = sourceLocationBuilder.location(at: baseIdentifier.positionAfterSkippingLeadingTrivia) result.insert(location) } diff --git a/Sources/SyntaxAnalysis/MultiplexingSyntaxVisitor.swift b/Sources/SyntaxAnalysis/MultiplexingSyntaxVisitor.swift index 1c947dc51..722aeb612 100644 --- a/Sources/SyntaxAnalysis/MultiplexingSyntaxVisitor.swift +++ b/Sources/SyntaxAnalysis/MultiplexingSyntaxVisitor.swift @@ -1,8 +1,8 @@ import Foundation -import SystemPackage -import SwiftSyntax -import SwiftParser import SourceGraph +import SwiftParser +import SwiftSyntax +import SystemPackage public protocol PeripherySyntaxVisitor { init(sourceLocationBuilder: SourceLocationBuilder) @@ -48,6 +48,7 @@ public protocol PeripherySyntaxVisitor { func visitPost(_ node: FunctionCallExprSyntax) } +// swiftlint:disable:next extension_access_modifier extension PeripherySyntaxVisitor { public func visit(_ node: ActorDeclSyntax) { } public func visit(_ node: ClassDeclSyntax) { } @@ -116,179 +117,179 @@ public final class MultiplexingSyntaxVisitor: SyntaxVisitor { public func visit() { walk(syntax) } - + public func parseComments() -> [CommentCommand] { CommentCommand.parseCommands(in: syntax.leadingTrivia) } - public override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: EnumCaseDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: EnumCaseDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: SubscriptDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: SubscriptDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: AssociatedTypeDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: AssociatedTypeDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: OperatorDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: OperatorDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: PrecedenceGroupDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: PrecedenceGroupDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: ImportDeclSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: ImportDeclSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: OptionalBindingConditionSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: OptionalBindingConditionSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind { + override public func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind { visitors.forEach { $0.visit(node) } return .visitChildren } - public override func visitPost(_ node: ActorDeclSyntax) { + override public func visitPost(_ node: ActorDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: ClassDeclSyntax) { + override public func visitPost(_ node: ClassDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: ProtocolDeclSyntax) { + override public func visitPost(_ node: ProtocolDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: StructDeclSyntax) { + override public func visitPost(_ node: StructDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: EnumDeclSyntax) { + override public func visitPost(_ node: EnumDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: EnumCaseDeclSyntax) { + override public func visitPost(_ node: EnumCaseDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: ExtensionDeclSyntax) { + override public func visitPost(_ node: ExtensionDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: FunctionDeclSyntax) { + override public func visitPost(_ node: FunctionDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: InitializerDeclSyntax) { + override public func visitPost(_ node: InitializerDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: DeinitializerDeclSyntax) { + override public func visitPost(_ node: DeinitializerDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: SubscriptDeclSyntax) { + override public func visitPost(_ node: SubscriptDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: VariableDeclSyntax) { + override public func visitPost(_ node: VariableDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: TypeAliasDeclSyntax) { + override public func visitPost(_ node: TypeAliasDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: AssociatedTypeDeclSyntax) { + override public func visitPost(_ node: AssociatedTypeDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: OperatorDeclSyntax) { + override public func visitPost(_ node: OperatorDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: PrecedenceGroupDeclSyntax) { + override public func visitPost(_ node: PrecedenceGroupDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: ImportDeclSyntax) { + override public func visitPost(_ node: ImportDeclSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: OptionalBindingConditionSyntax) { + override public func visitPost(_ node: OptionalBindingConditionSyntax) { visitors.forEach { $0.visitPost(node) } } - public override func visitPost(_ node: FunctionCallExprSyntax) { + override public func visitPost(_ node: FunctionCallExprSyntax) { visitors.forEach { $0.visitPost(node) } } } diff --git a/Sources/SyntaxAnalysis/SourceLocationBuilder.swift b/Sources/SyntaxAnalysis/SourceLocationBuilder.swift index d47d4de21..e4b7f96e4 100644 --- a/Sources/SyntaxAnalysis/SourceLocationBuilder.swift +++ b/Sources/SyntaxAnalysis/SourceLocationBuilder.swift @@ -1,5 +1,5 @@ -import SwiftSyntax import SourceGraph +import SwiftSyntax public final class SourceLocationBuilder { private let file: SourceFile @@ -13,7 +13,7 @@ public final class SourceLocationBuilder { public func location(at position: AbsolutePosition) -> Location { let location = locationConverter.location(for: position) return Location(file: file, - line: location.line, - column: location.column) + line: location.line, + column: location.column) } } diff --git a/Sources/SyntaxAnalysis/TypeSyntaxInspector.swift b/Sources/SyntaxAnalysis/TypeSyntaxInspector.swift index 19426b1c7..0095218e3 100644 --- a/Sources/SyntaxAnalysis/TypeSyntaxInspector.swift +++ b/Sources/SyntaxAnalysis/TypeSyntaxInspector.swift @@ -1,7 +1,7 @@ import Foundation -import SwiftSyntax -import SourceGraph import Shared +import SourceGraph +import SwiftSyntax struct TypeNameSourceLocation: Hashable { let name: String diff --git a/Sources/SyntaxAnalysis/UnusedParameterAnalyzer.swift b/Sources/SyntaxAnalysis/UnusedParameterAnalyzer.swift index 454fa6371..badaf7dd4 100644 --- a/Sources/SyntaxAnalysis/UnusedParameterAnalyzer.swift +++ b/Sources/SyntaxAnalysis/UnusedParameterAnalyzer.swift @@ -1,7 +1,7 @@ import Foundation +import SourceGraph import SwiftSyntax import SystemPackage -import SourceGraph public final class UnusedParameterAnalyzer { private enum UsageType { @@ -9,7 +9,7 @@ public final class UnusedParameterAnalyzer { case unused case shadowed } - + public init() { } public func analyze(file: SourceFile, syntax: SourceFileSyntax, locationConverter: SourceLocationConverter, parseProtocols: Bool) -> [Function: Set] { @@ -19,7 +19,7 @@ public final class UnusedParameterAnalyzer { locationConverter: locationConverter, parseProtocols: parseProtocols) - return functions.reduce(into: [Function: Set]()) { (result, function) in + return functions.reduce(into: [Function: Set]()) { result, function in let params = analyze(function: function) if !params.isEmpty { @@ -29,7 +29,7 @@ public final class UnusedParameterAnalyzer { } func analyze(function: Function) -> Set { - return Set(unusedParams(in: function)) + Set(unusedParams(in: function)) } // MARK: - Private diff --git a/Sources/SyntaxAnalysis/UnusedParameterParser.swift b/Sources/SyntaxAnalysis/UnusedParameterParser.swift index baebca498..c2ecd10ed 100644 --- a/Sources/SyntaxAnalysis/UnusedParameterParser.swift +++ b/Sources/SyntaxAnalysis/UnusedParameterParser.swift @@ -1,8 +1,8 @@ import Foundation -import SystemPackage -import SwiftSyntax -import SwiftParser import SourceGraph +import SwiftParser +import SwiftSyntax +import SystemPackage public protocol Item: AnyObject { var items: [Item] { get } @@ -46,7 +46,7 @@ public final class Function: Item, Hashable { public final class Parameter: Item, Hashable { public static func == (lhs: Parameter, rhs: Parameter) -> Bool { - return lhs.location == rhs.location + lhs.location == rhs.location } public func hash(into hasher: inout Hasher) { @@ -61,7 +61,7 @@ public final class Parameter: Item, Hashable { var function: Function? public var name: String { - return secondName ?? firstName ?? "" + secondName ?? firstName ?? "" } public func makeDeclaration(withParent parent: Declaration) -> Declaration { @@ -162,17 +162,17 @@ struct UnusedParameterParser { } func parse() -> [Function] { - return parse(node: syntax, collecting: Function.self) + parse(node: syntax, collecting: Function.self) } // MARK: - Private private func parse(node: SyntaxProtocol, collecting: T.Type) -> [T] { - return parse(children: node.children(viewMode: .sourceAccurate), collecting: collecting) + parse(children: node.children(viewMode: .sourceAccurate), collecting: collecting) } private func parse(children: SyntaxChildren, collecting: T.Type) -> [T] { - return parse(nodes: Array(children), collecting: collecting) + parse(nodes: Array(children), collecting: collecting) } private func parse(nodes: [Syntax], collecting: T.Type) -> [T] { @@ -210,7 +210,7 @@ struct UnusedParameterParser { if optBindingCondition.initializer == nil, let pattern = optBindingCondition.pattern.as(IdentifierPatternSyntax.self), let parentStmt = optBindingCondition.parent?.parent?.parent, - (parentStmt.is(IfExprSyntax.self) || parentStmt.is(GuardStmtSyntax.self)) { + parentStmt.is(IfExprSyntax.self) || parentStmt.is(GuardStmtSyntax.self) { // Handle `let x {}` syntax. parsed = parse(identifier: pattern.identifier) } else { @@ -220,7 +220,7 @@ struct UnusedParameterParser { parsed = parse(childrenFrom: node, collector) } - if let collector = collector, let parsed = parsed { + if let collector, let parsed { collector.add(parsed) } @@ -229,7 +229,7 @@ struct UnusedParameterParser { private func parse(childrenFrom node: Syntax, _ collector: Collector?) -> Item? { let items = node.children(viewMode: .sourceAccurate).compactMap { parse(node: $0, collector) } - if items.count > 0 { + if !items.isEmpty { return GenericItem(node: node, items: items) } return nil @@ -301,25 +301,26 @@ struct UnusedParameterParser { } private func parse(functionDecl syntax: FunctionDeclSyntax, _ collector: Collector?) -> Item? { - return build(function: syntax.signature, - attributes: syntax.attributes, - genericParams: syntax.genericParameterClause, - body: syntax.body, - named: syntax.name.text, - position: syntax.name.positionAfterSkippingLeadingTrivia, - collector) + build(function: syntax.signature, + attributes: syntax.attributes, + genericParams: syntax.genericParameterClause, + body: syntax.body, + named: syntax.name.text, + position: syntax.name.positionAfterSkippingLeadingTrivia, + collector) } private func parse(initializerDecl syntax: InitializerDeclSyntax, _ collector: Collector?) -> Item? { - return build(function: syntax.signature, - attributes: syntax.attributes, - genericParams: syntax.genericParameterClause, - body: syntax.body, - named: "init", - position: syntax.initKeyword.positionAfterSkippingLeadingTrivia, - collector) + build(function: syntax.signature, + attributes: syntax.attributes, + genericParams: syntax.genericParameterClause, + body: syntax.body, + named: "init", + position: syntax.initKeyword.positionAfterSkippingLeadingTrivia, + collector) } + // swiftlint:disable:next function_parameter_count private func build( function syntax: SyntaxProtocol, attributes: AttributeListSyntax?, @@ -364,8 +365,8 @@ struct UnusedParameterParser { private func sourceLocation(of position: AbsolutePosition) -> Location { let location = locationConverter.location(for: position) return Location(file: file, - line: location.line, - column: location.column) + line: location.line, + column: location.column) } } diff --git a/Sources/XcodeSupport/XcodeProject.swift b/Sources/XcodeSupport/XcodeProject.swift index c2b430cc1..a8946e72d 100644 --- a/Sources/XcodeSupport/XcodeProject.swift +++ b/Sources/XcodeSupport/XcodeProject.swift @@ -1,8 +1,8 @@ import Foundation -import XcodeProj -import SystemPackage import PeripheryKit import Shared +import SystemPackage +import XcodeProj final class XcodeProject: XcodeProjectlike { private static var cache: [FilePath: XcodeProject] = [:] @@ -105,6 +105,6 @@ extension XcodeProject: Hashable { extension XcodeProject: Equatable { static func == (lhs: XcodeProject, rhs: XcodeProject) -> Bool { - return lhs.path == rhs.path + lhs.path == rhs.path } } diff --git a/Sources/XcodeSupport/XcodeProjectDriver.swift b/Sources/XcodeSupport/XcodeProjectDriver.swift index cdf16e161..b74b22c2b 100644 --- a/Sources/XcodeSupport/XcodeProjectDriver.swift +++ b/Sources/XcodeSupport/XcodeProjectDriver.swift @@ -1,9 +1,9 @@ import Foundation -import SystemPackage +import Indexer import PeripheryKit import Shared import SourceGraph -import Indexer +import SystemPackage public final class XcodeProjectDriver { public static func build() throws -> Self { @@ -39,7 +39,7 @@ public final class XcodeProjectDriver { invalidTargetNames.append(targetName) continue } - + if let target = project.packageTargets[package]?.first(where: { $0.name == packageTargetName }) { packageTargets[package, default: []].insert(target) } else if let subTarget = package.targets.first(where: { $0.name == packageTargetName }) { @@ -86,6 +86,7 @@ public final class XcodeProjectDriver { private let targets: Set private let packageTargets: [SPM.Package: Set] + // swiftlint:disable:next function_default_parameter_at_end init( logger: Logger = .init(), configuration: Configuration = .shared, @@ -179,7 +180,8 @@ extension XcodeProjectDriver: ProjectDriver { target.sourcePaths.forEach { let absolutePath = packageRoot.pushing($0) let indexTarget = IndexTarget(name: target.name) - sourceFiles[absolutePath, default: []].insert(indexTarget) } + sourceFiles[absolutePath, default: []].insert(indexTarget) + } } } diff --git a/Sources/XcodeSupport/XcodeProjectSetupGuide.swift b/Sources/XcodeSupport/XcodeProjectSetupGuide.swift index 089ff3a1a..8c914f70b 100644 --- a/Sources/XcodeSupport/XcodeProjectSetupGuide.swift +++ b/Sources/XcodeSupport/XcodeProjectSetupGuide.swift @@ -1,6 +1,6 @@ import Foundation -import SystemPackage import Shared +import SystemPackage public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide { private let configuration: Configuration @@ -13,7 +13,7 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide } public var projectKind: ProjectKind { - return .xcode + .xcode } public var isSupported: Bool { @@ -29,13 +29,13 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide project = try XcodeProject(path: projectPath) } - if let project = project { + if let project { guard !project.targets.isEmpty else { throw PeripheryError.guidedSetupError(message: "Failed to identify any targets in \(project.path.lastComponent?.string ?? "")") } var targets = project.targets.map { $0.name } - targets += project.packageTargets.flatMap { (package, targets) in + targets += project.packageTargets.flatMap { package, _ in package.targets.map { "\(package.name).\($0.name)" } } targets = targets.sorted() @@ -43,10 +43,10 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide print(colorize("Select build targets to analyze:", .bold)) configuration.targets = select(multiple: targets, allowAll: true).selectedValues - let schemes = try filter( + let schemes = Array(try filter( project.schemes(additionalArguments: configuration.xcodeListArguments), project - ).map { $0 }.sorted() + )).sorted() print(colorize("\nSelect the schemes necessary to build your chosen targets:", .bold)) configuration.schemes = select(multiple: schemes, allowAll: false).selectedValues @@ -113,7 +113,7 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide workspacePath = paths.first } - if let workspacePath = workspacePath { + if let workspacePath { configuration.workspace = workspacePath.relativeTo(.current).string return workspacePath } @@ -142,7 +142,7 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide projectPath = paths.first } - if let projectPath = projectPath { + if let projectPath { configuration.project = projectPath.relativeTo(.current).string return projectPath } diff --git a/Sources/XcodeSupport/XcodeProjectlike.swift b/Sources/XcodeSupport/XcodeProjectlike.swift index 34fa31537..d253e5018 100644 --- a/Sources/XcodeSupport/XcodeProjectlike.swift +++ b/Sources/XcodeSupport/XcodeProjectlike.swift @@ -1,6 +1,6 @@ import Foundation -import SystemPackage import PeripheryKit +import SystemPackage protocol XcodeProjectlike: AnyObject { var path: FilePath { get } @@ -15,6 +15,6 @@ protocol XcodeProjectlike: AnyObject { extension XcodeProjectlike { var name: String { - return path.lastComponent?.stem ?? "" + path.lastComponent?.stem ?? "" } } diff --git a/Sources/XcodeSupport/XcodeTarget.swift b/Sources/XcodeSupport/XcodeTarget.swift index ec4d049a2..6d1cdb7c9 100644 --- a/Sources/XcodeSupport/XcodeTarget.swift +++ b/Sources/XcodeSupport/XcodeTarget.swift @@ -1,7 +1,7 @@ import Foundation -import XcodeProj -import SystemPackage import SourceGraph +import SystemPackage +import XcodeProj final class XcodeTarget { let project: XcodeProject @@ -87,6 +87,6 @@ extension XcodeTarget: Hashable { extension XcodeTarget: Equatable { static func == (lhs: XcodeTarget, rhs: XcodeTarget) -> Bool { - return lhs.name == rhs.name + lhs.name == rhs.name } } diff --git a/Sources/XcodeSupport/XcodeWorkspace.swift b/Sources/XcodeSupport/XcodeWorkspace.swift index 940e37a6a..13bfde94c 100644 --- a/Sources/XcodeSupport/XcodeWorkspace.swift +++ b/Sources/XcodeSupport/XcodeWorkspace.swift @@ -1,8 +1,8 @@ import Foundation -import XcodeProj -import SystemPackage import PeripheryKit import Shared +import SystemPackage +import XcodeProj final class XcodeWorkspace: XcodeProjectlike { let type: String = "workspace" diff --git a/Sources/XcodeSupport/Xcodebuild.swift b/Sources/XcodeSupport/Xcodebuild.swift index 1c2bc02c2..7b3ec02a5 100644 --- a/Sources/XcodeSupport/Xcodebuild.swift +++ b/Sources/XcodeSupport/Xcodebuild.swift @@ -1,6 +1,6 @@ import Foundation -import SystemPackage import Shared +import SystemPackage public final class Xcodebuild { private let shell: Shell @@ -97,6 +97,7 @@ public final class Xcodebuild { // MARK: - Private + // swiftlint:disable:next discouraged_optional_collection private func deserialize(_ jsonString: String) throws -> [String: Any]? { do { guard let jsonData = jsonString.data(using: .utf8) else { return nil } @@ -114,7 +115,7 @@ public final class Xcodebuild { let xcodeVersionHash = try version().djb2Hex let projectHash = project.name.djb2Hex - let schemesHash = schemes.map { $0 }.joined().djb2Hex + let schemesHash = Array(schemes).joined().djb2Hex return try Constants.cachePath().appending("DerivedData-\(xcodeVersionHash)-\(projectHash)-\(schemesHash)") } @@ -127,8 +128,7 @@ public final class Xcodebuild { let value = arguments[safe: i + 1], !value.hasPrefix("-"), !value.hasPrefix("\""), - !value.hasPrefix("\'") - { + !value.hasPrefix("\'") { quotedArguments[i + 1] = "\"\(value)\"" } } diff --git a/Tests/AccessibilityTests/Helper.swift b/Tests/AccessibilityTests/Helper.swift index ea27252bf..c202eaba1 100644 --- a/Tests/AccessibilityTests/Helper.swift +++ b/Tests/AccessibilityTests/Helper.swift @@ -3,5 +3,5 @@ import SystemPackage @testable import TestShared var AccessibilityProjectPath: FilePath { - return ProjectRootPath.appending("Tests/AccessibilityTests/AccessibilityProject") + ProjectRootPath.appending("Tests/AccessibilityTests/AccessibilityProject") } diff --git a/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift b/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift index 578f8e48d..d94e02287 100644 --- a/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift +++ b/Tests/AccessibilityTests/RedundantPublicAccessibilityTest.swift @@ -1,8 +1,9 @@ -import XCTest -@testable import TestShared @testable import PeripheryKit +@testable import TestShared +import XCTest -class RedundantPublicAccessibilityTest: SourceGraphTestCase { +// swiftlint:disable:next balanced_xctest_lifecycle +final class RedundantPublicAccessibilityTest: SourceGraphTestCase { override static func setUp() { super.setUp() diff --git a/Tests/PeripheryTests/CrossModuleRetentionTest.swift b/Tests/PeripheryTests/CrossModuleRetentionTest.swift index e79be95b2..de0ed28fe 100644 --- a/Tests/PeripheryTests/CrossModuleRetentionTest.swift +++ b/Tests/PeripheryTests/CrossModuleRetentionTest.swift @@ -1,10 +1,11 @@ -import XCTest +@testable import PeripheryKit import SystemPackage @testable import TestShared -@testable import PeripheryKit +import XCTest +// swiftlint:disable:next balanced_xctest_lifecycle final class CrossModuleRetentionTest: SourceGraphTestCase { - static override func setUp() { + override static func setUp() { super.setUp() configuration.targets = ["CrossModuleRetentionFixtures", "CrossModuleRetentionSupportFixtures"] diff --git a/Tests/PeripheryTests/Extensions/FilePathGlobTest.swift b/Tests/PeripheryTests/Extensions/FilePathGlobTest.swift index db9bf3daf..a3d5d3462 100644 --- a/Tests/PeripheryTests/Extensions/FilePathGlobTest.swift +++ b/Tests/PeripheryTests/Extensions/FilePathGlobTest.swift @@ -1,8 +1,8 @@ -import XCTest -import SystemPackage import Shared +import SystemPackage +import XCTest -class FilePathGlobTest: XCTestCase { +final class FilePathGlobTest: XCTestCase { private let files = ["foo", "bar", "baz", "dir1/file1.ext", "dir1/dir2/dir3/file2.ext"] private let baseDir = FilePath.current.appending("tmp/FilePathGlobTest").string private let fileManager = FileManager.default @@ -91,7 +91,7 @@ class FilePathGlobTest: XCTestCase { } func testRelative() { - FilePath(baseDir).chdir() { + FilePath(baseDir).chdir { let pattern = "**/*.ext" let paths = FilePath.glob(pattern).sorted() XCTAssertPathsEqual(paths, [ @@ -102,7 +102,7 @@ class FilePathGlobTest: XCTestCase { } func testRelativeParent() { - FilePath("\(baseDir)/dir1").chdir() { + FilePath("\(baseDir)/dir1").chdir { let pattern = "../bar" let paths = FilePath.glob(pattern).sorted() XCTAssertPathsEqual(paths, [ @@ -110,7 +110,7 @@ class FilePathGlobTest: XCTestCase { ]) } - FilePath("\(baseDir)/dir1/dir2").chdir() { + FilePath("\(baseDir)/dir1/dir2").chdir { let pattern = "../../**/*.ext" let paths = FilePath.glob(pattern).sorted() XCTAssertPathsEqual(paths, [ diff --git a/Tests/PeripheryTests/Extensions/FilePathTest.swift b/Tests/PeripheryTests/Extensions/FilePathTest.swift index de009a7ea..fbac71706 100644 --- a/Tests/PeripheryTests/Extensions/FilePathTest.swift +++ b/Tests/PeripheryTests/Extensions/FilePathTest.swift @@ -1,8 +1,8 @@ import Foundation -import XCTest import SystemPackage +import XCTest -class FilePathTest: XCTestCase { +final class FilePathTest: XCTestCase { func testMakeAbsolute() { let current = FilePath("/current") XCTAssertEqual(FilePath.makeAbsolute("/a", relativeTo: current).string, "/a") diff --git a/Tests/PeripheryTests/Extensions/FilenameMatcherTests.swift b/Tests/PeripheryTests/Extensions/FilenameMatcherTests.swift index 6e726d68a..2efc42d06 100644 --- a/Tests/PeripheryTests/Extensions/FilenameMatcherTests.swift +++ b/Tests/PeripheryTests/Extensions/FilenameMatcherTests.swift @@ -1,7 +1,7 @@ +import FilenameMatcher import Foundation import Shared import XCTest -import FilenameMatcher final class FilenameMatcherTests: XCTestCase { func testRelativePatterns() { diff --git a/Tests/PeripheryTests/Extensions/String+VersionTest.swift b/Tests/PeripheryTests/Extensions/String+VersionTest.swift index 78d3e0e98..6f594057d 100644 --- a/Tests/PeripheryTests/Extensions/String+VersionTest.swift +++ b/Tests/PeripheryTests/Extensions/String+VersionTest.swift @@ -1,7 +1,7 @@ import Foundation import XCTest -class StringVersionTest: XCTestCase { +final class StringVersionTest: XCTestCase { func testVersion() { XCTAssertTrue("9.3".isVersion(lessThan: "10.0")) XCTAssertTrue("9.3.1".isVersion(lessThan: "10.0")) diff --git a/Tests/PeripheryTests/ObjcAccessibleRetentionTest.swift b/Tests/PeripheryTests/ObjcAccessibleRetentionTest.swift index 743d32ba7..0f9040735 100644 --- a/Tests/PeripheryTests/ObjcAccessibleRetentionTest.swift +++ b/Tests/PeripheryTests/ObjcAccessibleRetentionTest.swift @@ -1,13 +1,13 @@ -import XCTest +@testable import PeripheryKit import SystemPackage @testable import TestShared -@testable import PeripheryKit +import XCTest -#if os(macOS) +#if os(macOS) // swiftlint:disable:next balanced_xctest_lifecycle final class ObjcAccessibleRetentionTest: FixtureSourceGraphTestCase { let performKnownFailures = false - static override func setUp() { + override static func setUp() { super.setUp() configuration.targets = ["ObjcAccessibleRetentionFixtures"] diff --git a/Tests/PeripheryTests/ObjcAnnotatedRetentionTest.swift b/Tests/PeripheryTests/ObjcAnnotatedRetentionTest.swift index 3fa5e0e7c..a4761bb77 100644 --- a/Tests/PeripheryTests/ObjcAnnotatedRetentionTest.swift +++ b/Tests/PeripheryTests/ObjcAnnotatedRetentionTest.swift @@ -1,11 +1,11 @@ -import XCTest +@testable import PeripheryKit import SystemPackage @testable import TestShared -@testable import PeripheryKit +import XCTest -#if os(macOS) +#if os(macOS) // swiftlint:disable:next balanced_xctest_lifecycle final class ObjcAnnotatedRetentionTest: FixtureSourceGraphTestCase { - static override func setUp() { + override static func setUp() { super.setUp() configuration.targets = ["ObjcAnnotatedRetentionFixtures"] diff --git a/Tests/PeripheryTests/RetentionTest.swift b/Tests/PeripheryTests/RetentionTest.swift index ef32a5517..7c9fa97e0 100644 --- a/Tests/PeripheryTests/RetentionTest.swift +++ b/Tests/PeripheryTests/RetentionTest.swift @@ -1,13 +1,14 @@ -import XCTest -import SystemPackage +@testable import PeripheryKit import Shared +import SystemPackage @testable import TestShared -@testable import PeripheryKit +import XCTest +// swiftlint:disable:next balanced_xctest_lifecycle final class RetentionTest: FixtureSourceGraphTestCase { let performKnownFailures = false - static override func setUp() { + override static func setUp() { super.setUp() configuration.targets = ["RetentionFixtures"] @@ -16,13 +17,13 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testNonReferencedClass() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass1")) } } func testNonReferencedFreeFunction() { - analyze() { + analyze { assertNotReferenced(.functionFree("someFunction()")) } } @@ -53,14 +54,14 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testConformingProtocolReferencedByNonReferencedClass() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass6")) assertNotReferenced(.protocol("FixtureProtocol1")) } } func testSelfReferencedClass() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass8")) } } @@ -90,7 +91,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testSelfReferencedProperty() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass39")) } } @@ -107,7 +108,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testCrossReferencedClasses() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass14")) assertNotReferenced(.class("FixtureClass15")) assertNotReferenced(.class("FixtureClass16")) @@ -115,7 +116,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testDeeplyNestedClassReferences() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass17")) } } @@ -132,7 +133,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testConformanceToExternalProtocolIsRetained() { - analyze() { + analyze { // Retained because it's a method from an external declaration (in this case, Equatable) assertReferenced(.class("FixtureClass55")) { self.assertReferenced(.functionOperatorInfix("==(_:_:)")) @@ -146,9 +147,9 @@ final class RetentionTest: FixtureSourceGraphTestCase { assertReferenced(.protocol("FixtureProtocol114")) assertRedundantProtocol("FixtureProtocol114", implementedBy: - .class("FixtureClass114"), + .class("FixtureClass114"), // swiftlint:disable vertical_parameter_alignment_on_call .class("FixtureClass115"), - .struct("FixtureStruct116")) + .struct("FixtureStruct116")) // swiftlint:enable vertical_parameter_alignment_on_call } } @@ -394,7 +395,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testAccessibility() { - analyze() { + analyze { assertAccessibility(.class("FixtureClass31"), .public) { self.assertAccessibility(.functionConstructor("init(arg:)"), .public) self.assertAccessibility(.functionMethodInstance("openFunc()"), .open) @@ -438,7 +439,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testXCTestCaseClassesAndMethodsAreRetained() { - analyze() { + analyze { assertReferenced(.class("FixtureClass34")) { self.assertReferenced(.functionMethodInstance("testSomething()")) self.assertNotReferenced(.functionMethodInstance("testNotATest(param:)")) @@ -499,7 +500,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testUnusedTypealias() { - analyze() { + analyze { assertNotReferenced(.typealias("UnusedAlias")) } } @@ -605,7 +606,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testRetainsExternalTypeExtension() { - analyze() { + analyze { assertReferenced(.extensionProtocol("Sequence")) assertReferenced(.extensionStruct("Array")) assertReferenced(.extensionClass("NumberFormatter")) @@ -1537,7 +1538,7 @@ final class RetentionTest: FixtureSourceGraphTestCase { } func testIgnoreUnusedParamInUnusedFunction() { - analyze() { + analyze { assertNotReferenced(.class("FixtureClass105")) } } diff --git a/Tests/PeripheryTests/ShellTest.swift b/Tests/PeripheryTests/ShellTest.swift index 8cac5e480..2adc2080f 100644 --- a/Tests/PeripheryTests/ShellTest.swift +++ b/Tests/PeripheryTests/ShellTest.swift @@ -1,5 +1,5 @@ -import XCTest @testable import Shared +import XCTest final class ShellTest: XCTestCase { func testPristineEnvironmentWithPreservedVariables() { diff --git a/Tests/PeripheryTests/SwiftVersionParserTest.swift b/Tests/PeripheryTests/SwiftVersionParserTest.swift index 9c93a110c..3cd722dda 100644 --- a/Tests/PeripheryTests/SwiftVersionParserTest.swift +++ b/Tests/PeripheryTests/SwiftVersionParserTest.swift @@ -1,8 +1,8 @@ import Foundation -import XCTest import Shared +import XCTest -class SwiftVersionParserTest: XCTestCase { +final class SwiftVersionParserTest: XCTestCase { func testParse() throws { let v1 = try SwiftVersionParser.parse("Apple Swift version 5.4 (swiftlang-1205.0.16.12 clang-1205.0.19.6)\nTarget: x86_64-apple-darwin20.2.0") XCTAssertEqual(v1, "5.4") diff --git a/Tests/PeripheryTests/Syntax/FunctionVisitTest.swift b/Tests/PeripheryTests/Syntax/FunctionVisitTest.swift index dc9855c61..293acdbeb 100644 --- a/Tests/PeripheryTests/Syntax/FunctionVisitTest.swift +++ b/Tests/PeripheryTests/Syntax/FunctionVisitTest.swift @@ -1,10 +1,11 @@ import Foundation -import XCTest -@testable import TestShared @testable import SourceGraph @testable import SyntaxAnalysis +@testable import TestShared +import XCTest -class FunctionVisitTest: XCTestCase { +final class FunctionVisitTest: XCTestCase { + // swiftlint:disable:next implicitly_unwrapped_optional private var results: [Location: DeclarationSyntaxVisitor.Result]! override func setUpWithError() throws { @@ -15,6 +16,11 @@ class FunctionVisitTest: XCTestCase { results = visitor.resultsByLocation } + override func tearDown() { + results = nil + super.tearDown() + } + func testFunctionWithSimpleReturnType() throws { let result = results[fixtureLocation(line: 1)] XCTAssertEqual(result?.returnTypeLocations, [fixtureLocation(line: 1, column: 40)]) diff --git a/Tests/PeripheryTests/Syntax/PropertyVisitTest.swift b/Tests/PeripheryTests/Syntax/PropertyVisitTest.swift index f57598160..9b9b2b7a1 100644 --- a/Tests/PeripheryTests/Syntax/PropertyVisitTest.swift +++ b/Tests/PeripheryTests/Syntax/PropertyVisitTest.swift @@ -1,10 +1,11 @@ import Foundation -import XCTest -@testable import TestShared @testable import SourceGraph @testable import SyntaxAnalysis +@testable import TestShared +import XCTest -class PropertyVisitTest: XCTestCase { +final class PropertyVisitTest: XCTestCase { + // swiftlint:disable:next implicitly_unwrapped_optional private var results: [Location: DeclarationSyntaxVisitor.Result]! override func setUpWithError() throws { @@ -15,6 +16,11 @@ class PropertyVisitTest: XCTestCase { results = visitor.resultsByLocation } + override func tearDown() { + results = nil + super.tearDown() + } + func testImplicitType() { let result = results[fixtureLocation(line: 8)]! XCTAssertNil(result.variableType) diff --git a/Tests/PeripheryTests/Syntax/TypeSyntaxInspectorTest.swift b/Tests/PeripheryTests/Syntax/TypeSyntaxInspectorTest.swift index 5131caf37..2e02ac459 100644 --- a/Tests/PeripheryTests/Syntax/TypeSyntaxInspectorTest.swift +++ b/Tests/PeripheryTests/Syntax/TypeSyntaxInspectorTest.swift @@ -1,12 +1,13 @@ import Foundation -import XCTest -import SwiftSyntax -import SwiftParser -@testable import TestShared @testable import SourceGraph +import SwiftParser +import SwiftSyntax @testable import SyntaxAnalysis +@testable import TestShared +import XCTest -class TypeSyntaxInspectorTest: XCTestCase { +final class TypeSyntaxInspectorTest: XCTestCase { + // swiftlint:disable:next implicitly_unwrapped_optional private var results: [Location: TypeSyntaxInspectorTestVisitor.Result]! override func setUpWithError() throws { @@ -16,6 +17,11 @@ class TypeSyntaxInspectorTest: XCTestCase { results = visitor.results } + override func tearDown() { + results = nil + super.tearDown() + } + func testSimpleType() { let simpleType = results[fixtureLocation(line: 3, column: 17)] XCTAssertEqual(simpleType?.type, "String") @@ -130,6 +136,7 @@ private class TypeSyntaxInspectorTestVisitor: SyntaxVisitor { private let typeSyntaxInspector: TypeSyntaxInspector typealias Result = (type: String, locations: [Location]) + var results: [Location: Result] = [:] init(file: SourceFile) throws { diff --git a/Tests/PeripheryTests/Syntax/UnusedParameterTest.swift b/Tests/PeripheryTests/Syntax/UnusedParameterTest.swift index b16d92cab..3a9ab30df 100644 --- a/Tests/PeripheryTests/Syntax/UnusedParameterTest.swift +++ b/Tests/PeripheryTests/Syntax/UnusedParameterTest.swift @@ -1,10 +1,10 @@ import Foundation -import XCTest -@testable import TestShared -@testable import SyntaxAnalysis @testable import SourceGraph +@testable import SyntaxAnalysis +@testable import TestShared +import XCTest -class UnusedParameterTest: XCTestCase { +final class UnusedParameterTest: XCTestCase { func testSimpleUnused() { analyze() assertUnused("param", in: "myFunc(param:)") @@ -69,7 +69,7 @@ class UnusedParameterTest: XCTestCase { func testIgnoreProtocolDeclaration() { analyze() - XCTAssert(functions.count == 0) + XCTAssert(functions.isEmpty) } func testParamForGenericSpecialization() { @@ -215,7 +215,7 @@ class UnusedParameterTest: XCTestCase { private func assertUnused(_ name: String, in functionName: String, file: StaticString = #file, line: UInt = #line) { let function = functions.first { $0.fullName == functionName } - if let function = function { + if let function { assert(function: function, hasParam: name, file: file, line: line) let unused = isUnused(param: name, in: function) XCTAssertTrue(unused, "Param '\(name)' is used in '\(functionName)'.", file: file, line: line) @@ -227,7 +227,7 @@ class UnusedParameterTest: XCTestCase { private func assertUsed(_ name: String, in functionName: String, file: StaticString = #file, line: UInt = #line) { let function = functions.first { $0.fullName == functionName } - if let function = function { + if let function { assert(function: function, hasParam: name, file: file, line: line) let unused = isUnused(param: name, in: function) XCTAssertFalse(unused, "Param '\(name)' is unused in '\(functionName)'.", file: file, line: line) diff --git a/Tests/SPMTests/Helper.swift b/Tests/SPMTests/Helper.swift index 821a28eda..2693cbb39 100644 --- a/Tests/SPMTests/Helper.swift +++ b/Tests/SPMTests/Helper.swift @@ -3,5 +3,5 @@ import SystemPackage @testable import TestShared var SPMProjectPath: FilePath { - return ProjectRootPath.appending("Tests/SPMTests/SPMProject") + ProjectRootPath.appending("Tests/SPMTests/SPMProject") } diff --git a/Tests/SPMTests/SPMProject/Sources/SPMProjectKit/SPMProject.swift b/Tests/SPMTests/SPMProject/Sources/SPMProjectKit/SPMProject.swift index 88e5c2edf..b7d568756 100644 --- a/Tests/SPMTests/SPMProject/Sources/SPMProjectKit/SPMProject.swift +++ b/Tests/SPMTests/SPMProject/Sources/SPMProjectKit/SPMProject.swift @@ -1,5 +1,6 @@ public struct SPMProject { public init() {} + public var text = "Hello, World!" } diff --git a/Tests/SPMTests/SPMProjectTest.swift b/Tests/SPMTests/SPMProjectTest.swift index 7e08b1a37..d3f3c980a 100644 --- a/Tests/SPMTests/SPMProjectTest.swift +++ b/Tests/SPMTests/SPMProjectTest.swift @@ -1,8 +1,9 @@ -import XCTest -@testable import TestShared @testable import PeripheryKit +@testable import TestShared +import XCTest -class SPMProjectTest: SourceGraphTestCase { +// swiftlint:disable:next balanced_xctest_lifecycle +final class SPMProjectTest: SourceGraphTestCase { override static func setUp() { super.setUp() diff --git a/Tests/Shared/DeclarationDescription.swift b/Tests/Shared/DeclarationDescription.swift index 369d584b0..fd3ab23d4 100644 --- a/Tests/Shared/DeclarationDescription.swift +++ b/Tests/Shared/DeclarationDescription.swift @@ -8,7 +8,7 @@ struct DeclarationDescription: CustomStringConvertible { var description: String { var parts = [kind.rawValue, "\"\(name)\""] - if let line = line { + if let line { parts.append("line: \(line)") } return "(\(parts.joined(separator: ", ")))" diff --git a/Tests/Shared/FixtureSourceGraphTestCase.swift b/Tests/Shared/FixtureSourceGraphTestCase.swift index 64d0dbf93..f58093265 100644 --- a/Tests/Shared/FixtureSourceGraphTestCase.swift +++ b/Tests/Shared/FixtureSourceGraphTestCase.swift @@ -1,19 +1,21 @@ -import SystemPackage @testable import PeripheryKit +import SystemPackage import XCTest +// swiftlint:disable:next final_test_case balanced_xctest_lifecycle class FixtureSourceGraphTestCase: SourceGraphTestCase { - class override func setUp() { + override class func setUp() { super.setUp() _sourceFiles = nil } @discardableResult - func analyze(retainPublic: Bool = false, - retainObjcAccessible: Bool = false, - retainObjcAnnotated: Bool = false, - disableRedundantPublicAnalysis: Bool = false, - testBlock: () throws -> Void + func analyze( + retainPublic: Bool = false, + retainObjcAccessible: Bool = false, + retainObjcAnnotated: Bool = false, + disableRedundantPublicAnalysis: Bool = false, + testBlock: () throws -> Void ) rethrows -> [ScanResult] { configuration.retainPublic = retainPublic configuration.retainObjcAccessible = retainObjcAccessible @@ -33,6 +35,7 @@ class FixtureSourceGraphTestCase: SourceGraphTestCase { // MARK: - Private + // swiftlint:disable:next discouraged_optional_collection private static var _sourceFiles: Set? private static var sourceFiles: Set { if let files = _sourceFiles { diff --git a/Tests/Shared/SourceGraphTestCase.swift b/Tests/Shared/SourceGraphTestCase.swift index bb28380c8..9539d610f 100644 --- a/Tests/Shared/SourceGraphTestCase.swift +++ b/Tests/Shared/SourceGraphTestCase.swift @@ -1,13 +1,17 @@ -import XCTest -import SystemPackage @testable import Indexer @testable import PeripheryKit -@testable import SourceGraph import Shared +@testable import SourceGraph +import SystemPackage +import XCTest +// swiftlint:disable:next blanket_disable_command +// swiftlint:disable test_case_accessibility open class SourceGraphTestCase: XCTestCase { + // swiftlint:disable implicitly_unwrapped_optional static var driver: ProjectDriver! static var configuration: Configuration! + // swiftlint:enable implicitly_unwrapped_optional static var results: [ScanResult] = [] private static var graph = SourceGraph() @@ -17,13 +21,13 @@ open class SourceGraphTestCase: XCTestCase { private var scopeStack: [DeclarationScope] = [] - class open override func setUp() { + override open class func setUp() { super.setUp() configuration = Configuration.shared configuration.quiet = true } - open override func setUp() { + override open func setUp() { super.setUp() configuration.reset() } @@ -77,7 +81,9 @@ open class SourceGraphTestCase: XCTestCase { _ name: String, implementedBy conformances: DeclarationDescription..., inherits inheritedProtocols: DeclarationDescription..., - file: StaticString = #file, line: UInt = #line) { + file: StaticString = #file, + line: UInt = #line + ) { guard let declaration = materialize(.protocol(name), file: file, line: line) else { return } if let tuple = Self.results.redundantProtocolDeclarations[declaration] { @@ -179,6 +185,7 @@ open class SourceGraphTestCase: XCTestCase { // MARK: - Private + // swiftlint:disable:next function_default_parameter_at_end discouraged_optional_collection private func materialize(_ description: DeclarationDescription, in defaultDeclarations: Set? = nil, fail: Bool = true, file: StaticString, line: UInt) -> Declaration? { let declarations = scopedDeclarations(from: defaultDeclarations) @@ -198,6 +205,7 @@ open class SourceGraphTestCase: XCTestCase { return matchedDeclaration } + // swiftlint:disable:next discouraged_optional_collection private func scopedDeclarations(from defaultDeclarations: Set? = nil) -> Set { let allDeclarations = defaultDeclarations ?? Self.graph.rootDeclarations diff --git a/Tests/XcodeTests/Helper.swift b/Tests/XcodeTests/Helper.swift index 417d62fcc..d448863d3 100644 --- a/Tests/XcodeTests/Helper.swift +++ b/Tests/XcodeTests/Helper.swift @@ -3,9 +3,9 @@ import SystemPackage @testable import TestShared var UIKitProjectPath: FilePath { - return ProjectRootPath.appending("Tests/XcodeTests/UIKitProject/UIKitProject.xcodeproj") + ProjectRootPath.appending("Tests/XcodeTests/UIKitProject/UIKitProject.xcodeproj") } var SwiftUIProjectPath: FilePath { - return ProjectRootPath.appending("Tests/XcodeTests/SwiftUIProject/SwiftUIProject.xcodeproj") + ProjectRootPath.appending("Tests/XcodeTests/SwiftUIProject/SwiftUIProject.xcodeproj") } diff --git a/Tests/XcodeTests/SwiftUIProject/SwiftUIProject/App.swift b/Tests/XcodeTests/SwiftUIProject/SwiftUIProject/App.swift index 1ca9485e9..d7831b040 100644 --- a/Tests/XcodeTests/SwiftUIProject/SwiftUIProject/App.swift +++ b/Tests/XcodeTests/SwiftUIProject/SwiftUIProject/App.swift @@ -2,7 +2,8 @@ import SwiftUI @main struct SwiftUIProjectApp: App { - @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate + @UIApplicationDelegateAdaptor(AppDelegate.self) + var appDelegate var body: some Scene { WindowGroup { diff --git a/Tests/XcodeTests/SwiftUIProjectTest.swift b/Tests/XcodeTests/SwiftUIProjectTest.swift index 812a0b921..2d34ce86e 100644 --- a/Tests/XcodeTests/SwiftUIProjectTest.swift +++ b/Tests/XcodeTests/SwiftUIProjectTest.swift @@ -1,8 +1,9 @@ -import XCTest @testable import TestShared @testable import XcodeSupport +import XCTest -class SwiftUIProjectTest: SourceGraphTestCase { +// swiftlint:disable:next balanced_xctest_lifecycle +final class SwiftUIProjectTest: SourceGraphTestCase { override static func setUp() { super.setUp() diff --git a/Tests/XcodeTests/UIKitProject/NotificationServiceExtension/NotificationService.swift b/Tests/XcodeTests/UIKitProject/NotificationServiceExtension/NotificationService.swift index 196b2cdfd..f6a063413 100644 --- a/Tests/XcodeTests/UIKitProject/NotificationServiceExtension/NotificationService.swift +++ b/Tests/XcodeTests/UIKitProject/NotificationServiceExtension/NotificationService.swift @@ -22,7 +22,7 @@ class NotificationService: UNNotificationServiceExtension { override func serviceExtensionTimeWillExpire() { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. - if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } diff --git a/Tests/XcodeTests/UIKitProject/UIKitProjectTests/UIKitProjectTests.swift b/Tests/XcodeTests/UIKitProject/UIKitProjectTests/UIKitProjectTests.swift index 4c3fd1604..d4343a685 100644 --- a/Tests/XcodeTests/UIKitProject/UIKitProjectTests/UIKitProjectTests.swift +++ b/Tests/XcodeTests/UIKitProject/UIKitProjectTests/UIKitProjectTests.swift @@ -7,7 +7,7 @@ import XCTest -class UIKitProjectTests: XCTestCase { +final class UIKitProjectTests: XCTestCase { override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. diff --git a/Tests/XcodeTests/UIKitProjectTest.swift b/Tests/XcodeTests/UIKitProjectTest.swift index e295a293a..228f0b103 100644 --- a/Tests/XcodeTests/UIKitProjectTest.swift +++ b/Tests/XcodeTests/UIKitProjectTest.swift @@ -1,15 +1,18 @@ -import XCTest @testable import TestShared @testable import XcodeSupport +import XCTest -class UIKitProjectTest: SourceGraphTestCase { +// swiftlint:disable:next balanced_xctest_lifecycle +final class UIKitProjectTest: SourceGraphTestCase { override static func setUp() { super.setUp() configuration.project = UIKitProjectPath.string configuration.schemes = ["UIKitProject"] - configuration.targets = ["UIKitProject", "NotificationServiceExtension", "WatchWidgetExtension", - "UIKitProjectTests", "LocalPackage.LocalPackageTarget"] + configuration.targets = [ + "UIKitProject", "NotificationServiceExtension", "WatchWidgetExtension", + "UIKitProjectTests", "LocalPackage.LocalPackageTarget" + ] build(driver: XcodeProjectDriver.self) index() diff --git a/Tests/XcodeTests/XcodeTargetTest.swift b/Tests/XcodeTests/XcodeTargetTest.swift index 7c40f3bab..7abf44951 100644 --- a/Tests/XcodeTests/XcodeTargetTest.swift +++ b/Tests/XcodeTests/XcodeTargetTest.swift @@ -1,9 +1,9 @@ import Foundation -import XCTest @testable import TestShared @testable import XcodeSupport +import XCTest -class XcodeTargetTest: XCTestCase { +final class XcodeTargetTest: XCTestCase { func testSourceFileInGroupWithoutFolder() throws { let project = try! XcodeProject(path: UIKitProjectPath) let target = project.targets.first { $0.name == "UIKitProject" }! diff --git a/Tests/XcodeTests/XcodebuildTest.swift b/Tests/XcodeTests/XcodebuildBuildProjectTest.swift similarity index 92% rename from Tests/XcodeTests/XcodebuildTest.swift rename to Tests/XcodeTests/XcodebuildBuildProjectTest.swift index a816e9780..ef53399e8 100644 --- a/Tests/XcodeTests/XcodebuildTest.swift +++ b/Tests/XcodeTests/XcodebuildBuildProjectTest.swift @@ -1,11 +1,14 @@ import Foundation -import XCTest import Shared @testable import XcodeSupport +import XCTest -class XcodebuildBuildProjectTest: XCTestCase { - var xcodebuild: Xcodebuild! - var project: XcodeProject! +// swiftlint:disable single_test_class +final class XcodebuildBuildProjectTest: XCTestCase { + // swiftlint:disable implicitly_unwrapped_optional + private var xcodebuild: Xcodebuild! + private var project: XcodeProject! + // swiftlint:enable implicitly_unwrapped_optional override func setUp() { super.setUp() @@ -14,16 +17,24 @@ class XcodebuildBuildProjectTest: XCTestCase { project = try! XcodeProject(path: UIKitProjectPath) } + override func tearDown() { + xcodebuild = nil + project = nil + super.tearDown() + } + func testBuildSchemeWithWhitespace() throws { let scheme = "Scheme With Spaces" try xcodebuild.build(project: project, scheme: scheme, allSchemes: [scheme]) } } -class XcodebuildSchemesTest: XCTestCase { - var shell: ShellMock! - var xcodebuild: Xcodebuild! - var project: XcodeProject! +final class XcodebuildSchemesTest: XCTestCase { + // swiftlint:disable implicitly_unwrapped_optional + private var shell: ShellMock! + private var xcodebuild: Xcodebuild! + private var project: XcodeProject! + // swiftlint:enable implicitly_unwrapped_optional override func setUp() { super.setUp() @@ -33,6 +44,13 @@ class XcodebuildSchemesTest: XCTestCase { project = try! XcodeProject(path: UIKitProjectPath) } + override func tearDown() { + shell = nil + xcodebuild = nil + project = nil + super.tearDown() + } + func testParseSchemes() { for output in XcodebuildListOutputs { shell.output = output @@ -50,7 +68,7 @@ class ShellMock: Shell { } override func exec(_ args: [String], stderr: Bool = true) throws -> String { - return output + output } }