Skip to content

Commit

Permalink
Add option to select --retain-objc-annotated to setup guide
Browse files Browse the repository at this point in the history
  • Loading branch information
ileitch committed Dec 19, 2024
1 parent 1dbeebc commit 9e5505e
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Sources/Frontend/CommonSetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class CommonSetupGuide: SetupGuideHelpers {

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

Expand Down
5 changes: 3 additions & 2 deletions Sources/Frontend/GuidedSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ final class GuidedSetup: SetupGuideHelpers {
let kindName = select(single: projectGuides.map(\.projectKindName))
projectGuide_ = projectGuides.first { $0.projectKindName == kindName }
print("")
} else {
projectGuide_ = projectGuides.first
} else if let singleGuide = projectGuides.first {
print(colorize("*", .boldGreen) + " Detected \(singleGuide.projectKindName) project")
projectGuide_ = singleGuide
}

guard let projectGuide = projectGuide_ else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Frontend/SPMProjectSetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class SPMProjectSetupGuide: SetupGuideHelpers, SetupGuide {
}

var projectKindName: String {
"Swift Project Manager"
"Swift Package"
}

func perform() throws -> ProjectKind {
Expand Down
46 changes: 19 additions & 27 deletions Sources/Shared/SetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ open class SetupGuideHelpers {
}

public func select(single options: [String]) -> String {
print(colorize("?", .boldYellow) + " Type the number for the option you wish to select")
display(options: options)
print(colorize("> ", .bold), terminator: "")
print(colorize("?", .boldYellow) + " Type the number for the option you wish to select")
print(colorize("=> ", .bold), terminator: "")

if let strChoice = readLine(strippingNewline: true)?.trimmed,
let choice = Int(strChoice)
Expand All @@ -51,48 +51,40 @@ open class SetupGuideHelpers {
return select(single: options)
}

public func select(multiple options: [String], allowAll: Bool) -> SetupSelection {
public func select(multiple options: [String]) -> SetupSelection {
var helpMsg = " Delimit choices with a single space, e.g: 1 2 3"

if allowAll {
helpMsg += ", or 'all' to select all options"
}

print(colorize("?", .boldYellow) + helpMsg)
display(options: options)
print(colorize("> ", .bold), terminator: "")
print(colorize("?", .boldYellow) + helpMsg)
print(colorize("=> ", .bold), terminator: "")

if let strChoices = readLine(strippingNewline: true)?.trimmed.split(separator: " ", omittingEmptySubsequences: true) {
if allowAll, strChoices.contains("all") {
return .all(options)
} else {
var selected: [String] = []

for strChoice in strChoices {
if let choice = Int(strChoice),
let option = options[safe: choice - 1]
{
selected.append(option)
} else {
print(colorize("\nInvalid option: \(strChoice)\n", .boldYellow))
return select(multiple: options, allowAll: allowAll)
}
var selected: [String] = []

for strChoice in strChoices {
if let choice = Int(strChoice),
let option = options[safe: choice - 1]
{
selected.append(option)
} else {
print(colorize("\nInvalid option: \(strChoice)\n", .boldYellow))
return select(multiple: options)
}

if !selected.isEmpty { return .some(selected) }
}

if !selected.isEmpty { return .some(selected) }
}

print(colorize("\nInvalid input, expected a number.\n", .boldYellow))
return select(multiple: options, allowAll: allowAll)
return select(multiple: options)
}

public func selectBoolean() -> Bool {
print(
"(" + colorize("Y", .boldGreen) + ")es" +
"/" +
"(" + colorize("N", .boldGreen) + ")o" +
colorize(" > ", .bold),
colorize("\n=> ", .bold),
terminator: ""
)

Expand Down
34 changes: 28 additions & 6 deletions Sources/XcodeSupport/XcodeProjectSetupGuide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,30 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, SetupGuide {
project
).map { $0 }.sorted()

print(colorize("\nSelect the schemes necessary to build your chosen targets:", .bold))
configuration.schemes = select(multiple: schemes, allowAll: false).selectedValues

print(colorize("\nAssume Objective-C accessible declarations are in use?", .bold))
print(colorize("?", .boldYellow) + " Declarations exposed to the Objective-C runtime explicitly with @objc, or implicitly by inheriting NSObject will be assumed to be in use. Choose 'No' if your project is pure Swift.")
configuration.retainObjcAccessible = selectBoolean()
print(colorize("\nSelect the schemes to build:", .bold))
print("Periphery will scan all files built by your chosen schemes.")
configuration.schemes = select(multiple: schemes).selectedValues

print(colorize("\nDoes this project contain Objective-C code?", .bold))
let containsObjC = selectBoolean()

if containsObjC {
print(colorize("\nPeriphery cannot scan Objective-C code and, as a result, cannot detect Swift types referenced by Objective-C code.", .bold))
print("To avoid false positives, you have a few options:")
let retainObjcAccessibleOption = colorize("Assume all types accessible from Objective-C are in use:", .bold) + " This includes public NSObject instances (and their subclasses), as well as any types explicitly annotated with @objc. This approach will eliminate false positives but may also result in a lot of missed unused code."
let retainObjcAnnotationOption = colorize("Assume only types annotated with @objc are in use:", .bold) + " This option may lead to false positives, but they can be easily corrected by adding the necessary @objc annotations."
let objcChoice = select(single: [
retainObjcAccessibleOption,
retainObjcAnnotationOption,
colorize("Do nothing:", .bold) + " Do not assume any Swift types are used in Objective-C code.",
])

if objcChoice == retainObjcAccessibleOption {
configuration.retainObjcAccessible = true
} else if objcChoice == retainObjcAnnotationOption {
configuration.retainObjcAnnotated = true
}
}

return .xcode(projectPath: project.path)
}
Expand All @@ -108,6 +126,10 @@ public final class XcodeProjectSetupGuide: SetupGuideHelpers, SetupGuide {
options.append("--retain-objc-accessible")
}

if configuration.retainObjcAnnotated {
options.append("--retain-objc-annotated")
}

return options
}

Expand Down

0 comments on commit 9e5505e

Please sign in to comment.