Skip to content

Commit a9f75b1

Browse files
committed
cleanup after adding dependecies
1 parent 184236e commit a9f75b1

File tree

3 files changed

+38
-248
lines changed

3 files changed

+38
-248
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct RegisteredDependencyValue: Hashable {
2+
let variableName: String
3+
let symbolName: String
4+
}

Core/Sources/Service/MultiFileContext/MultiFileContextManager.swift

Lines changed: 4 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ public class MultiFileContextManager {
44
private let workspaceProvider: WorkspaceProvider
55
private let parser: ProgrammingLanguageSyntaxParser
66

7-
// cache so we don’t re-parse the file every time
8-
// private var cachedSwiftDependenciesKeys: [String: String]?
9-
107
public init(workspaceProvider: WorkspaceProvider, parser: ProgrammingLanguageSyntaxParser) {
118
self.workspaceProvider = workspaceProvider
129
self.parser = parser
@@ -36,60 +33,9 @@ public class MultiFileContextManager {
3633
return files
3734
}
3835

39-
/// List files within dependency directories
40-
/// This is currently not used as it is too expensive to run
41-
// private func listDependencyFiles() async -> [String] {
42-
// guard let root = try? await workspaceProvider.getProjectRootURL() else { return [] }
43-
// var files: [String] = []
44-
// let fm = FileManager.default
45-
// let depRoots: [URL] = [
46-
// root.appendingPathComponent("Tuist/.build/checkouts", isDirectory: true),
47-
// root.appendingPathComponent("SourcePackages/checkouts", isDirectory: true),
48-
// root.appendingPathComponent(".swiftpm/xcode/checkout", isDirectory: true)
49-
// ].filter { fm.fileExists(atPath: $0.path) }
50-
//
51-
// for base in depRoots {
52-
// if let e = fm.enumerator(
53-
// at: base,
54-
// includingPropertiesForKeys: [.isRegularFileKey],
55-
// options: [.skipsPackageDescendants] // keep this to avoid .xcodeproj/.app bundles
56-
// ) {
57-
// for case let url as URL in e {
58-
// guard url.pathExtension.lowercased() == "swift" else { continue }
59-
// // (Optional) only Sources, to avoid Tests/Examples
60-
// // guard url.path.contains("/Sources/") else { continue }
61-
// files.append(url.absoluteString)
62-
// }
63-
// }
64-
// }
65-
// return files
66-
// }
67-
68-
/// Looks up `swift-dependencies/Sources/Dependencies/DependencyValues.swift`
69-
/// under common checkout roots relative to the workspace.
70-
// func loadSwiftDependenciesDependencyValuesFile() async throws -> [String: String] {
71-
// guard let root = try? await workspaceProvider.getProjectRootURL() else { return [:] }
72-
//
73-
// // candidate locations (Tuist SPM, Xcode SPM, .swiftpm)
74-
// let candidates: [URL] = [
75-
// root.appendingPathComponent("Tuist/.build/checkouts/swift-dependencies/Sources/Dependencies/DependencyValues.swift"),
76-
// root.appendingPathComponent("SourcePackages/checkouts/swift-dependencies/Sources/Dependencies/DependencyValues.swift"),
77-
// root.appendingPathComponent(".swiftpm/xcode/checkout/swift-dependencies/Sources/Dependencies/DependencyValues.swift"),
78-
// ]
79-
//
80-
// let fm = FileManager.default
81-
// guard let fileURL = candidates.first(where: { fm.fileExists(atPath: $0.path) }) else {
82-
// return [:]
83-
// }
84-
//
85-
// let src = try String(contentsOf: fileURL, encoding: .utf8)
86-
// return parseDependencyValuesSource(src)
87-
// }
88-
8936
public func readFileContents(ignoreWithinPaths: [String]) async -> [FileContent] {
9037
let workspaceURLs = await listFilesInWorkspace(ignoreWithinPaths: ignoreWithinPaths)
91-
// let dependencyURLs = await listDependencyFiles()
92-
let fileURLs = workspaceURLs // + dependencyURLs
38+
let fileURLs = workspaceURLs
9339
return fileURLs.compactMap { fileURLString in
9440
guard let fileURL = URL(string: fileURLString) else { return nil }
9541
do {
@@ -128,7 +74,6 @@ public class MultiFileContextManager {
12874

12975
for (name, content) in allSymbols {
13076
if let current = currentSymbolName, current == name { continue }
131-
// if ignoreWithinPaths.contains(where: { content.fileURL.contains($0) }) { continue }
13277

13378
if file.content.containsExactIdentifier(name) {
13479
if relevant[name] == nil {
@@ -147,45 +92,12 @@ public class MultiFileContextManager {
14792
return relevant
14893
}
14994

150-
func retrieveUsedDependencyKeys(file: FileContent, allFiles: [FileContent]) async -> [RegisteredDependencyValue] {
95+
private func retrieveUsedDependencyKeys(file: FileContent, allFiles: [FileContent]) async -> [RegisteredDependencyValue] {
15196
let dependencyValuesExtensions = await scanProjectForDependencyKeys(files: allFiles)
15297
let dependecyVariablesAndTypes = dependencyValuesExtensions.flatMap { getDependencySymbolsFromExtensionContent($0.symbol.content) }
15398
let usedDependencyKeys = file.content.extractDependencyReferences(dependencies: dependecyVariablesAndTypes)
15499
return usedDependencyKeys
155100
}
156-
157-
158-
// public func retrieveRelevantSymbolsForFileContent(
159-
// file: FileContent,
160-
// ignoreWithinPaths: [String] = []
161-
// ) async -> [String: SymbolContent] {
162-
// let currentSymbolName = parser.parse(file: file).first?.symbol.name
163-
// let allSymbols = await classifyContentWithinFiles()
164-
//
165-
// // Build maps
166-
// let propToType = await collectDependencyValueKeys(from: allSymbols) // "errorToastCoordinator" -> "ErrorToastCoordinator"
167-
// let usedKeys = extractDependencyKeys(in: file.content) // e.g. {"errorToastCoordinator"}
168-
//
169-
// // Invert for quick lookup: type -> set of keys
170-
// var keysByType: [String: Set<String>] = [:]
171-
// for (prop, type) in propToType { keysByType[type, default: []].insert(prop) }
172-
//
173-
// var relevant: [String: SymbolContent] = [:]
174-
//
175-
// for (typeName, content) in allSymbols {
176-
// if let current = currentSymbolName, current == typeName { continue }
177-
// if ignoreWithinPaths.contains(where: { content.fileURL.contains($0) }) { continue }
178-
//
179-
// var isReferenced = file.content.containsExactIdentifier(typeName)
180-
// if !isReferenced, let keys = keysByType[typeName], !usedKeys.isDisjoint(with: keys) {
181-
// isReferenced = true
182-
// }
183-
//
184-
// if isReferenced { relevant[typeName] = content }
185-
// }
186-
//
187-
// return relevant
188-
// }
189101

190102
private func mergeExtensionsIntoBaseDeclarations(_ symbols: inout [SymbolContent]) {
191103
var indexesToRemove: [Int] = []
@@ -210,118 +122,7 @@ public class MultiFileContextManager {
210122
}
211123
}
212124

213-
/// Parses the DependencyValues.swift source and returns property -> type mapping.
214-
// func parseDependencyValuesSource(_ src: String) -> [String: String] {
215-
// var map: [String: String] = [:]
216-
//
217-
// // Typed properties
218-
// if let re = try? NSRegularExpression(
219-
// pattern: #"\bvar\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_?.<>]+)\s*\{"#
220-
// ) {
221-
// re.enumerateMatches(in: src, range: NSRange(src.startIndex..., in: src)) { m, _, _ in
222-
// guard
223-
// let m,
224-
// let name = Range(m.range(at: 1), in: src).map({ String(src[$0]) }),
225-
// let type = Range(m.range(at: 2), in: src).map({ String(src[$0]) })
226-
// else { return }
227-
// map[name] = type
228-
// }
229-
// }
230-
//
231-
// // Getter/setter using self[TypeName.self]
232-
// if let re2 = try? NSRegularExpression(
233-
// pattern: #"\bvar\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{[^}]*?self\[\s*([A-Za-z_][A-Za-z0-9_]*)\.self\s*\]"#,
234-
// options: [.dotMatchesLineSeparators]
235-
// ) {
236-
// re2.enumerateMatches(in: src, range: NSRange(src.startIndex..., in: src)) { m, _, _ in
237-
// guard
238-
// let m,
239-
// let name = Range(m.range(at: 1), in: src).map({ String(src[$0]) }),
240-
// let type = Range(m.range(at: 2), in: src).map({ String(src[$0]) })
241-
// else { return }
242-
// if map[name] == nil { map[name] = type }
243-
// }
244-
// }
245-
//
246-
// return map
247-
// }
248-
249-
/// Builds map of DependencyValues property -> backing type.
250-
/// 1) First tries from already parsed project symbols (your extensions).
251-
/// 2) If empty, tries to load from swift-dependencies checkout quickly.
252-
// func collectDependencyValueKeys(from symbols: [String: SymbolContent]) async -> [String: String] {
253-
// var map: [String: String] = [:]
254-
//
255-
// // 1) Project-local extensions (what you already had)
256-
// for (_, content) in symbols {
257-
// guard content.symbol.kind == .extensionWord,
258-
// content.symbol.name == "DependencyValues" else { continue }
259-
//
260-
// let src = content.content
261-
//
262-
// // Typed: var foo: TypeName {
263-
// if let re = try? NSRegularExpression(
264-
// pattern: #"\bvar\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_?.<>]+)\s*\{"#
265-
// ) {
266-
// re.enumerateMatches(in: src, range: NSRange(src.startIndex..., in: src)) { m, _, _ in
267-
// guard
268-
// let m,
269-
// let name = Range(m.range(at: 1), in: src).map({ String(src[$0]) }),
270-
// let type = Range(m.range(at: 2), in: src).map({ String(src[$0]) })
271-
// else { return }
272-
// map[name] = type
273-
// }
274-
// }
275-
//
276-
// // Getter body: self[TypeName.self]
277-
// if let re2 = try? NSRegularExpression(
278-
// pattern: #"\bvar\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{[^}]*?self\[\s*([A-Za-z_][A-Za-z0-9_]*)\.self\s*\]"#,
279-
// options: [.dotMatchesLineSeparators]
280-
// ) {
281-
// re2.enumerateMatches(in: src, range: NSRange(src.startIndex..., in: src)) { m, _, _ in
282-
// guard
283-
// let m,
284-
// let name = Range(m.range(at: 1), in: src).map({ String(src[$0]) }),
285-
// let type = Range(m.range(at: 2), in: src).map({ String(src[$0]) })
286-
// else { return }
287-
// if map[name] == nil { map[name] = type }
288-
// }
289-
// }
290-
// }
291-
//
292-
// if !map.isEmpty { return map } // ✅ found in project
293-
//
294-
// // 2) Fast fallback to the single file from swift-dependencies
295-
// if let cached = cachedSwiftDependenciesKeys { return cached }
296-
//
297-
// if let fast = try? await loadSwiftDependenciesDependencyValuesFile(),
298-
// !fast.isEmpty {
299-
// cachedSwiftDependenciesKeys = fast
300-
// return fast
301-
// }
302-
//
303-
// return map // empty
304-
// }
305-
306-
// Extracts keys like `errorToastCoordinator` from `@Dependency(\.errorToastCoordinator)`
307-
// private func extractDependencyKeys(in source: String) -> Set<String> {
308-
// // Matches: @Dependency(\.fooBar)
309-
// let pattern = #"@Dependency\s*\(\s*\\\.\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)"#
310-
// guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return [] }
311-
//
312-
// var keys = Set<String>()
313-
// let range = NSRange(source.startIndex..., in: source)
314-
// regex.enumerateMatches(in: source, options: [], range: range) { match, _, _ in
315-
// guard
316-
// let match,
317-
// let r = Range(match.range(at: 1), in: source)
318-
// else { return }
319-
// keys.insert(String(source[r]))
320-
// }
321-
// return keys
322-
// }
323-
324-
func scanProjectForDependencyKeys(files: [FileContent]) async -> [SymbolContent] {
125+
private func scanProjectForDependencyKeys(files: [FileContent]) async -> [SymbolContent] {
325126
let allSymbols: [SymbolContent] = files.flatMap { parser.parse(file: $0) }
326127
let dependencyValueExtensions = allSymbols.filter {
327128
$0.symbol.kind == .extensionWord && $0.symbol.name == "DependencyValues"
@@ -331,7 +132,7 @@ public class MultiFileContextManager {
331132

332133
/// Extract every `var <prop>: <Type> { ... }` and/or `self[<Type>.self]` from an
333134
/// `extension DependencyValues { ... }` source string.
334-
func getDependencySymbolsFromExtensionContent(_ content: String) -> [RegisteredDependencyValue] {
135+
private func getDependencySymbolsFromExtensionContent(_ content: String) -> [RegisteredDependencyValue] {
335136
var results = Set<RegisteredDependencyValue>()
336137

337138
// 1) Typed property form: `var fooBar: TypeName {`
@@ -352,35 +153,10 @@ public class MultiFileContextManager {
352153
}
353154
}
354155

355-
// 2) Getter/setter body form: `var foo { get { self[TypeName.self] } ... }`
356-
// (dotMatchesLineSeparators so it works across newlines)
357-
// if let body = try? NSRegularExpression(
358-
// pattern: #"\bvar\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{[^}]*?self\[\s*([A-Za-z_][A-Za-z0-9_?.<>]+)\.self\s*\]"#,
359-
// options: [.dotMatchesLineSeparators]
360-
// ) {
361-
// let range = NSRange(content.startIndex..., in: content)
362-
// body.enumerateMatches(in: content, options: [], range: range) { m, _, _ in
363-
// guard
364-
// let m,
365-
// let nameR = Range(m.range(at: 1), in: content),
366-
// let typeR = Range(m.range(at: 2), in: content)
367-
// else { return }
368-
// let varName = String(content[nameR])
369-
// let typeName = String(content[typeR])
370-
// // Don’t overwrite a typed match if it already exists
371-
// results.insert(.init(variableName: varName, symbolName: typeName))
372-
// }
373-
// }
374-
375156
return Array(results)//.flatMap { $0 }
376157
}
377158
}
378159

379-
struct RegisteredDependencyValue: Hashable {
380-
let variableName: String
381-
let symbolName: String
382-
}
383-
384160
extension String {
385161
/// Checks if the string contains an exact symbol match.
386162
/// Allows any character besides letters, numbers, and underscores as boundaries

Core/Tests/ServiceTests/MultiFileContextManagerTests.swift

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,35 @@ class MultiFileContextManagerTests: XCTestCase {
1212
)
1313
}
1414

15-
func testListingFiles() async {
16-
let sut = sut
17-
let files = await sut.listFilesInWorkspace()
18-
19-
XCTAssertNotEqual(files.count, 0)
20-
}
15+
// func testListingFiles() async {
16+
// let sut = sut
17+
// let files = await sut.listFilesInWorkspace()
18+
//
19+
// XCTAssertNotEqual(files.count, 0)
20+
// }
2121

22-
func testRetrievingFileContent() async {
23-
let sut = sut
24-
let files = await sut.readFileContents()
25-
26-
XCTAssertNotEqual(files.count, 0)
27-
}
22+
// func testRetrievingFileContent() async {
23+
// let sut = sut
24+
// let files = await sut.readFileContents()
25+
//
26+
// XCTAssertNotEqual(files.count, 0)
27+
// }
2828

29-
func testClassifyingCode() async {
30-
let sut = sut
31-
let classifiedSymbols = await sut.classifyContentWithinFiles()
32-
// symbols
33-
XCTAssertNotEqual(classifiedSymbols.count, 0)
34-
}
29+
// func testClassifyingCode() async {
30+
// let sut = sut
31+
// let classifiedSymbols = await sut.classifyContentWithinFiles()
32+
// // symbols
33+
// XCTAssertNotEqual(classifiedSymbols.count, 0)
34+
// }
35+
36+
// func testScanningForDependencyKeys() async {
37+
// let sut = sut
38+
// let dependencyKeys = await sut.scanProjectForDependencyKeys()
39+
// let registeredDependencies = dependencyKeys.map { dependencyKey in
40+
// sut.getDependencySymbolsFromExtensionContent(dependencyKey.symbol.content)
41+
// }
42+
// XCTAssertNotEqual(dependencyKeys.count, 0)
43+
// }
3544
}
3645

3746

@@ -42,12 +51,13 @@ class WorkspaceProviderMock: WorkspaceProvider {
4251
// let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ios-minttv")
4352
// let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ios-minttv/Pod/Classes/Twitch/TwitchEndpoint.swift")
4453
// let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ios-minttv/Pod/Classes/Twitch/Chat/IRC")
45-
let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ios-minttv/Pod/Classes/Twitch/Chat/Presentation/View")
54+
// let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ios-minttv/Pod/Classes/Twitch/Chat/Presentation/View")projectRootURL Foundation.URL "file:///Users/christopherknapp/repos/ModernCleanArchitectureSwiftUI/"
55+
let workspaceURL = URL(filePath: "/Users/christopherknapp/repos/ModernCleanArchitectureSwiftUI/")
4656
return Workspace(workspaceURL: workspaceURL)
4757
}
4858

4959
func getProjectRootURL() async throws -> URL {
50-
URL(filePath: "/Users/christopherknapp/repos/ios-minttv/Pod/Classes/Twitch/Chat/Presentation/View")
60+
URL(filePath: "/Users/christopherknapp/repos/ModernCleanArchitectureSwiftUI/")
5161
}
5262
}
5363

0 commit comments

Comments
 (0)