Skip to content

Commit ec31939

Browse files
authored
Add option to write results to a file (#911)
1 parent 82ff0fc commit ec31939

24 files changed

+119
-80
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
##### Enhancements
88

9-
- None.
9+
- Added `--write-results <file>` option.
1010

1111
##### Bug Fixes
1212

Sources/Configuration/Configuration.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ public final class Configuration {
122122
@Setting(key: "write_baseline", defaultValue: nil, setter: filePathSetter)
123123
public var writeBaseline: FilePath?
124124

125+
@Setting(key: "write_results", defaultValue: nil, setter: filePathSetter)
126+
public var writeResults: FilePath?
127+
125128
@Setting(key: "generic_project_config", defaultValue: nil, setter: filePathSetter)
126129
public var genericProjectConfig: FilePath?
127130

@@ -216,7 +219,15 @@ public final class Configuration {
216219

217220
// MARK: - Private
218221

219-
lazy var settings: [any AbstractSetting] = [$project, $schemes, $excludeTargets, $excludeTests, $indexExclude, $reportExclude, $reportInclude, $outputFormat, $retainPublic, $retainFiles, $retainAssignOnlyProperties, $retainAssignOnlyPropertyTypes, $retainObjcAccessible, $retainObjcAnnotated, $retainUnusedProtocolFuncParams, $retainSwiftUIPreviews, $disableRedundantPublicAnalysis, $disableUnusedImportAnalysis, $externalEncodableProtocols, $externalCodableProtocols, $externalTestCaseClasses, $verbose, $quiet, $disableUpdateCheck, $strict, $indexStorePath, $skipBuild, $skipSchemesValidation, $cleanBuild, $buildArguments, $xcodeListArguments, $relativeResults, $jsonPackageManifestPath, $retainCodableProperties, $retainEncodableProperties, $baseline, $writeBaseline, $genericProjectConfig, $bazel, $bazelFilter]
222+
lazy var settings: [any AbstractSetting] = [
223+
$project, $schemes, $excludeTargets, $excludeTests, $indexExclude, $reportExclude, $reportInclude, $outputFormat,
224+
$retainPublic, $retainFiles, $retainAssignOnlyProperties, $retainAssignOnlyPropertyTypes, $retainObjcAccessible,
225+
$retainObjcAnnotated, $retainUnusedProtocolFuncParams, $retainSwiftUIPreviews, $disableRedundantPublicAnalysis,
226+
$disableUnusedImportAnalysis, $externalEncodableProtocols, $externalCodableProtocols, $externalTestCaseClasses,
227+
$verbose, $quiet, $disableUpdateCheck, $strict, $indexStorePath, $skipBuild, $skipSchemesValidation, $cleanBuild,
228+
$buildArguments, $xcodeListArguments, $relativeResults, $jsonPackageManifestPath, $retainCodableProperties,
229+
$retainEncodableProperties, $baseline, $writeBaseline, $writeResults, $genericProjectConfig, $bazel, $bazelFilter,
230+
]
220231

221232
private func buildFilenameMatchers(with patterns: [String]) -> [FilenameMatcher] {
222233
// TODO: respect filesystem case sensitivity.

Sources/Configuration/OutputFormat.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@ public enum OutputFormat: String, CaseIterable {
2222
@inlinable public var supportsAuxiliaryOutput: Bool {
2323
self == .xcode
2424
}
25+
26+
@inlinable public var supportsColoredOutput: Bool {
27+
self == .xcode
28+
}
2529
}

Sources/Frontend/BazelProjectSetupGuide.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ final class BazelProjectSetupGuide: SetupGuideHelpers, SetupGuide {
1515
}
1616

1717
func perform() throws -> ProjectKind {
18-
print(colorize("\nAdd the following snippet to your MODULE.bazel file:", .bold))
19-
print(colorize("""
18+
print(Logger.colorize("\nAdd the following snippet to your MODULE.bazel file:", .bold))
19+
print(Logger.colorize("""
2020
bazel_dep(name = "periphery", version = "\(PeripheryVersion)")
2121
use_repo(use_extension("@periphery//bazel:generated.bzl", "generated"), "periphery_generated")
2222
""", .lightGray))
23-
print(colorize("\nEnter to continue when ready ", .bold), terminator: "")
23+
print(Logger.colorize("\nEnter to continue when ready ", .bold), terminator: "")
2424
_ = readLine()
2525

2626
return .bazel

Sources/Frontend/Commands/CheckUpdateCommand.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ struct CheckUpdateCommand: FrontendCommand {
1616
DispatchQueue.global().async { checker.run() }
1717
let latestVersion = try checker.wait().get()
1818
if latestVersion.isVersion(greaterThan: PeripheryVersion) {
19-
logger.info(colorize("* Update Available", .boldGreen))
20-
let boldLatestVersion = colorize(latestVersion, .bold)
21-
let boldLocalVersion = colorize(PeripheryVersion, .bold)
19+
logger.info(Logger.colorize("* Update Available", .boldGreen))
20+
let boldLatestVersion = Logger.colorize(latestVersion, .bold)
21+
let boldLocalVersion = Logger.colorize(PeripheryVersion, .bold)
2222
logger.info("Version \(boldLatestVersion) is now available, you are using version \(boldLocalVersion).")
2323
} else {
24-
let boldLatestVersion = colorize(latestVersion, .bold)
24+
let boldLatestVersion = Logger.colorize(latestVersion, .bold)
2525
logger.info("You are using the latest version, \(boldLatestVersion).")
2626
}
2727
}

Sources/Frontend/Commands/FrontendCommand.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import Logger
33

44
protocol FrontendCommand: ParsableCommand {}
55
extension FrontendCommand {
6-
static var _errorLabel: String { colorize("error", .boldRed) }
6+
static var _errorLabel: String { Logger.colorize("error", .boldRed) }
77
}

Sources/Frontend/Commands/ScanCommand.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ struct ScanCommand: FrontendCommand {
129129
@Option(help: "Baseline file path where results are written. Pass the same path to '--baseline' in subsequent scans to exclude the results recorded in the baseline.")
130130
var writeBaseline: FilePath?
131131

132+
@Option(help: "File path where formatted results are written.")
133+
var writeResults: FilePath?
134+
132135
@Option(help: "Project configuration for non-Apple build systems")
133136
var genericProjectConfig: FilePath?
134137

@@ -188,6 +191,7 @@ struct ScanCommand: FrontendCommand {
188191
configuration.apply(\.$jsonPackageManifestPath, jsonPackageManifestPath)
189192
configuration.apply(\.$baseline, baseline)
190193
configuration.apply(\.$writeBaseline, writeBaseline)
194+
configuration.apply(\.$writeResults, writeResults)
191195
configuration.apply(\.$genericProjectConfig, genericProjectConfig)
192196
configuration.apply(\.$bazel, bazel)
193197
configuration.apply(\.$bazelFilter, bazelFilter)
@@ -241,12 +245,27 @@ struct ScanCommand: FrontendCommand {
241245
try data.write(to: baselinePath.url)
242246
}
243247

244-
if let output = try configuration.outputFormat.formatter.init(configuration: configuration).format(filteredResults) {
245-
if configuration.outputFormat.supportsAuxiliaryOutput {
248+
let outputFormat = configuration.outputFormat
249+
let formatter = outputFormat.formatter.init(configuration: configuration)
250+
251+
if let output = try formatter.format(filteredResults, colored: outputFormat.supportsColoredOutput) {
252+
if outputFormat.supportsAuxiliaryOutput {
246253
logger.info("", canQuiet: true)
247254
}
248255

249256
logger.info(output, canQuiet: false)
257+
258+
if let resultsPath = configuration.writeResults {
259+
var output = output
260+
261+
if outputFormat.supportsColoredOutput {
262+
// The formatted output contains ANSI escape codes, so we need to re-format
263+
// with coloring disabled.
264+
output = try formatter.format(filteredResults, colored: false) ?? ""
265+
}
266+
267+
try output.write(to: resultsPath.url, atomically: true, encoding: .utf8)
268+
}
250269
}
251270

252271
logger.endInterval(interval)

Sources/Frontend/CommonSetupGuide.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ final class CommonSetupGuide: SetupGuideHelpers {
1212
}
1313

1414
func perform() throws {
15-
print(colorize("\nAssume all 'public' declarations are in use?", .bold))
15+
print(Logger.colorize("\nAssume all 'public' declarations are in use?", .bold))
1616
print("Choose 'Yes' if your project is a framework/library without a main application target.")
1717
configuration.retainPublic = selectBoolean()
1818
}

Sources/Frontend/GuidedSetup.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class GuidedSetup: SetupGuideHelpers {
1919
}
2020

2121
func perform() throws -> Project {
22-
print(colorize("Welcome to Periphery!", .boldGreen))
22+
print(Logger.colorize("Welcome to Periphery!", .boldGreen))
2323
print("This guided setup will help you select the appropriate configuration for your project.\n")
2424

2525
var projectGuides: [SetupGuide] = []
@@ -41,20 +41,20 @@ final class GuidedSetup: SetupGuideHelpers {
4141
var projectGuide_: SetupGuide?
4242

4343
if projectGuides.count > 1 {
44-
print(colorize("Select which project to use:", .bold))
44+
print(Logger.colorize("Select which project to use:", .bold))
4545
let kindName = select(single: projectGuides.map(\.projectKindName))
4646
projectGuide_ = projectGuides.first { $0.projectKindName == kindName }
4747
print("")
4848
} else if let singleGuide = projectGuides.first {
49-
print(colorize("*", .boldGreen) + " Detected \(singleGuide.projectKindName) project")
49+
print(Logger.colorize("*", .boldGreen) + " Detected \(singleGuide.projectKindName) project")
5050
projectGuide_ = singleGuide
5151
}
5252

5353
guard let projectGuide = projectGuide_ else {
5454
fatalError("Failed to identify project type.")
5555
}
5656

57-
print(colorize("*", .boldGreen) + " Inspecting project...")
57+
print(Logger.colorize("*", .boldGreen) + " Inspecting project...")
5858

5959
let kind = try projectGuide.perform()
6060
let project = Project(kind: kind, configuration: configuration, shell: shell, logger: logger)
@@ -66,16 +66,16 @@ final class GuidedSetup: SetupGuideHelpers {
6666
var shouldSave = false
6767

6868
if configuration.hasNonDefaultValues {
69-
print(colorize("\nSave configuration to \(Configuration.defaultConfigurationFile)?", .bold))
69+
print(Logger.colorize("\nSave configuration to \(Configuration.defaultConfigurationFile)?", .bold))
7070
shouldSave = selectBoolean()
7171

7272
if shouldSave {
7373
try configuration.save()
7474
}
7575
}
7676

77-
print(colorize("\n*", .boldGreen) + " Executing command:")
78-
print(colorize(formatScanCommand(options: options, didSave: shouldSave) + "\n", .bold))
77+
print(Logger.colorize("\n*", .boldGreen) + " Executing command:")
78+
print(Logger.colorize(formatScanCommand(options: options, didSave: shouldSave) + "\n", .bold))
7979

8080
return project
8181
}

Sources/Frontend/Scan.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ final class Scan {
6363
let indexInterval = logger.beginInterval("index")
6464

6565
if configuration.outputFormat.supportsAuxiliaryOutput {
66-
let asterisk = colorize("*", .boldGreen)
66+
let asterisk = Logger.colorize("*", .boldGreen)
6767
logger.info("\(asterisk) Indexing...")
6868
}
6969

@@ -79,7 +79,7 @@ final class Scan {
7979
let analyzeInterval = logger.beginInterval("analyze")
8080

8181
if configuration.outputFormat.supportsAuxiliaryOutput {
82-
let asterisk = colorize("*", .boldGreen)
82+
let asterisk = Logger.colorize("*", .boldGreen)
8383
logger.info("\(asterisk) Analyzing...")
8484
}
8585

0 commit comments

Comments
 (0)