forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathActiveDocumentContext.swift
More file actions
164 lines (145 loc) · 5.64 KB
/
ActiveDocumentContext.swift
File metadata and controls
164 lines (145 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import Foundation
import SuggestionModel
public struct ActiveDocumentContext {
public var documentURL: URL
public var relativePath: String
public var language: CodeLanguage
public var fileContent: String
public var lines: [String]
public var selectedCode: String
public var selectionRange: CursorRange
public var lineAnnotations: [EditorInformation.LineAnnotation]
public var imports: [String]
public var includes: [String]
public struct FocusedContext {
public struct Context: Equatable {
public var signature: String
public var name: String
public var range: CursorRange
public init(signature: String, name: String, range: CursorRange) {
self.signature = signature
self.name = name
self.range = range
}
}
public var context: [Context]
public var contextRange: CursorRange
public var smallestContextRange: CursorRange
public var codeRange: CursorRange
public var code: String
public var lineAnnotations: [EditorInformation.LineAnnotation]
public var otherLineAnnotations: [EditorInformation.LineAnnotation]
public init(
context: [Context],
contextRange: CursorRange,
smallestContextRange: CursorRange,
codeRange: CursorRange,
code: String,
lineAnnotations: [EditorInformation.LineAnnotation],
otherLineAnnotations: [EditorInformation.LineAnnotation]
) {
self.context = context
self.contextRange = contextRange
self.smallestContextRange = smallestContextRange
self.codeRange = codeRange
self.code = code
self.lineAnnotations = lineAnnotations
self.otherLineAnnotations = otherLineAnnotations
}
}
public var focusedContext: FocusedContext?
public init(
documentURL: URL,
relativePath: String,
language: CodeLanguage,
fileContent: String,
lines: [String],
selectedCode: String,
selectionRange: CursorRange,
lineAnnotations: [EditorInformation.LineAnnotation],
imports: [String],
includes: [String],
focusedContext: FocusedContext? = nil
) {
self.documentURL = documentURL
self.relativePath = relativePath
self.language = language
self.fileContent = fileContent
self.lines = lines
self.selectedCode = selectedCode
self.selectionRange = selectionRange
self.lineAnnotations = lineAnnotations
self.imports = imports
self.includes = includes
self.focusedContext = focusedContext
}
public mutating func moveToFocusedCode() {
moveToCodeContainingRange(selectionRange)
}
public mutating func moveToCodeAroundLine(_ line: Int) {
moveToCodeContainingRange(.init(
start: .init(line: line, character: 0),
end: .init(line: line, character: 0)
))
}
public mutating func expandFocusedRangeToContextRange() {
guard let focusedContext else { return }
moveToCodeContainingRange(focusedContext.contextRange)
}
public mutating func moveToCodeContainingRange(_ range: CursorRange) {
let finder = FocusedCodeFinder(
maxFocusedCodeLineCount: UserDefaults.shared.value(for: \.maxFocusedCodeLineCount)
)
let codeContext = finder.findFocusedCode(
in: .init(documentURL: documentURL, content: fileContent, lines: lines),
containingRange: range,
language: language
)
imports = codeContext.imports
includes = codeContext.includes
let startLine = codeContext.focusedRange.start.line
let endLine = codeContext.focusedRange.end.line
var matchedAnnotations = [EditorInformation.LineAnnotation]()
var otherAnnotations = [EditorInformation.LineAnnotation]()
for annotation in lineAnnotations {
if annotation.line >= startLine, annotation.line <= endLine {
matchedAnnotations.append(annotation)
} else {
otherAnnotations.append(annotation)
}
}
focusedContext = .init(
context: codeContext.scopeContexts,
contextRange: codeContext.contextRange,
smallestContextRange: codeContext.smallestContextRange,
codeRange: codeContext.focusedRange,
code: codeContext.focusedCode,
lineAnnotations: matchedAnnotations,
otherLineAnnotations: otherAnnotations
)
}
public mutating func update(_ info: EditorInformation) {
/// Whenever the file content, relative path, or selection range changes,
/// we should reset the context.
let changed: Bool = {
if info.relativePath != relativePath { return true }
if info.editorContent?.content != fileContent { return true }
if let range = info.editorContent?.selections.first,
range != selectionRange { return true }
return false
}()
documentURL = info.documentURL
relativePath = info.relativePath
language = info.language
fileContent = info.editorContent?.content ?? ""
lines = info.editorContent?.lines ?? []
selectedCode = info.selectedContent
selectionRange = info.editorContent?.selections.first ?? .zero
lineAnnotations = info.editorContent?.lineAnnotations ?? []
imports = []
includes = []
if changed {
moveToFocusedCode()
}
}
}