Skip to content

Commit

Permalink
Automatic target detection
Browse files Browse the repository at this point in the history
  • Loading branch information
ileitch committed Aug 3, 2024
1 parent 0b0407b commit 8b2c230
Show file tree
Hide file tree
Showing 201 changed files with 392 additions and 698 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ DerivedData
*.gcda
*.gcno
.swiftpm
Tests/Fixtures/.build/

# VSCode
.vscode/*
8 changes: 0 additions & 8 deletions .periphery.linux.yml
Original file line number Diff line number Diff line change
@@ -1,8 +0,0 @@
targets:
- Frontend
- Shared
- PeripheryKit
- TestShared
- PeripheryTests
- SPMTests
- AccessibilityTests
10 changes: 0 additions & 10 deletions .periphery.yml

This file was deleted.

20 changes: 10 additions & 10 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "0fbc8848e389af3bb55c182bc19ca9d5dc2f255b",
"version" : "1.4.0"
"revision" : "41982a3656a71c768319979febd796c6fd111d5c",
"version" : "1.5.0"
}
},
{
Expand All @@ -59,35 +59,35 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "303e5c5c36d6a558407d364878df131c3546fad8",
"version" : "510.0.2"
"revision" : "2bc86522d115234d1f588efe2bcb4ce4be8f8b82",
"version" : "510.0.3"
}
},
{
"identity" : "swift-system",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system",
"state" : {
"revision" : "6a9e38e7bd22a3b8ba80bddf395623cf68f57807",
"version" : "1.3.1"
"revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5",
"version" : "1.3.2"
}
},
{
"identity" : "xcodeproj",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tuist/xcodeproj",
"state" : {
"revision" : "20d5803c70e4ac5d67151ea6f5624a8136ab8fe0",
"version" : "8.21.0"
"revision" : "7713589d4d1bceedd02899d9c44b8e57be05ea35",
"version" : "8.22.0"
}
},
{
"identity" : "yams",
"kind" : "remoteSourceControl",
"location" : "https://github.com/jpsim/Yams",
"state" : {
"revision" : "9234124cff5e22e178988c18d8b95a8ae8007f76",
"version" : "5.1.2"
"revision" : "3036ba9d69cf1fd04d433527bc339dc0dc75433d",
"version" : "5.1.3"
}
}
],
Expand Down
47 changes: 1 addition & 46 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var dependencies: [Package.Dependency] = [
.package(url: "https://github.com/tadija/AEXML", from: "4.0.0"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
.package(url: "https://github.com/ileitch/swift-indexstore", from: "9.0.4"),
.package(url: "https://github.com/apple/swift-syntax", from: "510.0.2"),
.package(url: "https://github.com/apple/swift-syntax", from: "510.0.3"),
.package(url: "https://github.com/ileitch/swift-filename-matcher", from: "0.0.0"),
]

Expand Down Expand Up @@ -72,43 +72,6 @@ var targets: [PackageDescription.Target] = [
],
path: "Tests/Shared"
),
.target(
name: "ExternalModuleFixtures",
path: "Tests/Fixtures/ExternalModuleFixtures"
),
.target(
name: "CrossModuleRetentionFixtures",
dependencies: [
.target(name: "CrossModuleRetentionSupportFixtures")
],
path: "Tests/Fixtures/CrossModuleRetentionFixtures"
),
.target(
name: "CrossModuleRetentionSupportFixtures",
path: "Tests/Fixtures/CrossModuleRetentionSupportFixtures"
),
.target(
name: "RetentionFixtures",
dependencies: [
.target(name: "ExternalModuleFixtures")
],
path: "Tests/Fixtures/RetentionFixtures"
),
.target(
name: "UnusedParameterFixtures",
path: "Tests/Fixtures/UnusedParameterFixtures",
swiftSettings: [
.unsafeFlags(["-suppress-warnings"]) // Suppress warnings from testLocalVariableAssignment
]
),
.target(
name: "TypeSyntaxInspectorFixtures",
path: "Tests/Fixtures/TypeSyntaxInspectorFixtures"
),
.target(
name: "DeclarationVisitorFixtures",
path: "Tests/Fixtures/DeclarationVisitorFixtures"
),
.testTarget(
name: "PeripheryTests",
dependencies: [
Expand Down Expand Up @@ -145,14 +108,6 @@ targets.append(contentsOf: [
.product(name: "XcodeProj", package: "XcodeProj"),
]
),
.target(
name: "ObjcAccessibleRetentionFixtures",
path: "Tests/Fixtures/ObjcAccessibleRetentionFixtures"
),
.target(
name: "ObjcAnnotatedRetentionFixtures",
path: "Tests/Fixtures/ObjcAnnotatedRetentionFixtures"
),
.testTarget(
name: "XcodeTests",
dependencies: [
Expand Down
18 changes: 0 additions & 18 deletions Sources/Frontend/Commands/ScanBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,24 +90,6 @@ final class ScanBehavior {
logger.info(output, canQuiet: false)
logger.endInterval(interval)

if filteredResults.count > 0,
configuration.outputFormat.supportsAuxiliaryOutput {
logger.info(
colorize("\n* ", .boldGreen) +
colorize("Seeing false positives?", .bold) +

colorize("\n - ", .boldGreen) +
"Periphery only analyzes files that are members of the targets you specify." +
"\n References to declarations identified as unused may reside in files that are members of other targets, e.g test targets." +

colorize("\n - ", .boldGreen) +
"Periphery is a very precise tool, false positives often turn out to be correct after further investigation." +

colorize("\n - ", .boldGreen) +
"If it really is a false positive, please report it - https://github.com/peripheryapp/periphery/issues."
)
}

updateChecker.notifyIfAvailable()

if !filteredResults.isEmpty && configuration.strict {
Expand Down
80 changes: 36 additions & 44 deletions Sources/Frontend/Commands/ScanCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ struct ScanCommand: FrontendCommand {
@Option(parsing: .upToNextOption, help: "File target mapping configuration file paths. For use with third-party build systems")
var fileTargetsPath: [FilePath] = defaultConfiguration.$fileTargetsPath.defaultValue

@Option(parsing: .upToNextOption, help: "Schemes that must be built in order to produce the targets passed to the --targets option. Xcode projects only")
@Option(parsing: .upToNextOption, help: "TODO") // TODO: Update, explain targets?
var schemes: [String] = defaultConfiguration.$schemes.defaultValue

@Option(parsing: .upToNextOption, help: "Target names to scan. Required for Xcode projects. Optional for Swift Package Manager projects, default behavior is to scan all targets defined in Package.swift")
var targets: [String] = defaultConfiguration.$targets.defaultValue

@Option(help: "Output format (allowed: \(OutputFormat.allValueStrings.joined(separator: ", ")))")
var format: OutputFormat = defaultConfiguration.$outputFormat.defaultValue

Expand Down Expand Up @@ -117,9 +114,6 @@ struct ScanCommand: FrontendCommand {
@Flag(help: "Only output results")
var quiet: Bool = defaultConfiguration.$quiet.defaultValue

@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?

Expand All @@ -137,43 +131,41 @@ struct ScanCommand: FrontendCommand {

let configuration = Configuration.shared
configuration.guidedSetup = setup
configuration.apply(\.$workspace, workspace)
configuration.apply(\.$project, project)
configuration.apply(\.$fileTargetsPath, fileTargetsPath)
configuration.apply(\.$schemes, schemes)
configuration.apply(\.$targets, targets)
configuration.apply(\.$indexExclude, indexExclude)
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)
configuration.apply(\.$retainObjcAccessible, retainObjcAccessible)
configuration.apply(\.$retainObjcAnnotated, retainObjcAnnotated)
configuration.apply(\.$retainUnusedProtocolFuncParams, retainUnusedProtocolFuncParams)
configuration.apply(\.$retainSwiftUIPreviews, retainSwiftUIPreviews)
configuration.apply(\.$disableRedundantPublicAnalysis, disableRedundantPublicAnalysis)
configuration.apply(\.$disableUnusedImportAnalysis, disableUnusedImportAnalysis)
configuration.apply(\.$externalEncodableProtocols, externalEncodableProtocols)
configuration.apply(\.$externalCodableProtocols, externalCodableProtocols)
configuration.apply(\.$externalTestCaseClasses, externalTestCaseClasses)
configuration.apply(\.$verbose, verbose)
configuration.apply(\.$quiet, quiet)
configuration.apply(\.$disableUpdateCheck, disableUpdateCheck)
configuration.apply(\.$strict, strict)
configuration.apply(\.$indexStorePath, indexStorePath)
configuration.apply(\.$skipBuild, skipBuild)
configuration.apply(\.$skipSchemesValidation, skipSchemesValidation)
configuration.apply(\.$cleanBuild, cleanBuild)
configuration.apply(\.$buildArguments, buildArguments)
configuration.apply(\.$relativeResults, relativeResults)
configuration.apply(\.$retainCodableProperties, retainCodableProperties)
configuration.apply(\.$retainEncodableProperties, retainEncodableProperties)
configuration.apply(\.$jsonPackageManifestPath, jsonPackageManifestPath)
configuration.apply(\.$baseline, baseline)
configuration.apply(\.$writeBaseline, writeBaseline)
configuration.$workspace.assign(workspace)
configuration.$project.assign(project)
configuration.$fileTargetsPath.assign(fileTargetsPath)
configuration.$schemes.assign(schemes)
configuration.$indexExclude.assign(indexExclude)
configuration.$reportExclude.assign(reportExclude)
configuration.$reportInclude.assign(reportInclude)
configuration.$outputFormat.assign(format)
configuration.$retainFiles.assign(retainFiles)
configuration.$retainPublic.assign(retainPublic)
configuration.$retainAssignOnlyProperties.assign(retainAssignOnlyProperties)
configuration.$retainAssignOnlyPropertyTypes.assign(retainAssignOnlyPropertyTypes)
configuration.$retainObjcAccessible.assign(retainObjcAccessible)
configuration.$retainObjcAnnotated.assign(retainObjcAnnotated)
configuration.$retainUnusedProtocolFuncParams.assign(retainUnusedProtocolFuncParams)
configuration.$retainSwiftUIPreviews.assign(retainSwiftUIPreviews)
configuration.$disableRedundantPublicAnalysis.assign(disableRedundantPublicAnalysis)
configuration.$disableUnusedImportAnalysis.assign(disableUnusedImportAnalysis)
configuration.$externalEncodableProtocols.assign(externalEncodableProtocols)
configuration.$externalCodableProtocols.assign(externalCodableProtocols)
configuration.$externalTestCaseClasses.assign(externalTestCaseClasses)
configuration.$verbose.assign(verbose)
configuration.$quiet.assign(quiet)
configuration.$disableUpdateCheck.assign(disableUpdateCheck)
configuration.$strict.assign(strict)
configuration.$indexStorePath.assign(indexStorePath)
configuration.$skipBuild.assign(skipBuild)
configuration.$skipSchemesValidation.assign(skipSchemesValidation)
configuration.$cleanBuild.assign(cleanBuild)
configuration.$buildArguments.assign(buildArguments)
configuration.$relativeResults.assign(relativeResults)
configuration.$retainCodableProperties.assign(retainCodableProperties)
configuration.$retainEncodableProperties.assign(retainEncodableProperties)
configuration.$baseline.assign(baseline)
configuration.$writeBaseline.assign(writeBaseline)

try scanBehavior.main { project in
try Scan().perform(project: project)
Expand Down
39 changes: 2 additions & 37 deletions Sources/Frontend/SPMProjectSetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ import PeripheryKit
import Shared

final class SPMProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide {
private let configuration: Configuration

init(configuration: Configuration = .shared) {
self.configuration = configuration
super.init()
}

var projectKind: ProjectKind {
.spm
}
Expand All @@ -19,37 +12,9 @@ final class SPMProjectSetupGuide: SetupGuideHelpers, ProjectSetupGuide {
SPM.isSupported
}

func perform() throws {
let package = try SPM.Package.load()
let selection = try selectTargets(in: package)

if case let .some(targets) = selection {
configuration.targets = targets
}
}
func perform() {}

var commandLineOptions: [String] {
var options: [String] = []

if !configuration.targets.isEmpty {
options.append("--targets " + configuration.targets.map { "\"\($0)\"" }.joined(separator: ","))
}

return options
[]
}

// MARK: - Private

private func selectTargets(in package: SPM.Package) throws -> SetupSelection {
let targets = package.swiftTargets

guard !targets.isEmpty else {
throw PeripheryError.guidedSetupError(message: "Failed to identify any targets in package \(package.name)")
}

print(colorize("Select build targets to analyze:", .bold))
let targetNames = targets.map { $0.name }.sorted()
return select(multiple: targetNames, allowAll: true)
}

}
5 changes: 4 additions & 1 deletion Sources/Frontend/Scan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ final class Scan {
logger.info("\(asterisk) Indexing...")
}

let indexLogger = logger.contextualized(with: "index")
let sourceFiles = try driver.collect(logger: indexLogger)

let graph = SourceGraph.shared
try driver.index(graph: graph)
try driver.index(sourceFiles: sourceFiles, graph: graph, logger: indexLogger)
logger.endInterval(indexInterval)

let analyzeInterval = logger.beginInterval("analyze")
Expand Down
Loading

0 comments on commit 8b2c230

Please sign in to comment.