diff --git a/Extension/.scripts/common.ts b/Extension/.scripts/common.ts index 598ff97e8f..91adc0e302 100644 --- a/Extension/.scripts/common.ts +++ b/Extension/.scripts/common.ts @@ -48,7 +48,7 @@ export const Git = async (...args: Parameters>) => (awa export const GitClean = async (...args: Parameters>) => (await new Command(await git, 'clean'))(...args); export async function getModifiedIgnoredFiles() { - const {code, error, stdio } = await GitClean('-Xd', '-n'); + const { code, error, stdio } = await GitClean('-Xd', '-n'); if (code) { throw new Error(`\n${error.all().join('\n')}`); } @@ -65,11 +65,11 @@ export async function rimraf(...paths: string[]) { } if (await filepath.isFolder(each)) { verbose(`Removing folder ${red(each)}`); - all.push(rm(each, {recursive: true, force: true})); + all.push(rm(each, { recursive: true, force: true })); continue; } verbose(`Removing file ${red(each)}`); - all.push(rm(each, {force: true})); + all.push(rm(each, { force: true })); } await Promise.all(all); } @@ -345,3 +345,15 @@ export async function checkBinaries() { } return failing; } + +export async function checkProposals() { + let failing = false; + + await rm(`${$root}/vscode.proposed.chatParticipantAdditions.d.ts`); + failing = await assertAnyFile('vscode.proposed.chatParticipantAdditions.d.ts') && (quiet || warn(`The VSCode import file '${$root}/vscode.proposed.chatParticipantAdditions.d.ts' should not be present.`)) || failing; + + if (!failing) { + verbose('VSCode proposals appear to be in place.'); + } + return failing; +} diff --git a/Extension/.scripts/verify.ts b/Extension/.scripts/verify.ts index d6ed9896d3..ccfaac49d8 100644 --- a/Extension/.scripts/verify.ts +++ b/Extension/.scripts/verify.ts @@ -3,7 +3,7 @@ * See 'LICENSE' in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import { checkBinaries, checkCompiled, checkDTS, checkPrep, error, green } from './common'; +import { checkBinaries, checkCompiled, checkDTS, checkPrep, checkProposals, error, green } from './common'; const quiet = process.argv.includes('--quiet'); export async function main() { @@ -50,3 +50,12 @@ export async function dts() { process.exit(1); } } + +export async function proposals() { + let failing = false; + failing = (await checkProposals() && (quiet || error(`Issue with VSCode proposals. Run ${green('yarn prep')} to fix it.`))) || failing; + + if (failing) { + process.exit(1); + } +} diff --git a/Extension/package.json b/Extension/package.json index db1fb79e18..beb9757a5f 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -38,7 +38,8 @@ "Snippets" ], "enabledApiProposals": [ - "terminalDataWriteEvent" + "terminalDataWriteEvent", + "chatParticipantAdditions" ], "capabilities": { "untrustedWorkspaces": { @@ -6537,7 +6538,7 @@ "translations-generate": "set NODE_OPTIONS=--no-experimental-fetch && gulp translations-generate", "translations-import": "gulp translations-import", "import-edge-strings": "ts-node -T ./.scripts/import_edge_strings.ts", - "prep:dts": "yarn verify dts --quiet || (npx @vscode/dts dev && npx @vscode/dts main)", + "prep:dts": "yarn verify dts --quiet || (npx @vscode/dts main && npx @vscode/dts dev && yarn verify proposals)", "build": "yarn prep:dts && echo [Building TypeScript code] && tsc --build tsconfig.json" }, "devDependencies": { diff --git a/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts b/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts index a6d052895b..05a5ecb8c7 100644 --- a/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts +++ b/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import { Position, ResponseError } from 'vscode-languageclient'; import * as nls from 'vscode-nls'; -import { DefaultClient, GetCopilotHoverInfoParams, GetCopilotHoverInfoRequest } from '../client'; +import { DefaultClient, GetCopilotHoverInfoParams, GetCopilotHoverInfoRequest, GetCopilotHoverInfoResult } from '../client'; import { RequestCancelled, ServerCancelled } from '../protocolFilter'; import { CppSettings } from '../settings'; @@ -92,8 +92,8 @@ export class CopilotHoverProvider implements vscode.HoverProvider { return this.currentCancellationToken; } - public async getRequestInfo(document: vscode.TextDocument, position: vscode.Position): Promise { - let requestInfo = ""; + public async getRequestInfo(document: vscode.TextDocument, position: vscode.Position): Promise { + let response: GetCopilotHoverInfoResult; const params: GetCopilotHoverInfoParams = { textDocument: { uri: document.uri.toString() }, position: Position.create(position.line, position.character) @@ -105,8 +105,7 @@ export class CopilotHoverProvider implements vscode.HoverProvider { } try { - const response = await this.client.languageClient.sendRequest(GetCopilotHoverInfoRequest, params, this.currentCancellationToken); - requestInfo = response.content; + response = await this.client.languageClient.sendRequest(GetCopilotHoverInfoRequest, params, this.currentCancellationToken); } catch (e: any) { if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) { throw new vscode.CancellationError(); @@ -114,7 +113,7 @@ export class CopilotHoverProvider implements vscode.HoverProvider { throw e; } - return requestInfo; + return response; } public isCancelled(document: vscode.TextDocument, position: vscode.Position): boolean { diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 46e2b71cac..94f719e909 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -540,8 +540,9 @@ export interface GetCopilotHoverInfoParams { position: Position; } -interface GetCopilotHoverInfoResult { +export interface GetCopilotHoverInfoResult { content: string; + files: string[]; } export interface ChatContextResult { diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 642831c25c..87ac5d6e57 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -11,7 +11,7 @@ import * as StreamZip from 'node-stream-zip'; import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import { Range } from 'vscode-languageclient'; +import { CancellationToken, Range } from 'vscode-languageclient'; import * as nls from 'vscode-nls'; import { TargetPopulation } from 'vscode-tas-client'; import * as which from 'which'; @@ -1430,10 +1430,26 @@ async function onCopilotHover(): Promise { // Gather the content for the query from the client. const requestInfo = await copilotHoverProvider.getRequestInfo(hoverDocument, hoverPosition); - if (requestInfo.length === 0) { + try { + for (const file of requestInfo.files) { + const fileUri = vscode.Uri.file(file); + if (await vscodelm.fileIsIgnored(fileUri, copilotHoverProvider.getCurrentHoverCancellationToken() ?? CancellationToken.None)) { + telemetry.logLanguageServerEvent("CopilotHover", { "Message": "Copilot summary is not available due to content exclusion." }); + await showCopilotContent(copilotHoverProvider, hoverDocument, hoverPosition, localize("copilot.hover.unavailable", "Copilot summary is not available.") + "\n\n" + + localize("copilot.hover.excluded", "The file containing this symbol's definition or declaration has been excluded from use with Copilot.")); + return; + } + } + } catch (err) { + if (err instanceof Error) { + await reportCopilotFailure(copilotHoverProvider, hoverDocument, hoverPosition, err.message); + } + return; + } + if (requestInfo.content.length === 0) { // Context is not available for this symbol. telemetry.logLanguageServerEvent("CopilotHover", { "Message": "Copilot summary is not available for this symbol." }); - await showCopilotContent(copilotHoverProvider, hoverDocument, hoverPosition, localize("copilot.hover.unavailable", "Copilot summary is not available for this symbol.")); + await showCopilotContent(copilotHoverProvider, hoverDocument, hoverPosition, localize("copilot.hover.unavailable.symbol", "Copilot summary is not available for this symbol.")); return; } @@ -1441,7 +1457,7 @@ async function onCopilotHover(): Promise { const messages = [ vscode.LanguageModelChatMessage - .User(requestInfo + locale)]; + .User(requestInfo.content + locale)]; const [model] = await vscodelm.selectChatModels(modelSelector);