diff --git a/extensions/vscode/src/autocomplete/__tests__/ContinueCompletionProvider.vitest.ts b/extensions/vscode/src/autocomplete/__tests__/ContinueCompletionProvider.vitest.ts index 9d6e816c69c..df1af8d2500 100644 --- a/extensions/vscode/src/autocomplete/__tests__/ContinueCompletionProvider.vitest.ts +++ b/extensions/vscode/src/autocomplete/__tests__/ContinueCompletionProvider.vitest.ts @@ -2,7 +2,10 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import * as vscode from "vscode"; -import { ContinueCompletionProvider } from "../completionProvider"; +import { + ContinueCompletionProvider, + isNonCodeInputScheme, +} from "../completionProvider"; import * as NextEditLoggingServiceModule from "core/nextEdit/NextEditLoggingService"; import * as PrefetchQueueModule from "core/nextEdit/NextEditPrefetchQueue"; @@ -158,6 +161,90 @@ describe("ContinueCompletionProvider triggering logic", () => { }); }); +describe("isNonCodeInputScheme", () => { + it("returns true for non-code input surfaces", () => { + const deniedSchemes = [ + "vscode-scm", + "comment", + "chatSessionInput", + "vscode-interactive-input", + "vscode-chat-editor", + "chat-editing-text-model", + "output", + "vscode-settings", + ]; + for (const scheme of deniedSchemes) { + expect(isNonCodeInputScheme(scheme)).toBe(true); + } + }); + + it("returns false for real editable document schemes", () => { + const allowedSchemes = [ + "file", + "vscode-remote", + "untitled", + "vscode-notebook-cell", + "vscode-vfs", + ]; + for (const scheme of allowedSchemes) { + expect(isNonCodeInputScheme(scheme)).toBe(false); + } + }); +}); + +describe("ContinueCompletionProvider non-code input schemes", () => { + const deniedSchemes = [ + "vscode-scm", + "comment", + "chatSessionInput", + "vscode-interactive-input", + "vscode-chat-editor", + "chat-editing-text-model", + "output", + "vscode-settings", + ]; + + it.each(deniedSchemes)( + "returns null and does not start a chain for the %s scheme", + async (scheme) => { + const document = createDocument(undefined, `${scheme}:input-0`); + setActiveEditor(document); + + const provider = buildProvider(); + + const result = await provider.provideInlineCompletionItems( + document, + createPosition(), + createContext(), + createToken(), + ); + + expect(result).toBeNull(); + expect(mockNextEditProvider.startChain).not.toHaveBeenCalled(); + expect( + mockNextEditProvider.provideInlineCompletionItems, + ).not.toHaveBeenCalled(); + }, + ); + + it("does not autocomplete inside the Copilot Chat input (chatSessionInput)", async () => { + const document = createDocument(undefined, "chatSessionInput:input-0"); + setActiveEditor(document); + + const provider = buildProvider(); + + const result = await provider.provideInlineCompletionItems( + document, + createPosition(), + createContext(), + createToken(), + ); + + expect(result).toBeNull(); + expect(mockNextEditProvider.startChain).not.toHaveBeenCalled(); + }); +}); + function buildProvider(options: { usingFullFileDiff?: boolean } = {}) { const usingFullFileDiff = options.usingFullFileDiff ?? true; const configHandler = { @@ -181,10 +268,11 @@ function buildProvider(options: { usingFullFileDiff?: boolean } = {}) { function createDocument( text = "function example() {\n return true;\n}", + uri = "file:///test", ): vscode.TextDocument { const lines = text.split("\n"); return { - uri: vscode.Uri.parse("file:///test"), + uri: { scheme: uri.split(":")[0], toString: () => uri }, isUntitled: false, getText: (range?: any) => { if (!range) { diff --git a/extensions/vscode/src/autocomplete/completionProvider.ts b/extensions/vscode/src/autocomplete/completionProvider.ts index 498f971d05d..fc917a21920 100644 --- a/extensions/vscode/src/autocomplete/completionProvider.ts +++ b/extensions/vscode/src/autocomplete/completionProvider.ts @@ -31,6 +31,24 @@ import { stopStatusBarLoading, } from "./statusBar"; +// Schemes belonging to non-code input surfaces (other extensions' chat / comment / +// output boxes) where inline completions must not fire. See issue #12933. +// Ref: VS Code scheme registry (Schemas) in src/vs/base/common/network.ts. +const NON_CODE_INPUT_SCHEMES: Set = new Set([ + "vscode-scm", // SCM commit-message input (was the only prior guard) + "comment", // SCM / review comment input + "chatSessionInput", // Copilot Chat input (current builds) — the #12933 repro + "vscode-interactive-input", // chat / interactive input (older builds — version drift) + "vscode-chat-editor", // chat editor surface (older builds) + "chat-editing-text-model", // chat editing working-copy model + "output", // Output panel (never a code input) + "vscode-settings", // Settings editor input fields +]); + +export function isNonCodeInputScheme(scheme: string): boolean { + return NON_CODE_INPUT_SCHEMES.has(scheme); +} + interface VsCodeCompletionInput { document: vscode.TextDocument; position: vscode.Position; @@ -171,7 +189,7 @@ export class ContinueCompletionProvider return null; } - if (document.uri.scheme === "vscode-scm") { + if (isNonCodeInputScheme(document.uri.scheme)) { return null; }