Skip to content

Commit 22019c5

Browse files
committed
Move FocusedCodeFinder to Tool
1 parent 832d7b7 commit 22019c5

File tree

7 files changed

+183
-126
lines changed

7 files changed

+183
-126
lines changed

Copilot for Xcode.xcodeproj/xcshareddata/xcschemes/Copilot for Xcode.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
buildConfiguration = "Debug">
7777
</AnalyzeAction>
7878
<ArchiveAction
79-
buildConfiguration = "Release"
79+
buildConfiguration = "Debug"
8080
revealArchiveInOrganizer = "YES">
8181
</ArchiveAction>
8282
</Scheme>

Core/Package.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,9 @@ let package = Package(
360360
name: "ActiveDocumentChatContextCollector",
361361
dependencies: [
362362
"ChatContextCollector",
363-
.product(name: "LangChain", package: "Tool"),
364363
.product(name: "OpenAIService", package: "Tool"),
365364
.product(name: "Preferences", package: "Tool"),
366-
.product(name: "ASTParser", package: "Tool"),
367-
.product(name: "SwiftSyntax", package: "swift-syntax"),
368-
.product(name: "SwiftParser", package: "swift-syntax"),
365+
.product(name: "FocusedCodeFinder", package: "Tool"),
369366
],
370367
path: "Sources/ChatContextCollectors/ActiveDocumentChatContextCollector"
371368
),

Core/Sources/ChatContextCollectors/ActiveDocumentChatContextCollector/ActiveDocumentChatContextCollector.swift

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ASTParser
22
import ChatContextCollector
3+
import FocusedCodeFinder
34
import Foundation
45
import OpenAIService
56
import Preferences
@@ -188,107 +189,3 @@ public final class ActiveDocumentChatContextCollector: ChatContextCollector {
188189
}
189190
}
190191

191-
struct ActiveDocumentContext {
192-
var filePath: String
193-
var relativePath: String
194-
var language: CodeLanguage
195-
var fileContent: String
196-
var lines: [String]
197-
var selectedCode: String
198-
var selectionRange: CursorRange
199-
var lineAnnotations: [EditorInformation.LineAnnotation]
200-
var imports: [String]
201-
202-
struct FocusedContext {
203-
var context: [String]
204-
var contextRange: CursorRange
205-
var codeRange: CursorRange
206-
var code: String
207-
var lineAnnotations: [EditorInformation.LineAnnotation]
208-
var otherLineAnnotations: [EditorInformation.LineAnnotation]
209-
}
210-
211-
var focusedContext: FocusedContext?
212-
213-
mutating func moveToFocusedCode() {
214-
moveToCodeContainingRange(selectionRange)
215-
}
216-
217-
mutating func moveToCodeAroundLine(_ line: Int) {
218-
moveToCodeContainingRange(.init(
219-
start: .init(line: line, character: 0),
220-
end: .init(line: line, character: 0)
221-
))
222-
}
223-
224-
mutating func expandFocusedRangeToContextRange() {
225-
guard let focusedContext else { return }
226-
moveToCodeContainingRange(focusedContext.contextRange)
227-
}
228-
229-
mutating func moveToCodeContainingRange(_ range: CursorRange) {
230-
let finder: FocusedCodeFinder = {
231-
switch language {
232-
case .builtIn(.swift):
233-
return SwiftFocusedCodeFinder()
234-
default:
235-
return UnknownLanguageFocusedCodeFinder(proposedSearchRange: 5)
236-
}
237-
}()
238-
239-
let codeContext = finder.findFocusedCode(
240-
containingRange: range,
241-
activeDocumentContext: self
242-
)
243-
244-
imports = codeContext.imports
245-
246-
let startLine = codeContext.focusedRange.start.line
247-
let endLine = codeContext.focusedRange.end.line
248-
var matchedAnnotations = [EditorInformation.LineAnnotation]()
249-
var otherAnnotations = [EditorInformation.LineAnnotation]()
250-
for annotation in lineAnnotations {
251-
if annotation.line >= startLine, annotation.line <= endLine {
252-
matchedAnnotations.append(annotation)
253-
} else {
254-
otherAnnotations.append(annotation)
255-
}
256-
}
257-
258-
focusedContext = .init(
259-
context: codeContext.scopeSignatures,
260-
contextRange: codeContext.contextRange,
261-
codeRange: codeContext.focusedRange,
262-
code: codeContext.focusedCode,
263-
lineAnnotations: matchedAnnotations,
264-
otherLineAnnotations: otherAnnotations
265-
)
266-
}
267-
268-
mutating func update(_ info: EditorInformation) {
269-
/// Whenever the file content, relative path, or selection range changes,
270-
/// we should reset the context.
271-
let changed: Bool = {
272-
if info.relativePath != relativePath { return true }
273-
if info.editorContent?.content != fileContent { return true }
274-
if let range = info.editorContent?.selections.first,
275-
range != selectionRange { return true }
276-
return false
277-
}()
278-
279-
filePath = info.documentURL.path
280-
relativePath = info.relativePath
281-
language = info.language
282-
fileContent = info.editorContent?.content ?? ""
283-
lines = info.editorContent?.lines ?? []
284-
selectedCode = info.selectedContent
285-
selectionRange = info.editorContent?.selections.first ?? .zero
286-
lineAnnotations = info.editorContent?.lineAnnotations ?? []
287-
imports = []
288-
289-
if changed {
290-
moveToFocusedCode()
291-
}
292-
}
293-
}
294-

Tool/Package.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let package = Package(
1717
.library(name: "Environment", targets: ["Environment"]),
1818
.library(name: "SuggestionModel", targets: ["SuggestionModel"]),
1919
.library(name: "ASTParser", targets: ["ASTParser"]),
20+
.library(name: "FocusedCodeFinder", targets: ["FocusedCodeFinder"]),
2021
.library(name: "Toast", targets: ["Toast"]),
2122
.library(name: "Keychain", targets: ["Keychain"]),
2223
.library(name: "SharedUIComponents", targets: ["SharedUIComponents"]),
@@ -47,6 +48,7 @@ let package = Package(
4748
url: "https://github.com/pointfreeco/swift-composable-architecture",
4849
from: "0.55.0"
4950
),
51+
.package(url: "https://github.com/apple/swift-syntax.git", branch: "main"),
5052

5153
// TreeSitter
5254
.package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.7.1"),
@@ -184,6 +186,16 @@ let package = Package(
184186
]
185187
),
186188

189+
.target(
190+
name: "FocusedCodeFinder",
191+
dependencies: [
192+
"Preferences",
193+
"ASTParser",
194+
.product(name: "SwiftSyntax", package: "swift-syntax"),
195+
.product(name: "SwiftParser", package: "swift-syntax"),
196+
]
197+
),
198+
187199
// MARK: - Services
188200

189201
.target(
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import Foundation
2+
import SuggestionModel
3+
4+
public struct ActiveDocumentContext {
5+
public var filePath: String
6+
public var relativePath: String
7+
public var language: CodeLanguage
8+
public var fileContent: String
9+
public var lines: [String]
10+
public var selectedCode: String
11+
public var selectionRange: CursorRange
12+
public var lineAnnotations: [EditorInformation.LineAnnotation]
13+
public var imports: [String]
14+
15+
public struct FocusedContext {
16+
public var context: [String]
17+
public var contextRange: CursorRange
18+
public var codeRange: CursorRange
19+
public var code: String
20+
public var lineAnnotations: [EditorInformation.LineAnnotation]
21+
public var otherLineAnnotations: [EditorInformation.LineAnnotation]
22+
23+
public init(
24+
context: [String],
25+
contextRange: CursorRange,
26+
codeRange: CursorRange,
27+
code: String,
28+
lineAnnotations: [EditorInformation.LineAnnotation],
29+
otherLineAnnotations: [EditorInformation.LineAnnotation]
30+
) {
31+
self.context = context
32+
self.contextRange = contextRange
33+
self.codeRange = codeRange
34+
self.code = code
35+
self.lineAnnotations = lineAnnotations
36+
self.otherLineAnnotations = otherLineAnnotations
37+
}
38+
}
39+
40+
public var focusedContext: FocusedContext?
41+
42+
public init(
43+
filePath: String,
44+
relativePath: String,
45+
language: CodeLanguage,
46+
fileContent: String,
47+
lines: [String],
48+
selectedCode: String,
49+
selectionRange: CursorRange,
50+
lineAnnotations: [EditorInformation.LineAnnotation],
51+
imports: [String],
52+
focusedContext: FocusedContext? = nil
53+
) {
54+
self.filePath = filePath
55+
self.relativePath = relativePath
56+
self.language = language
57+
self.fileContent = fileContent
58+
self.lines = lines
59+
self.selectedCode = selectedCode
60+
self.selectionRange = selectionRange
61+
self.lineAnnotations = lineAnnotations
62+
self.imports = imports
63+
self.focusedContext = focusedContext
64+
}
65+
66+
public mutating func moveToFocusedCode() {
67+
moveToCodeContainingRange(selectionRange)
68+
}
69+
70+
public mutating func moveToCodeAroundLine(_ line: Int) {
71+
moveToCodeContainingRange(.init(
72+
start: .init(line: line, character: 0),
73+
end: .init(line: line, character: 0)
74+
))
75+
}
76+
77+
public mutating func expandFocusedRangeToContextRange() {
78+
guard let focusedContext else { return }
79+
moveToCodeContainingRange(focusedContext.contextRange)
80+
}
81+
82+
public mutating func moveToCodeContainingRange(_ range: CursorRange) {
83+
let finder: FocusedCodeFinder = {
84+
switch language {
85+
case .builtIn(.swift):
86+
return SwiftFocusedCodeFinder()
87+
default:
88+
return UnknownLanguageFocusedCodeFinder(proposedSearchRange: 5)
89+
}
90+
}()
91+
92+
let codeContext = finder.findFocusedCode(
93+
containingRange: range,
94+
activeDocumentContext: self
95+
)
96+
97+
imports = codeContext.imports
98+
99+
let startLine = codeContext.focusedRange.start.line
100+
let endLine = codeContext.focusedRange.end.line
101+
var matchedAnnotations = [EditorInformation.LineAnnotation]()
102+
var otherAnnotations = [EditorInformation.LineAnnotation]()
103+
for annotation in lineAnnotations {
104+
if annotation.line >= startLine, annotation.line <= endLine {
105+
matchedAnnotations.append(annotation)
106+
} else {
107+
otherAnnotations.append(annotation)
108+
}
109+
}
110+
111+
focusedContext = .init(
112+
context: codeContext.scopeSignatures,
113+
contextRange: codeContext.contextRange,
114+
codeRange: codeContext.focusedRange,
115+
code: codeContext.focusedCode,
116+
lineAnnotations: matchedAnnotations,
117+
otherLineAnnotations: otherAnnotations
118+
)
119+
}
120+
121+
public mutating func update(_ info: EditorInformation) {
122+
/// Whenever the file content, relative path, or selection range changes,
123+
/// we should reset the context.
124+
let changed: Bool = {
125+
if info.relativePath != relativePath { return true }
126+
if info.editorContent?.content != fileContent { return true }
127+
if let range = info.editorContent?.selections.first,
128+
range != selectionRange { return true }
129+
return false
130+
}()
131+
132+
filePath = info.documentURL.path
133+
relativePath = info.relativePath
134+
language = info.language
135+
fileContent = info.editorContent?.content ?? ""
136+
lines = info.editorContent?.lines ?? []
137+
selectedCode = info.selectedContent
138+
selectionRange = info.editorContent?.selections.first ?? .zero
139+
lineAnnotations = info.editorContent?.lineAnnotations ?? []
140+
imports = []
141+
142+
if changed {
143+
moveToFocusedCode()
144+
}
145+
}
146+
}
147+

Core/Sources/ChatContextCollectors/ActiveDocumentChatContextCollector/FocusedCodeFinder/FocusedCodeFinder.swift renamed to Tool/Sources/FocusedCodeFinder/FocusedCodeFinder.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Foundation
22
import SuggestionModel
33

4-
struct CodeContext: Equatable {
5-
enum Scope: Equatable {
4+
public struct CodeContext: Equatable {
5+
public enum Scope: Equatable {
66
case file
77
case top
88
case scope(signature: [String])
99
}
1010

11-
var scopeSignatures: [String] {
11+
public var scopeSignatures: [String] {
1212
switch scope {
1313
case .file:
1414
return []
@@ -19,32 +19,32 @@ struct CodeContext: Equatable {
1919
}
2020
}
2121

22-
var scope: Scope
23-
var contextRange: CursorRange
24-
var focusedRange: CursorRange
25-
var focusedCode: String
26-
var imports: [String]
22+
public var scope: Scope
23+
public var contextRange: CursorRange
24+
public var focusedRange: CursorRange
25+
public var focusedCode: String
26+
public var imports: [String]
2727

28-
static var empty: CodeContext {
28+
public static var empty: CodeContext {
2929
.init(scope: .file, contextRange: .zero, focusedRange: .zero, focusedCode: "", imports: [])
3030
}
3131
}
3232

33-
protocol FocusedCodeFinder {
33+
public protocol FocusedCodeFinder {
3434
func findFocusedCode(
3535
containingRange: CursorRange,
3636
activeDocumentContext: ActiveDocumentContext
3737
) -> CodeContext
3838
}
3939

40-
struct UnknownLanguageFocusedCodeFinder: FocusedCodeFinder {
40+
public struct UnknownLanguageFocusedCodeFinder: FocusedCodeFinder {
4141
let proposedSearchRange: Int
4242

43-
init(proposedSearchRange: Int) {
43+
public init(proposedSearchRange: Int) {
4444
self.proposedSearchRange = proposedSearchRange
4545
}
4646

47-
func findFocusedCode(
47+
public func findFocusedCode(
4848
containingRange: CursorRange,
4949
activeDocumentContext: ActiveDocumentContext
5050
) -> CodeContext {

0 commit comments

Comments
 (0)