Path: blob/main/extensions/copilot/src/extension/inlineEdits/vscode-node/parts/verifyTextDocumentChanges.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { EndOfLine, TextDocument, TextDocumentChangeEvent, workspace } from 'vscode';6import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry';7import { Disposable } from '../../../../util/vs/base/common/lifecycle';8import { editFromTextDocumentContentChangeEvents } from './common';910/**11* Verifies that VS Code content change API reports consistent document edits.12* Tracks document states and verifies that applying reported edits to the previous state13* produces the new document state. Reports mismatches via telemetry.14*/15export class VerifyTextDocumentChanges extends Disposable {16private readonly _documentStates = new Map<string, { text: string; linefeed: EndOfLine }>();1718constructor(19@ITelemetryService private readonly _telemetryService: ITelemetryService20) {21super();2223// This comes from telemetry24const allowedSchemes = new Set([25'file',26'vscode-notebook-cell',27'untitled',28// "vscode-local",29// "vscode-chat-code-block",30// "chat-editing-text-model",31// "embedded-html",32// "vscode-userdata",33// "vscode-remote",34// "git",35]);36function shouldVerifyDoc(doc: TextDocument): boolean {37return allowedSchemes.has(doc.uri.scheme);38}3940this._register(workspace.onDidOpenTextDocument(doc => {41if (!shouldVerifyDoc(doc)) {42return;43}44const docUri = doc.uri.toString();45this._documentStates.set(docUri, { text: doc.getText(), linefeed: doc.eol });46}));4748this._register(workspace.onDidCloseTextDocument(doc => {49if (!shouldVerifyDoc(doc)) {50return;51}52const docUri = doc.uri.toString();53this._documentStates.delete(docUri);54}));5556workspace.textDocuments.forEach(doc => {57if (!shouldVerifyDoc(doc)) {58return;59}60const docUri = doc.uri.toString();61this._documentStates.set(docUri, { text: doc.getText(), linefeed: doc.eol });62});6364this._register(workspace.onDidChangeTextDocument(e => {65if (!shouldVerifyDoc(e.document)) {66return;67}68this._verifyDocumentStateConsistency(e);69}));70}7172private _verifyDocumentStateConsistency(e: TextDocumentChangeEvent): void {73const docUri = e.document.uri.toString();74const currentText = e.document.getText();75const previousValue = this._documentStates.get(docUri);7677if (previousValue === undefined) {78/* __GDPR__79"vscode.contentChangeForUnknownDocument" : {80"owner": "hediet",81"comment": "Telemetry for verifying VSCode content change API consistency"82}83*/84this._telemetryService.sendMSFTTelemetryEvent('vscode.contentChangeForUnknownDocument', {}, {});85return;86}8788this._documentStates.set(docUri, { text: currentText, linefeed: e.document.eol });8990const edit = editFromTextDocumentContentChangeEvents(e.contentChanges);91const expectedText = edit.apply(previousValue.text);9293if (expectedText !== currentText) {94/* __GDPR__95"vscode.contentChangeInconsistencyDetected" : {96"owner": "hediet",97"comment": "Telemetry for verifying VSCode content change API consistency",98"languageId": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Language of the currently open document." },99"sourceOfChange": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Source of the change." },100"reason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Reason for change (1 = undo, 2 = redo).", "isMeasurement": true },101"previousLineFeed": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Line feed of the previously open document.", "isMeasurement": true },102"currentLineFeed": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Line feed of the currently open document.", "isMeasurement": true },103"scheme": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Scheme of the currently open document." }104}105*/106this._telemetryService.sendMSFTTelemetryEvent('vscode.contentChangeInconsistencyDetected', {107languageId: e.document.languageId,108scheme: e.document.uri.scheme,109sourceOfChange: e.detailedReason?.source || '',110}, {111reason: e.reason,112previousLineFeed: previousValue.linefeed,113currentLineFeed: e.document.eol,114});115}116}117}118119120