Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic target detection #767

Merged
merged 1 commit into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,4 @@ jobs:
- name: Test
run: ${{ env.swift_test }}
- name: Scan
run: ${{ env.periphery_scan }} --config .periphery.linux.yml
run: ${{ env.periphery_scan }}
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

This file was deleted.

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
17 changes: 2 additions & 15 deletions Sources/Frontend/Commands/ScanCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,15 @@ struct ScanCommand: FrontendCommand {
@Option(help: "Path to configuration file. By default Periphery will look for .periphery.yml in the current directory")
var config: String?

@Option(help: "Path to your project's .xcworkspace. Xcode projects only")
var workspace: String?

@Option(help: "Path to your project's .xcodeproj - supply this option if your project doesn't have an .xcworkspace. Xcode projects only")
@Option(help: "Path to your project's .xcodeproj or .xcworkspace")
var project: String?

@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: "Schemes to build. All targets built by these schemes will be scanned")
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 +111,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,11 +128,9 @@ 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)
Expand Down Expand Up @@ -171,10 +160,8 @@ struct ScanCommand: FrontendCommand {
configuration.apply(\.$relativeResults, relativeResults)
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)
}.get()
Expand Down
4 changes: 2 additions & 2 deletions Sources/Frontend/CommonSetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ final class CommonSetupGuide: SetupGuideHelpers, SetupGuide {
}

func perform() throws {
print(colorize("\nAssume all 'public' declarations are in use?", .bold))
print(colorize("?", .boldYellow) + " You should choose 'Yes' here if your public interfaces are not used by any selected build target, as may be the case for a framework/library project.")
print(colorize("Assume all 'public' declarations are in use?", .bold))
print(colorize("?", .boldYellow) + " Choose 'Yes' if your project is a framework/library without a main application target.")
configuration.retainPublic = selectBoolean()
}

Expand Down
11 changes: 7 additions & 4 deletions Sources/Frontend/GuidedSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ final class GuidedSetup: SetupGuideHelpers {
let guides: [SetupGuide] = [projectGuide, commonGuide]
try guides.forEach { try $0.perform() }
let options = Array(guides.map { $0.commandLineOptions }.joined())
var shouldSave = false

print(colorize("\nSave configuration to \(Configuration.defaultConfigurationFile)?", .bold))
let shouldSave = selectBoolean()
if configuration.hasNonDefaultValues {
print(colorize("\nSave configuration to \(Configuration.defaultConfigurationFile)?", .bold))
shouldSave = selectBoolean()

if shouldSave {
try configuration.save()
if shouldSave {
try configuration.save()
}
}

print(colorize("\n*", .boldGreen) + " Executing command:")
Expand Down
2 changes: 1 addition & 1 deletion Sources/Frontend/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ final class Project {
static func identify() -> Self {
let configuration = Configuration.shared

if configuration.workspace != nil || configuration.project != nil {
if configuration.project != nil {
return self.init(kind: .xcode)
} else if !configuration.fileTargetsPath.isEmpty {
return self.init(kind: .generic)
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
Loading