Skip to content

Commit 0d20682

Browse files
[Feature] Add new IndexStore indexer variant (#67)
1 parent f9d34da commit 0d20682

23 files changed

+2013
-684
lines changed

Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let package = Package(
1717
.package(url: "https://github.com/kylef/PathKit", from: "1.0.0"),
1818
.package(name: "SwiftSyntax", url: "https://github.com/apple/swift-syntax", .exact("0.50200.0")),
1919
.package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "0.0.4")),
20+
.package(url: "https://github.com/apple/swift-tools-support-core.git", .branch("master")),
2021
],
2122
targets: [
2223
.target(
@@ -32,6 +33,7 @@ let package = Package(
3233
.product(name: "PathKit", package: "PathKit"),
3334
.product(name: "SwiftSyntax", package: "SwiftSyntax"),
3435
.product(name: "ArgumentParser", package: "swift-argument-parser"),
36+
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"),
3537
]
3638
),
3739
.testTarget(

Sources/PeripheryKit/Analyzer/Visitors/UnreadSimplePropertyReferenceEliminator.swift

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ final class UnreadSimplePropertyReferenceEliminator: SourceGraphVisitor {
1616
self.configuration = configuration
1717
}
1818

19+
func transformToGetterUsr(fromMangledSetterUsr usr: String) -> String {
20+
var usr = usr
21+
assert(usr.last == "s")
22+
usr.removeLast()
23+
usr.append("g")
24+
return usr
25+
}
26+
27+
func transformToPropertyUsr(fromMangledSetterUsr usr: String) -> String {
28+
var usr = usr
29+
assert(usr.last == "s")
30+
usr.removeLast()
31+
usr.append("p")
32+
return usr
33+
}
34+
35+
1936
func visit() {
2037
guard configuration.aggressive else { return }
2138

@@ -25,16 +42,32 @@ final class UnreadSimplePropertyReferenceEliminator: SourceGraphVisitor {
2542
let references = graph.references(to: setter)
2643

2744
for reference in references {
28-
// Parent should be a reference to a simple property.
29-
guard let propertyReference = reference.parent as? Reference,
30-
let property = graph.declaration(withUsr: propertyReference.usr),
31-
!property.isComplexProperty else { continue }
32-
33-
// If the property reference has no other descendent references we can remove it.
34-
if propertyReference.references == [reference] {
35-
graph.remove(propertyReference)
36-
property.analyzerHints.append(.unreadProperty)
37-
property.analyzerHints.append(.aggressive)
45+
if configuration.useIndexStore {
46+
guard let caller = reference.parent else { continue }
47+
let getterUsr = transformToGetterUsr(fromMangledSetterUsr: reference.usr)
48+
let propertyUsr = transformToPropertyUsr(fromMangledSetterUsr: reference.usr)
49+
50+
guard let property = graph.declaration(withUsr: propertyUsr),
51+
let propertyReference = caller.references.first(where: { $0.usr == propertyUsr }),
52+
!property.isComplexProperty else { continue }
53+
54+
let hasGetterReference = caller.references.contains(where: { $0.kind == .functionAccessorGetter && $0.usr == getterUsr })
55+
if !hasGetterReference {
56+
graph.remove(propertyReference)
57+
property.analyzerHints.append(.unreadProperty)
58+
property.analyzerHints.append(.aggressive)
59+
}
60+
} else {
61+
// Parent should be a reference to a simple property.
62+
guard let propertyReference = reference.parent as? Reference,
63+
let property = graph.declaration(withUsr: propertyReference.usr),
64+
!property.isComplexProperty else { continue }
65+
// If the property reference has no other descendent references we can remove it.
66+
if propertyReference.references == [reference] {
67+
graph.remove(propertyReference)
68+
property.analyzerHints.append(.unreadProperty)
69+
property.analyzerHints.append(.aggressive)
70+
}
3871
}
3972
}
4073
}

Sources/PeripheryKit/Cache.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Foundation
2+
3+
class Cache<Key: Hashable, T> {
4+
private var values = [Key: T]()
5+
private let lock = NSLock()
6+
7+
private let factory: (Key) throws -> T
8+
init(_ factory: @escaping (Key) throws -> T) {
9+
self.factory = factory
10+
}
11+
12+
func get(_ input: Key) throws -> T {
13+
lock.lock(); defer { lock.unlock() }
14+
return try values[input] ?? factory(input)
15+
}
16+
}

Sources/PeripheryKit/Configuration.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public final class Configuration: Singleton {
3030
var diagnosisConsole: Bool = false
3131
var strict: Bool = false
3232
var xcargs: String? = nil
33+
var useIndexStore: Bool = false
34+
var indexStorePath: String?
3335

3436
// Non user facing.
3537
var guidedSetup: Bool = false
@@ -57,7 +59,9 @@ public final class Configuration: Singleton {
5759
"disable_update_check": !updateCheck,
5860
"diagnose": diagnosisConsole,
5961
"strict": strict,
60-
"xcargs": xcargs
62+
"xcargs": xcargs,
63+
"use_index_store": useIndexStore,
64+
"index_store_path": indexStorePath
6165
]
6266

6367
return try Yams.dump(object: config)
@@ -144,6 +148,14 @@ public final class Configuration: Singleton {
144148
if let value = yaml["xcargs"] as? String {
145149
self.xcargs = value
146150
}
151+
152+
if let value = yaml["use_index_store"] as? Bool {
153+
self.useIndexStore = value
154+
}
155+
156+
if let value = yaml["index_store_path"] as? String {
157+
self.indexStorePath = value
158+
}
147159
}
148160

149161
// MARK: - Helpers

Sources/PeripheryKit/Frontend/Commands/ScanCommand.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Foundation
22
import ArgumentParser
3+
import TSCBasic
34

45
public struct ScanCommand: ParsableCommand {
56

@@ -68,6 +69,12 @@ public struct ScanCommand: ParsableCommand {
6869
@Option(help: "Pass additional arguments to xcodebuild for the build phase")
6970
var xcargs: String?
7071

72+
@Flag(inversion: .prefixedNo, help: "Enable new indexing system using IndexStore")
73+
var useIndexStore: Bool?
74+
75+
@Option(help: "Path to index that should be loaded. e.g. DerivedData/PROJECT/Index/DataStore")
76+
var indexStorePath: String?
77+
7178
public init() {}
7279

7380
public func run() throws {
@@ -149,6 +156,23 @@ public struct ScanCommand: ParsableCommand {
149156
configuration.xcargs = xcargs
150157
}
151158

159+
if let useIndexStore = useIndexStore {
160+
configuration.useIndexStore = useIndexStore
161+
}
162+
163+
if let indexStorePath = indexStorePath {
164+
configuration.indexStorePath = indexStorePath
165+
}
166+
167+
if configuration.indexStorePath == nil && configuration.useIndexStore,
168+
let buildRootEnv = ProcessInfo.processInfo.environment["BUILD_ROOT"] {
169+
let buildRootPath = AbsolutePath(buildRootEnv)
170+
configuration.indexStorePath = buildRootPath
171+
.parentDirectory.parentDirectory
172+
.appending(components: "Index", "DataStore")
173+
.pathString
174+
}
175+
152176
if let formatName = format {
153177
configuration.outputFormat = try OutputFormat.make(named: formatName)
154178
}

Sources/PeripheryKit/Indexer/Entity.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ protocol Entity: CustomStringConvertible, AnyObject {
55
var declarations: Set<Declaration> { get set }
66
var references: Set<Reference> { get set }
77
var parent: Entity? { get set }
8+
var usr: String { get }
89
}

0 commit comments

Comments
 (0)