Skip to content

Commit

Permalink
Add baseline capability
Browse files Browse the repository at this point in the history
  • Loading branch information
ileitch committed Jun 2, 2024
1 parent 7a8b360 commit 0a22202
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 43 deletions.
10 changes: 9 additions & 1 deletion Sources/Frontend/Commands/ScanBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,21 @@ final class ScanBehavior {

do {
results = try block(project)

let interval = logger.beginInterval("result:output")
let filteredResults = OutputDeclarationFilter().filter(results)
let filteredResults = try OutputDeclarationFilter().filter(results)

if configuration.autoRemove {
try ScanResultRemover().remove(results: filteredResults)
}

if !filteredResults.isEmpty, let baselinePath = configuration.writeBaseline {
let usrs = filteredResults.flatMapSet { $0.usrs }
let baseline = Baseline.v1(usrs: usrs)
let data = try JSONEncoder().encode(baseline)
try data.write(to: baselinePath.url)
}

let output = try configuration.outputFormat.formatter.init(configuration: configuration).format(filteredResults)

if configuration.outputFormat.supportsAuxiliaryOutput {
Expand Down
12 changes: 12 additions & 0 deletions Sources/Frontend/Commands/ScanCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ struct ScanCommand: FrontendCommand {
@Option(help: "JSON package manifest path (obtained using `swift package describe --type json` or manually)")
var jsonPackageManifestPath: String?

@Option(help: "Baseline file path used to filter results")
var baseline: FilePath?

@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.")
var writeBaseline: FilePath?

private static let defaultConfiguration = Configuration()

func run() throws {
Expand All @@ -136,6 +142,10 @@ struct ScanCommand: FrontendCommand {
Logger().warn("The option '--external-encodable-protocols' is deprecated, use '--external-codable-protocols' instead.")
}

if baseline != nil, writeBaseline != nil {
throw PeripheryError.usageError("The options '--baseline' and '--write-baseline' cannot be used as the same time. First, save a baseline with '--write-baseline', then use it with '--baseline'.")
}

let configuration = Configuration.shared
configuration.guidedSetup = setup
configuration.apply(\.$workspace, workspace)
Expand Down Expand Up @@ -174,6 +184,8 @@ struct ScanCommand: FrontendCommand {
configuration.apply(\.$retainCodableProperties, retainCodableProperties)
configuration.apply(\.$retainEncodableProperties, retainEncodableProperties)
configuration.apply(\.$jsonPackageManifestPath, jsonPackageManifestPath)
configuration.apply(\.$baseline, baseline)
configuration.apply(\.$writeBaseline, writeBaseline)

try scanBehavior.main { project in
try Scan().perform(project: project)
Expand Down
42 changes: 0 additions & 42 deletions Sources/PeripheryKit/Formatters/OutputDeclarationFilter.swift

This file was deleted.

13 changes: 13 additions & 0 deletions Sources/PeripheryKit/Results/Baseline.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

/// A baseline set of declarations that are excluded from results.
public enum Baseline: Codable {
case v1(usrs: Set<String>)

var usrs: Set<String> {
switch self {
case .v1(let usrs):
return usrs
}
}
}
63 changes: 63 additions & 0 deletions Sources/PeripheryKit/Results/OutputDeclarationFilter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Foundation
import SystemPackage
import Shared
import FilenameMatcher

public final class OutputDeclarationFilter {
private let configuration: Configuration
private let logger: Logger
private let contextualLogger: ContextualLogger

public required init(configuration: Configuration = .shared, logger: Logger = .init()) {
self.configuration = configuration
self.logger = logger
self.contextualLogger = logger.contextualized(with: "report:filter")
}

public func filter(_ declarations: [ScanResult]) throws -> [ScanResult] {
var declarations = declarations

if let baselinePath = configuration.baseline {
let data = try Data(contentsOf: baselinePath.url)
let baseline = try JSONDecoder().decode(Baseline.self, from: data)
var didFilterDeclaration = false
declarations = declarations.filter {
let isDisjoint = $0.usrs.isDisjoint(with: baseline.usrs)
if !isDisjoint {
didFilterDeclaration = true
}
return isDisjoint
}

if !didFilterDeclaration {
logger.warn("No results were filtered by the baseline.")
}
}

if configuration.reportInclude.isEmpty && configuration.reportExclude.isEmpty {
return declarations.sorted { $0.declaration < $1.declaration }
}

return declarations
.filter { [contextualLogger] in
let path = $0.declaration.location.file.path

if configuration.reportIncludeMatchers.isEmpty {
if configuration.reportExcludeMatchers.anyMatch(filename: path.string) {
contextualLogger.debug("Excluding \(path.string)")
return false
}

return true
}

if configuration.reportIncludeMatchers.anyMatch(filename: path.string) {
contextualLogger.debug("Including \(path.string)")
return true
}

return false
}
.sorted { $0.declaration < $1.declaration }
}
}
4 changes: 4 additions & 0 deletions Sources/PeripheryKit/ScanResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ public struct ScanResult {

let declaration: Declaration
let annotation: Annotation

public var usrs: Set<String> {
declaration.usrs
}
}
20 changes: 20 additions & 0 deletions Sources/Shared/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ public final class Configuration {
@Setting(key: "json_package_manifest_path", defaultValue: nil)
public var jsonPackageManifestPath: String?

@Setting(key: "baseline", defaultValue: nil)
public var baseline: FilePath?

@Setting(key: "write_baseline", defaultValue: nil)
public var writeBaseline: FilePath?

// Non user facing.
public var guidedSetup: Bool = false
public var removalOutputBasePath: FilePath?
Expand Down Expand Up @@ -280,6 +286,14 @@ public final class Configuration {
config[$jsonPackageManifestPath.key] = jsonPackageManifestPath
}

if $baseline.hasNonDefaultValue {
config[$baseline.key] = baseline
}

if $writeBaseline.hasNonDefaultValue {
config[$writeBaseline.key] = writeBaseline
}

return try Yams.dump(object: config)
}

Expand Down Expand Up @@ -373,6 +387,10 @@ public final class Configuration {
$retainEncodableProperties.assign(value)
case $jsonPackageManifestPath.key:
$jsonPackageManifestPath.assign(value)
case $baseline.key:
$baseline.assign(value)
case $writeBaseline.key:
$writeBaseline.assign(value)
default:
logger.warn("\(path.string): invalid key '\(key)'")
}
Expand Down Expand Up @@ -417,6 +435,8 @@ public final class Configuration {
$retainCodableProperties.reset()
$retainEncodableProperties.reset()
$jsonPackageManifestPath.reset()
$baseline.reset()
$writeBaseline.reset()
}

// MARK: - Helpers
Expand Down

0 comments on commit 0a22202

Please sign in to comment.