Skip to content

Commit

Permalink
Add the '--retain-files' option
Browse files Browse the repository at this point in the history
  • Loading branch information
ileitch committed Jan 4, 2024
1 parent 8264227 commit 1b59d67
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Assign-only properties on structs with synthesized initializers are now detected.
- Added the `--retain-codable-properties` option to retain all properties on Codable types.
- Results for redundant protocol conformances will now list the inherited protocols that should replace the redundant conformance.
- Added the `--retain-files` option to retain all declarations within the given files.

##### Bug Fixes

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,10 @@ To exclude the results from certain files, pass the `--report-exclude <globs>` o

To exclude files from being indexed, pass the `--index-exclude <globs>` option to the `scan` command. Excluding files from the index phase means that any declarations and references contained within the files will not be seen by Periphery. Periphery will be behave as if the files do not exist. For example, this option can be used to exclude generated code that holds references to non-generated code, or exclude all `.xib` and `.storyboard` files that hold references to code.

### Retaining File Declarations

To retain all declarations in files, pass the `--retain-files <globs>` option to the `scan` command. This option is equivalent to adding a `// periphery:ignore:all` comment command at the top of each file.

## Continuous Integration

When integrating Periphery into a CI pipeline, you can potentially skip the build phase if your pipeline has already done so, e.g to run tests. This can be achieved using the `--skip-build` option. However, you also need to tell Periphery the location of the index store using `--index-store-path`. This location is dependent on your project type.
Expand Down
4 changes: 4 additions & 0 deletions Sources/Frontend/Commands/ScanCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ struct ScanCommand: FrontendCommand {
@Option(help: "Path glob of source files to include in the results. This option supersedes '--report-exclude'. Note that this option is purely cosmetic, these files will still be indexed. Multiple globs may be delimited by a pipe", transform: split(by: "|"))
var reportInclude: [String] = defaultConfiguration.$reportInclude.defaultValue

@Option(parsing: .upToNextOption, help: "Retain all declarations within the given source files. Multiple paths may be specified")
var retainFiles: [String] = defaultConfiguration.$retainFiles.defaultValue

@Option(parsing: .upToNextOption, help: "Path to the index store. Multiple paths may be specified. Implies '--skip-build'")
var indexStorePath: [FilePath] = defaultConfiguration.$indexStorePath.defaultValue

Expand Down Expand Up @@ -132,6 +135,7 @@ struct ScanCommand: FrontendCommand {
configuration.apply(\.$reportExclude, reportExclude)
configuration.apply(\.$reportInclude, reportInclude)
configuration.apply(\.$outputFormat, format)
configuration.apply(\.$retainFiles, retainFiles)
configuration.apply(\.$retainPublic, retainPublic)
configuration.apply(\.$retainAssignOnlyProperties, retainAssignOnlyProperties)
configuration.apply(\.$retainAssignOnlyPropertyTypes, retainAssignOnlyPropertyTypes)
Expand Down
18 changes: 18 additions & 0 deletions Sources/PeripheryKit/Indexer/SwiftIndexer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,17 @@ public final class SwiftIndexer: Indexer {
throw PeripheryError.unindexedTargetsError(targets: targets, indexStorePaths: indexStorePaths)
}

var retainedFiles: Set<FilePath> = []

if !configuration.retainFilesMatchers.isEmpty {
retainedFiles = allSourceFiles.filter { configuration.retainFilesMatchers.anyMatch(filename: $0.string) }
}

let jobs = unitsByFile.map { (file, units) -> Job in
return Job(
file: file,
units: units,
retainAllDeclarations: retainedFiles.contains(file),
graph: graph,
logger: logger,
configuration: configuration
Expand Down Expand Up @@ -111,17 +118,20 @@ public final class SwiftIndexer: Indexer {
private let logger: ContextualLogger
private let configuration: Configuration
private var sourceFile: SourceFile?
private var retainAllDeclarations: Bool

required init(
file: FilePath,
units: [(IndexStore, IndexStoreUnit)],
retainAllDeclarations: Bool,
graph: SourceGraph,
logger: ContextualLogger,
configuration: Configuration

) {
self.file = file
self.units = units
self.retainAllDeclarations = retainAllDeclarations
self.graph = graph
self.logger = logger
self.configuration = configuration
Expand Down Expand Up @@ -225,6 +235,10 @@ public final class SwiftIndexer: Indexer {
graph.withLock {
graph.addUnsafe(references)
graph.addUnsafe(newDeclarations)

if retainAllDeclarations {
graph.markRetainedUnsafe(newDeclarations)
}
}

establishDeclarationHierarchy()
Expand Down Expand Up @@ -490,6 +504,10 @@ public final class SwiftIndexer: Indexer {
functionDecl.unusedParameters.insert(paramDecl)
graph.addUnsafe(paramDecl)

if retainAllDeclarations {
graph.markRetainedUnsafe(paramDecl)
}

if (functionDecl.isObjcAccessible && configuration.retainObjcAccessible) || ignoredParamNames.contains(param.name) {
graph.markRetainedUnsafe(paramDecl)
}
Expand Down
5 changes: 5 additions & 0 deletions Sources/PeripheryKit/SourceGraph/SourceGraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public final class SourceGraph {
_ = retainedDeclarations.insert(declaration)
}

func markRetainedUnsafe(_ declarations: Set<Declaration>) {
retainedDeclarations.formUnion(declarations)
}

func markAssignOnlyProperty(_ declaration: Declaration) {
withLock {
_ = assignOnlyProperties.insert(declaration)
Expand Down Expand Up @@ -352,3 +356,4 @@ public final class SourceGraph {
}
}
}

24 changes: 23 additions & 1 deletion Sources/Shared/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public final class Configuration {
@Setting(key: "retain_objc_annotated", defaultValue: false)
public var retainObjcAnnotated: Bool

@Setting(key: "retain_files", defaultValue: [])
public var retainFiles: [String]

@Setting(key: "retain_public", defaultValue: false)
public var retainPublic: Bool

Expand Down Expand Up @@ -161,6 +164,10 @@ public final class Configuration {
config[$retainPublic.key] = retainPublic
}

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

if $retainAssignOnlyProperties.hasNonDefaultValue {
config[$retainAssignOnlyProperties.key] = retainAssignOnlyProperties
}
Expand Down Expand Up @@ -273,6 +280,8 @@ public final class Configuration {
$outputFormat.assign(value)
case $retainPublic.key:
$retainPublic.assign(value)
case $retainFiles.key:
$retainFiles.assign(value)
case $retainAssignOnlyProperties.key:
$retainAssignOnlyProperties.assign(value)
case $retainAssignOnlyPropertyTypes.key:
Expand Down Expand Up @@ -335,6 +344,7 @@ public final class Configuration {
$reportInclude.reset()
$outputFormat.reset()
$retainPublic.reset()
$retainFiles.reset()
$retainAssignOnlyProperties.reset()
$retainAssignOnlyPropertyTypes.reset()
$retainObjcAccessible.reset()
Expand Down Expand Up @@ -379,8 +389,20 @@ public final class Configuration {
return matchers
}

public func resetIndexExcludeMatchers() {
private var _retainFilesMatchers: [FilenameMatcher]?
public var retainFilesMatchers: [FilenameMatcher] {
if let _retainFilesMatchers {
return _retainFilesMatchers
}

let matchers = buildFilenameMatchers(with: retainFiles)
_retainFilesMatchers = matchers
return matchers
}

public func resetMatchers() {
_indexExcludeMatchers = nil
_retainFilesMatchers = nil
}

public lazy var reportExcludeMatchers: [FilenameMatcher] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class FixtureClass100 {}
14 changes: 14 additions & 0 deletions Tests/PeripheryTests/RetentionTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,20 @@ final class RetentionTest: FixtureSourceGraphTestCase {
}
}

func testRetainsFilesOption() {
configuration.retainFiles = [testFixturePath.string]

analyze {
assertReferenced(.class("FixtureClass100"))
}

configuration.retainFiles = []

analyze {
assertNotReferenced(.class("FixtureClass100"))
}
}

// MARK: - Assign-only properties

func testStructImplicitInitializer() {
Expand Down
2 changes: 1 addition & 1 deletion Tests/Shared/FixtureSourceGraphTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class FixtureSourceGraphTestCase: SourceGraphTestCase {
configuration.retainObjcAccessible = retainObjcAccessible
configuration.retainObjcAnnotated = retainObjcAnnotated
configuration.indexExclude = Self.sourceFiles.subtracting([testFixturePath]).map { $0.string }
configuration.resetIndexExcludeMatchers()
configuration.resetMatchers()

if !testFixturePath.exists {
fatalError("\(testFixturePath.string) does not exist")
Expand Down

0 comments on commit 1b59d67

Please sign in to comment.