Skip to content

Commit 2b3cd75

Browse files
committed
detach cmd-l from inline completions
instead use a method call, so can disable inline completions fully when autocomplete is turned of
1 parent d6448fd commit 2b3cd75

File tree

2 files changed

+181
-2
lines changed

2 files changed

+181
-2
lines changed

src/services/ghost/GhostServiceManager.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,41 @@ export class GhostServiceManager {
276276
await this.load()
277277
}
278278

279-
// Trigger the inline completion provider
280-
await vscode.commands.executeCommand("editor.action.inlineSuggest.trigger")
279+
// Call the inline completion provider directly with manual trigger context
280+
const position = editor.selection.active
281+
const context: vscode.InlineCompletionContext = {
282+
triggerKind: vscode.InlineCompletionTriggerKind.Invoke,
283+
selectedCompletionInfo: undefined,
284+
}
285+
const tokenSource = new vscode.CancellationTokenSource()
286+
287+
try {
288+
const completions = await this.inlineCompletionProvider.provideInlineCompletionItems(
289+
document,
290+
position,
291+
context,
292+
tokenSource.token,
293+
)
294+
295+
// If we got completions, directly insert the first one
296+
if (completions && (Array.isArray(completions) ? completions.length > 0 : completions.items.length > 0)) {
297+
const items = Array.isArray(completions) ? completions : completions.items
298+
const firstCompletion = items[0]
299+
300+
if (firstCompletion && firstCompletion.insertText) {
301+
const insertText =
302+
typeof firstCompletion.insertText === "string"
303+
? firstCompletion.insertText
304+
: firstCompletion.insertText.value
305+
306+
await editor.edit((editBuilder) => {
307+
editBuilder.insert(position, insertText)
308+
})
309+
}
310+
}
311+
} finally {
312+
tokenSource.dispose()
313+
}
281314
}
282315

283316
private async updateGlobalContext() {

src/services/ghost/__tests__/GhostServiceManager.spec.ts

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,150 @@ console.log('test');]]></replace></change>`
144144
expect(result.suggestions.hasSuggestions()).toBe(true)
145145
})
146146
})
147+
148+
describe("codeSuggestion", () => {
149+
it("should call provideInlineCompletionItems and directly insert completion", async () => {
150+
// This test verifies that codeSuggestion calls the provider directly
151+
// and inserts the completion without using the VSCode inline suggest UI
152+
const initialContent = `console.log('test');`
153+
const { mockDocument } = await setupTestDocument("test.js", initialContent)
154+
155+
const suggestionText = "// suggestion"
156+
157+
// Mock the inline completion provider
158+
const mockProvider = {
159+
provideInlineCompletionItems: vi.fn().mockResolvedValue([
160+
{
161+
insertText: suggestionText,
162+
range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)),
163+
},
164+
]),
165+
}
166+
167+
// Mock editor.edit
168+
const mockEdit = vi.fn().mockImplementation((callback) => {
169+
const editBuilder = {
170+
insert: vi.fn(),
171+
}
172+
callback(editBuilder)
173+
return Promise.resolve(true)
174+
})
175+
176+
// Mock the GhostServiceManager instance with necessary properties
177+
const mockManager = {
178+
inlineCompletionProvider: mockProvider,
179+
model: { loaded: true },
180+
taskId: null,
181+
async hasAccess(_document: any) {
182+
return true
183+
},
184+
async load() {},
185+
async codeSuggestion() {
186+
const editor = vscode.window.activeTextEditor
187+
if (!editor) {
188+
return
189+
}
190+
191+
const document = editor.document
192+
if (!(await this.hasAccess(document))) {
193+
return
194+
}
195+
196+
if (!this.model.loaded) {
197+
await this.load()
198+
}
199+
200+
const position = editor.selection.active
201+
const context: vscode.InlineCompletionContext = {
202+
triggerKind: 1, // InlineCompletionTriggerKind.Invoke
203+
selectedCompletionInfo: undefined,
204+
}
205+
const tokenSource = {
206+
token: { isCancellationRequested: false, onCancellationRequested: vi.fn() },
207+
dispose: vi.fn(),
208+
}
209+
210+
try {
211+
const completions = await this.inlineCompletionProvider.provideInlineCompletionItems(
212+
document,
213+
position,
214+
context,
215+
tokenSource.token,
216+
)
217+
218+
if (
219+
completions &&
220+
(Array.isArray(completions) ? completions.length > 0 : completions.items.length > 0)
221+
) {
222+
const items = Array.isArray(completions) ? completions : completions.items
223+
const firstCompletion = items[0]
224+
225+
if (firstCompletion && firstCompletion.insertText) {
226+
const insertText =
227+
typeof firstCompletion.insertText === "string"
228+
? firstCompletion.insertText
229+
: firstCompletion.insertText.value
230+
231+
await editor.edit((editBuilder) => {
232+
editBuilder.insert(position, insertText)
233+
})
234+
}
235+
}
236+
} finally {
237+
tokenSource.dispose()
238+
}
239+
},
240+
}
241+
242+
// Set up active editor with mock edit function
243+
;(vscode.window as any).activeTextEditor = {
244+
document: mockDocument,
245+
selection: {
246+
active: new vscode.Position(0, 0),
247+
},
248+
edit: mockEdit,
249+
}
250+
251+
// Call codeSuggestion
252+
await mockManager.codeSuggestion()
253+
254+
// Verify that provideInlineCompletionItems was called with correct parameters
255+
expect(mockProvider.provideInlineCompletionItems).toHaveBeenCalledWith(
256+
mockDocument,
257+
expect.any(vscode.Position),
258+
expect.objectContaining({
259+
triggerKind: 1, // InlineCompletionTriggerKind.Invoke
260+
}),
261+
expect.any(Object),
262+
)
263+
264+
// Verify that editor.edit was called to insert the completion
265+
expect(mockEdit).toHaveBeenCalled()
266+
})
267+
268+
it("should not call provider when no active editor", async () => {
269+
const mockProvider = {
270+
provideInlineCompletionItems: vi.fn(),
271+
}
272+
273+
const mockManager = {
274+
inlineCompletionProvider: mockProvider,
275+
async codeSuggestion() {
276+
const editor = vscode.window.activeTextEditor
277+
if (!editor) {
278+
return
279+
}
280+
// Rest of the logic would go here
281+
},
282+
}
283+
284+
// No active editor
285+
;(vscode.window as any).activeTextEditor = null
286+
287+
await mockManager.codeSuggestion()
288+
289+
// Verify provider was not called
290+
expect(mockProvider.provideInlineCompletionItems).not.toHaveBeenCalled()
291+
})
292+
})
147293
})

0 commit comments

Comments
 (0)