Path: blob/main/src/vs/workbench/api/common/extHostLanguageFeatures.ts
5222 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 type * as vscode from 'vscode';6import { asArray, coalesce, isFalsyOrEmpty, isNonEmptyArray } from '../../../base/common/arrays.js';7import { raceCancellationError } from '../../../base/common/async.js';8import { VSBuffer } from '../../../base/common/buffer.js';9import { CancellationToken } from '../../../base/common/cancellation.js';10import { NotImplementedError, isCancellationError } from '../../../base/common/errors.js';11import { IdGenerator } from '../../../base/common/idGenerator.js';12import { DisposableStore, Disposable as CoreDisposable } from '../../../base/common/lifecycle.js';13import { equals, mixin } from '../../../base/common/objects.js';14import { StopWatch } from '../../../base/common/stopwatch.js';15import { regExpLeadsToEndlessLoop } from '../../../base/common/strings.js';16import { assertType, isObject } from '../../../base/common/types.js';17import { URI, UriComponents } from '../../../base/common/uri.js';18import { IURITransformer } from '../../../base/common/uriIpc.js';19import { generateUuid } from '../../../base/common/uuid.js';20import { IPosition } from '../../../editor/common/core/position.js';21import { Range as EditorRange, IRange } from '../../../editor/common/core/range.js';22import { ISelection, Selection } from '../../../editor/common/core/selection.js';23import * as languages from '../../../editor/common/languages.js';24import { IAutoClosingPairConditional } from '../../../editor/common/languages/languageConfiguration.js';25import { encodeSemanticTokensDto } from '../../../editor/common/services/semanticTokensDto.js';26import { localize } from '../../../nls.js';27import { ExtensionIdentifier, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';28import { ILogService } from '../../../platform/log/common/log.js';29import { isProposedApiEnabled } from '../../services/extensions/common/extensions.js';30import { Cache } from './cache.js';31import * as extHostProtocol from './extHost.protocol.js';32import { IExtHostApiDeprecationService } from './extHostApiDeprecationService.js';33import { CommandsConverter, ExtHostCommands } from './extHostCommands.js';34import { ExtHostDiagnostics } from './extHostDiagnostics.js';35import { ExtHostDocuments } from './extHostDocuments.js';36import { ExtHostTelemetry, IExtHostTelemetry } from './extHostTelemetry.js';37import * as typeConvert from './extHostTypeConverters.js';38import { CodeAction, CodeActionKind, CompletionList, DataTransfer, Disposable, DocumentDropOrPasteEditKind, DocumentSymbol, InlineCompletionsDisposeReasonKind, InlineCompletionTriggerKind, InternalDataTransferItem, Location, NewSymbolNameTriggerKind, Range, SemanticTokens, SemanticTokensEdit, SemanticTokensEdits, SnippetString, SymbolInformation, SyntaxTokenType } from './extHostTypes.js';39import { Emitter } from '../../../base/common/event.js';40import { IInlineCompletionsUnificationState } from '../../services/inlineCompletions/common/inlineCompletionsUnification.js';4142// --- adapter4344class DocumentSymbolAdapter {4546constructor(47private readonly _documents: ExtHostDocuments,48private readonly _provider: vscode.DocumentSymbolProvider49) { }5051async provideDocumentSymbols(resource: URI, token: CancellationToken): Promise<languages.DocumentSymbol[] | undefined> {52const doc = this._documents.getDocument(resource);53const value = await this._provider.provideDocumentSymbols(doc, token);54if (isFalsyOrEmpty(value)) {55return undefined;56} else if (value![0] instanceof DocumentSymbol) {57return (<DocumentSymbol[]>value).map(typeConvert.DocumentSymbol.from);58} else {59return DocumentSymbolAdapter._asDocumentSymbolTree(<SymbolInformation[]>value);60}61}6263private static _asDocumentSymbolTree(infos: SymbolInformation[]): languages.DocumentSymbol[] {64// first sort by start (and end) and then loop over all elements65// and build a tree based on containment.66infos = infos.slice(0).sort((a, b) => {67let res = a.location.range.start.compareTo(b.location.range.start);68if (res === 0) {69res = b.location.range.end.compareTo(a.location.range.end);70}71return res;72});73const res: languages.DocumentSymbol[] = [];74const parentStack: languages.DocumentSymbol[] = [];75for (const info of infos) {76const element: languages.DocumentSymbol = {77name: info.name || '!!MISSING: name!!',78kind: typeConvert.SymbolKind.from(info.kind),79tags: info.tags?.map(typeConvert.SymbolTag.from) || [],80detail: '',81containerName: info.containerName,82range: typeConvert.Range.from(info.location.range),83selectionRange: typeConvert.Range.from(info.location.range),84children: []85};8687while (true) {88if (parentStack.length === 0) {89parentStack.push(element);90res.push(element);91break;92}93const parent = parentStack[parentStack.length - 1];94if (EditorRange.containsRange(parent.range, element.range) && !EditorRange.equalsRange(parent.range, element.range)) {95parent.children?.push(element);96parentStack.push(element);97break;98}99parentStack.pop();100}101}102return res;103}104}105106class CodeLensAdapter {107108private readonly _cache = new Cache<vscode.CodeLens>('CodeLens');109private readonly _disposables = new Map<number, DisposableStore>();110111constructor(112private readonly _documents: ExtHostDocuments,113private readonly _commands: CommandsConverter,114private readonly _provider: vscode.CodeLensProvider,115private readonly _extension: IExtensionDescription,116private readonly _extTelemetry: ExtHostTelemetry,117private readonly _logService: ILogService,118) { }119120async provideCodeLenses(resource: URI, token: CancellationToken): Promise<extHostProtocol.ICodeLensListDto | undefined> {121const doc = this._documents.getDocument(resource);122123const lenses = await this._provider.provideCodeLenses(doc, token);124if (!lenses || token.isCancellationRequested) {125return undefined;126}127const cacheId = this._cache.add(lenses);128const disposables = new DisposableStore();129this._disposables.set(cacheId, disposables);130const result: extHostProtocol.ICodeLensListDto = {131cacheId,132lenses: [],133};134for (let i = 0; i < lenses.length; i++) {135136if (!Range.isRange(lenses[i].range)) {137console.warn('INVALID code lens, range is not defined', this._extension.identifier.value);138continue;139}140141result.lenses.push({142cacheId: [cacheId, i],143range: typeConvert.Range.from(lenses[i].range),144command: this._commands.toInternal(lenses[i].command, disposables)145});146}147return result;148}149150async resolveCodeLens(symbol: extHostProtocol.ICodeLensDto, token: CancellationToken): Promise<extHostProtocol.ICodeLensDto | undefined> {151152const lens = symbol.cacheId && this._cache.get(...symbol.cacheId);153if (!lens) {154return undefined;155}156157let resolvedLens: vscode.CodeLens | undefined | null;158if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {159resolvedLens = lens;160} else {161resolvedLens = await this._provider.resolveCodeLens(lens, token);162}163if (!resolvedLens) {164resolvedLens = lens;165}166167if (token.isCancellationRequested) {168return undefined;169}170const disposables = symbol.cacheId && this._disposables.get(symbol.cacheId[0]);171if (!disposables) {172// disposed in the meantime173return undefined;174}175176if (!resolvedLens.command) {177const error = new Error('INVALID code lens resolved, lacks command: ' + this._extension.identifier.value);178this._extTelemetry.onExtensionError(this._extension.identifier, error);179this._logService.error(error);180return undefined;181}182183symbol.command = this._commands.toInternal(resolvedLens.command, disposables);184return symbol;185}186187releaseCodeLenses(cachedId: number): void {188this._disposables.get(cachedId)?.dispose();189this._disposables.delete(cachedId);190this._cache.delete(cachedId);191}192}193194function convertToLocationLinks(value: vscode.Location | vscode.Location[] | vscode.LocationLink[] | undefined | null): languages.LocationLink[] {195if (Array.isArray(value)) {196// eslint-disable-next-line local/code-no-any-casts197return (<any>value).map(typeConvert.DefinitionLink.from);198} else if (value) {199return [typeConvert.DefinitionLink.from(value)];200}201return [];202}203204class DefinitionAdapter {205206constructor(207private readonly _documents: ExtHostDocuments,208private readonly _provider: vscode.DefinitionProvider209) { }210211async provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {212const doc = this._documents.getDocument(resource);213const pos = typeConvert.Position.to(position);214const value = await this._provider.provideDefinition(doc, pos, token);215return convertToLocationLinks(value);216}217}218219class DeclarationAdapter {220221constructor(222private readonly _documents: ExtHostDocuments,223private readonly _provider: vscode.DeclarationProvider224) { }225226async provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {227const doc = this._documents.getDocument(resource);228const pos = typeConvert.Position.to(position);229const value = await this._provider.provideDeclaration(doc, pos, token);230return convertToLocationLinks(value);231}232}233234class ImplementationAdapter {235236constructor(237private readonly _documents: ExtHostDocuments,238private readonly _provider: vscode.ImplementationProvider239) { }240241async provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {242const doc = this._documents.getDocument(resource);243const pos = typeConvert.Position.to(position);244const value = await this._provider.provideImplementation(doc, pos, token);245return convertToLocationLinks(value);246}247}248249class TypeDefinitionAdapter {250251constructor(252private readonly _documents: ExtHostDocuments,253private readonly _provider: vscode.TypeDefinitionProvider254) { }255256async provideTypeDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {257const doc = this._documents.getDocument(resource);258const pos = typeConvert.Position.to(position);259const value = await this._provider.provideTypeDefinition(doc, pos, token);260return convertToLocationLinks(value);261}262}263264class HoverAdapter {265266private _hoverCounter: number = 0;267private _hoverMap: Map<number, vscode.Hover> = new Map<number, vscode.Hover>();268269private static HOVER_MAP_MAX_SIZE = 10;270271constructor(272private readonly _documents: ExtHostDocuments,273private readonly _provider: vscode.HoverProvider,274) { }275276async provideHover(resource: URI, position: IPosition, context: languages.HoverContext<{ id: number }> | undefined, token: CancellationToken): Promise<extHostProtocol.HoverWithId | undefined> {277278const doc = this._documents.getDocument(resource);279const pos = typeConvert.Position.to(position);280281let value: vscode.Hover | null | undefined;282if (context && context.verbosityRequest) {283const previousHoverId = context.verbosityRequest.previousHover.id;284const previousHover = this._hoverMap.get(previousHoverId);285if (!previousHover) {286throw new Error(`Hover with id ${previousHoverId} not found`);287}288const hoverContext: vscode.HoverContext = { verbosityDelta: context.verbosityRequest.verbosityDelta, previousHover };289value = await this._provider.provideHover(doc, pos, token, hoverContext);290} else {291value = await this._provider.provideHover(doc, pos, token);292}293if (!value || isFalsyOrEmpty(value.contents)) {294return undefined;295}296if (!value.range) {297value.range = doc.getWordRangeAtPosition(pos);298}299if (!value.range) {300value.range = new Range(pos, pos);301}302const convertedHover: languages.Hover = typeConvert.Hover.from(value);303const id = this._hoverCounter;304// Check if hover map has more than 10 elements and if yes, remove oldest from the map305if (this._hoverMap.size === HoverAdapter.HOVER_MAP_MAX_SIZE) {306const minimumId = Math.min(...this._hoverMap.keys());307this._hoverMap.delete(minimumId);308}309this._hoverMap.set(id, value);310this._hoverCounter += 1;311const hover: extHostProtocol.HoverWithId = {312...convertedHover,313id314};315return hover;316}317318releaseHover(id: number): void {319this._hoverMap.delete(id);320}321}322323class EvaluatableExpressionAdapter {324325constructor(326private readonly _documents: ExtHostDocuments,327private readonly _provider: vscode.EvaluatableExpressionProvider,328) { }329330async provideEvaluatableExpression(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.EvaluatableExpression | undefined> {331332const doc = this._documents.getDocument(resource);333const pos = typeConvert.Position.to(position);334335const value = await this._provider.provideEvaluatableExpression(doc, pos, token);336if (value) {337return typeConvert.EvaluatableExpression.from(value);338}339return undefined;340}341}342343class InlineValuesAdapter {344345constructor(346private readonly _documents: ExtHostDocuments,347private readonly _provider: vscode.InlineValuesProvider,348) { }349350async provideInlineValues(resource: URI, viewPort: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<languages.InlineValue[] | undefined> {351const doc = this._documents.getDocument(resource);352const value = await this._provider.provideInlineValues(doc, typeConvert.Range.to(viewPort), typeConvert.InlineValueContext.to(context), token);353if (Array.isArray(value)) {354return value.map(iv => typeConvert.InlineValue.from(iv));355}356return undefined;357}358}359360class DocumentHighlightAdapter {361362constructor(363private readonly _documents: ExtHostDocuments,364private readonly _provider: vscode.DocumentHighlightProvider365) { }366367async provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.DocumentHighlight[] | undefined> {368369const doc = this._documents.getDocument(resource);370const pos = typeConvert.Position.to(position);371372const value = await this._provider.provideDocumentHighlights(doc, pos, token);373if (Array.isArray(value)) {374return value.map(typeConvert.DocumentHighlight.from);375}376return undefined;377}378}379380class MultiDocumentHighlightAdapter {381382constructor(383private readonly _documents: ExtHostDocuments,384private readonly _provider: vscode.MultiDocumentHighlightProvider,385private readonly _logService: ILogService,386) { }387388async provideMultiDocumentHighlights(resource: URI, position: IPosition, otherResources: URI[], token: CancellationToken): Promise<languages.MultiDocumentHighlight[] | undefined> {389const doc = this._documents.getDocument(resource);390const otherDocuments = otherResources.map(r => {391try {392return this._documents.getDocument(r);393} catch (err) {394this._logService.error('Error: Unable to retrieve document from URI: ' + r + '. Error message: ' + err);395return undefined;396}397}).filter(doc => doc !== undefined);398399const pos = typeConvert.Position.to(position);400401const value = await this._provider.provideMultiDocumentHighlights(doc, pos, otherDocuments, token);402if (Array.isArray(value)) {403return value.map(typeConvert.MultiDocumentHighlight.from);404}405return undefined;406}407}408409class LinkedEditingRangeAdapter {410constructor(411private readonly _documents: ExtHostDocuments,412private readonly _provider: vscode.LinkedEditingRangeProvider413) { }414415async provideLinkedEditingRanges(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LinkedEditingRanges | undefined> {416417const doc = this._documents.getDocument(resource);418const pos = typeConvert.Position.to(position);419420const value = await this._provider.provideLinkedEditingRanges(doc, pos, token);421if (value && Array.isArray(value.ranges)) {422return {423ranges: coalesce(value.ranges.map(typeConvert.Range.from)),424wordPattern: value.wordPattern425};426}427return undefined;428}429}430431class ReferenceAdapter {432433constructor(434private readonly _documents: ExtHostDocuments,435private readonly _provider: vscode.ReferenceProvider436) { }437438async provideReferences(resource: URI, position: IPosition, context: languages.ReferenceContext, token: CancellationToken): Promise<languages.Location[] | undefined> {439const doc = this._documents.getDocument(resource);440const pos = typeConvert.Position.to(position);441442const value = await this._provider.provideReferences(doc, pos, context, token);443if (Array.isArray(value)) {444return value.map(typeConvert.location.from);445}446return undefined;447}448}449450export interface CustomCodeAction extends extHostProtocol.ICodeActionDto {451_isSynthetic?: boolean;452}453454class CodeActionAdapter {455private static readonly _maxCodeActionsPerFile: number = 1000;456457private readonly _cache = new Cache<vscode.CodeAction | vscode.Command>('CodeAction');458private readonly _disposables = new Map<number, DisposableStore>();459460constructor(461private readonly _documents: ExtHostDocuments,462private readonly _commands: CommandsConverter,463private readonly _diagnostics: ExtHostDiagnostics,464private readonly _provider: vscode.CodeActionProvider,465private readonly _logService: ILogService,466private readonly _extension: IExtensionDescription,467private readonly _apiDeprecation: IExtHostApiDeprecationService,468) { }469470async provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<extHostProtocol.ICodeActionListDto | undefined> {471472const doc = this._documents.getDocument(resource);473const ran = Selection.isISelection(rangeOrSelection)474? <vscode.Selection>typeConvert.Selection.to(rangeOrSelection)475: <vscode.Range>typeConvert.Range.to(rangeOrSelection);476const allDiagnostics: vscode.Diagnostic[] = [];477478for (const diagnostic of this._diagnostics.getDiagnostics(resource)) {479if (ran.intersection(diagnostic.range)) {480const newLen = allDiagnostics.push(diagnostic);481if (newLen > CodeActionAdapter._maxCodeActionsPerFile) {482break;483}484}485}486487const codeActionContext: vscode.CodeActionContext = {488diagnostics: allDiagnostics,489only: context.only ? new CodeActionKind(context.only) : undefined,490triggerKind: typeConvert.CodeActionTriggerKind.to(context.trigger),491};492493const commandsOrActions = await this._provider.provideCodeActions(doc, ran, codeActionContext, token);494if (!isNonEmptyArray(commandsOrActions) || token.isCancellationRequested) {495return undefined;496}497498const cacheId = this._cache.add(commandsOrActions);499const disposables = new DisposableStore();500this._disposables.set(cacheId, disposables);501const actions: CustomCodeAction[] = [];502for (let i = 0; i < commandsOrActions.length; i++) {503const candidate = commandsOrActions[i];504if (!candidate) {505continue;506}507508if (CodeActionAdapter._isCommand(candidate) && !(candidate instanceof CodeAction)) {509// old school: synthetic code action510this._apiDeprecation.report('CodeActionProvider.provideCodeActions - return commands', this._extension,511`Return 'CodeAction' instances instead.`);512513actions.push({514_isSynthetic: true,515title: candidate.title,516command: this._commands.toInternal(candidate, disposables),517});518} else {519const toConvert = candidate as vscode.CodeAction;520521// new school: convert code action522if (codeActionContext.only) {523if (!toConvert.kind) {524this._logService.warn(`${this._extension.identifier.value} - Code actions of kind '${codeActionContext.only.value}' requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`);525} else if (!codeActionContext.only.contains(toConvert.kind)) {526this._logService.warn(`${this._extension.identifier.value} - Code actions of kind '${codeActionContext.only.value}' requested but returned code action is of kind '${toConvert.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code actions.`);527}528}529530// Ensures that this is either a Range[] or an empty array so we don't get Array<Range | undefined>531const range = toConvert.ranges ?? [];532533actions.push({534cacheId: [cacheId, i],535title: toConvert.title,536command: toConvert.command && this._commands.toInternal(toConvert.command, disposables),537diagnostics: toConvert.diagnostics && toConvert.diagnostics.map(typeConvert.Diagnostic.from),538edit: toConvert.edit && typeConvert.WorkspaceEdit.from(toConvert.edit, undefined),539kind: toConvert.kind && toConvert.kind.value,540isPreferred: toConvert.isPreferred,541isAI: isProposedApiEnabled(this._extension, 'codeActionAI') ? toConvert.isAI : false,542ranges: isProposedApiEnabled(this._extension, 'codeActionRanges') ? coalesce(range.map(typeConvert.Range.from)) : undefined,543disabled: toConvert.disabled?.reason544});545}546}547return { cacheId, actions };548}549550async resolveCodeAction(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ edit?: extHostProtocol.IWorkspaceEditDto; command?: extHostProtocol.ICommandDto }> {551const [sessionId, itemId] = id;552const item = this._cache.get(sessionId, itemId);553if (!item || CodeActionAdapter._isCommand(item)) {554return {}; // code actions only!555}556if (!this._provider.resolveCodeAction) {557return {}; // this should not happen...558}559560561const resolvedItem = (await this._provider.resolveCodeAction(item, token)) ?? item;562563let resolvedEdit: extHostProtocol.IWorkspaceEditDto | undefined;564if (resolvedItem.edit) {565resolvedEdit = typeConvert.WorkspaceEdit.from(resolvedItem.edit, undefined);566}567568let resolvedCommand: extHostProtocol.ICommandDto | undefined;569if (resolvedItem.command) {570const disposables = this._disposables.get(sessionId);571if (disposables) {572resolvedCommand = this._commands.toInternal(resolvedItem.command, disposables);573}574}575576return { edit: resolvedEdit, command: resolvedCommand };577}578579releaseCodeActions(cachedId: number): void {580this._disposables.get(cachedId)?.dispose();581this._disposables.delete(cachedId);582this._cache.delete(cachedId);583}584585private static _isCommand(thing: any): thing is vscode.Command {586return typeof (<vscode.Command>thing).command === 'string' && typeof (<vscode.Command>thing).title === 'string';587}588}589590class DocumentPasteEditProvider {591592private _cachedPrepare?: Map<string, vscode.DataTransferItem>;593594private readonly _editsCache = new Cache<vscode.DocumentPasteEdit>('DocumentPasteEdit.edits');595596constructor(597private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,598private readonly _documents: ExtHostDocuments,599private readonly _provider: vscode.DocumentPasteEditProvider,600private readonly _handle: number,601private readonly _extension: IExtensionDescription,602) { }603604async prepareDocumentPaste(resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {605if (!this._provider.prepareDocumentPaste) {606return;607}608609this._cachedPrepare = undefined;610611const doc = this._documents.getDocument(resource);612const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));613614const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, () => {615throw new NotImplementedError();616});617await this._provider.prepareDocumentPaste(doc, vscodeRanges, dataTransfer, token);618if (token.isCancellationRequested) {619return;620}621622// Only send back values that have been added to the data transfer623const newEntries = Array.from(dataTransfer).filter(([, value]) => !(value instanceof InternalDataTransferItem));624625// Store off original data transfer items so we can retrieve them on paste626const newCache = new Map<string, vscode.DataTransferItem>();627628const items = await Promise.all(Array.from(newEntries, async ([mime, value]) => {629const id = generateUuid();630newCache.set(id, value);631return [mime, await typeConvert.DataTransferItem.from(mime, value, id)] as const;632}));633634this._cachedPrepare = newCache;635636return { items };637}638639async providePasteEdits(requestId: number, resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, context: extHostProtocol.IDocumentPasteContextDto, token: CancellationToken): Promise<extHostProtocol.IPasteEditDto[]> {640if (!this._provider.provideDocumentPasteEdits) {641return [];642}643644const doc = this._documents.getDocument(resource);645const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));646647const items = dataTransferDto.items.map(([mime, value]): [string, vscode.DataTransferItem] => {648const cached = this._cachedPrepare?.get(value.id);649if (cached) {650return [mime, cached];651}652653return [654mime,655typeConvert.DataTransferItem.to(mime, value, async id => {656return (await this._proxy.$resolvePasteFileData(this._handle, requestId, id)).buffer;657})658];659});660661const dataTransfer = new DataTransfer(items);662663const edits = await this._provider.provideDocumentPasteEdits(doc, vscodeRanges, dataTransfer, {664only: context.only ? new DocumentDropOrPasteEditKind(context.only) : undefined,665triggerKind: context.triggerKind,666}, token);667if (!edits || token.isCancellationRequested) {668return [];669}670671const cacheId = this._editsCache.add(edits);672673return edits.map((edit, i): extHostProtocol.IPasteEditDto => ({674_cacheId: [cacheId, i],675title: edit.title ?? localize('defaultPasteLabel', "Paste using '{0}' extension", this._extension.displayName || this._extension.name),676kind: edit.kind,677yieldTo: edit.yieldTo?.map(x => x.value),678insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },679additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,680}));681}682683async resolvePasteEdit(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ insertText?: string | vscode.SnippetString; additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {684const [sessionId, itemId] = id;685const item = this._editsCache.get(sessionId, itemId);686if (!item || !this._provider.resolveDocumentPasteEdit) {687return {}; // this should not happen...688}689690const resolvedItem = (await this._provider.resolveDocumentPasteEdit(item, token)) ?? item;691return {692insertText: resolvedItem.insertText,693additionalEdit: resolvedItem.additionalEdit ? typeConvert.WorkspaceEdit.from(resolvedItem.additionalEdit, undefined) : undefined694};695}696697releasePasteEdits(id: number): any {698this._editsCache.delete(id);699}700}701702class DocumentFormattingAdapter {703704constructor(705private readonly _documents: ExtHostDocuments,706private readonly _provider: vscode.DocumentFormattingEditProvider707) { }708709async provideDocumentFormattingEdits(resource: URI, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {710711const document = this._documents.getDocument(resource);712713// eslint-disable-next-line local/code-no-any-casts714const value = await this._provider.provideDocumentFormattingEdits(document, <any>options, token);715if (Array.isArray(value)) {716return value.map(typeConvert.TextEdit.from);717}718return undefined;719}720}721722class RangeFormattingAdapter {723724constructor(725private readonly _documents: ExtHostDocuments,726private readonly _provider: vscode.DocumentRangeFormattingEditProvider727) { }728729async provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {730731const document = this._documents.getDocument(resource);732const ran = typeConvert.Range.to(range);733734// eslint-disable-next-line local/code-no-any-casts735const value = await this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token);736if (Array.isArray(value)) {737return value.map(typeConvert.TextEdit.from);738}739return undefined;740}741742async provideDocumentRangesFormattingEdits(resource: URI, ranges: IRange[], options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {743assertType(typeof this._provider.provideDocumentRangesFormattingEdits === 'function', 'INVALID invocation of `provideDocumentRangesFormattingEdits`');744745const document = this._documents.getDocument(resource);746const _ranges = <Range[]>ranges.map(typeConvert.Range.to);747// eslint-disable-next-line local/code-no-any-casts748const value = await this._provider.provideDocumentRangesFormattingEdits(document, _ranges, <any>options, token);749if (Array.isArray(value)) {750return value.map(typeConvert.TextEdit.from);751}752return undefined;753}754}755756class OnTypeFormattingAdapter {757758constructor(759private readonly _documents: ExtHostDocuments,760private readonly _provider: vscode.OnTypeFormattingEditProvider761) { }762763autoFormatTriggerCharacters: string[] = []; // not here764765async provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {766767const document = this._documents.getDocument(resource);768const pos = typeConvert.Position.to(position);769770// eslint-disable-next-line local/code-no-any-casts771const value = await this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token);772if (Array.isArray(value)) {773return value.map(typeConvert.TextEdit.from);774}775return undefined;776}777}778779class NavigateTypeAdapter {780781private readonly _cache = new Cache<vscode.SymbolInformation>('WorkspaceSymbols');782783constructor(784private readonly _provider: vscode.WorkspaceSymbolProvider,785private readonly _logService: ILogService786) { }787788async provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolsDto> {789const value = await this._provider.provideWorkspaceSymbols(search, token);790791if (!isNonEmptyArray(value)) {792return { symbols: [] };793}794795const sid = this._cache.add(value);796const result: extHostProtocol.IWorkspaceSymbolsDto = {797cacheId: sid,798symbols: []799};800801for (let i = 0; i < value.length; i++) {802const item = value[i];803if (!item || !item.name) {804this._logService.warn('INVALID SymbolInformation', item);805continue;806}807result.symbols.push({808...typeConvert.WorkspaceSymbol.from(item),809cacheId: [sid, i]810});811}812813return result;814}815816async resolveWorkspaceSymbol(symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {817if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {818return symbol;819}820if (!symbol.cacheId) {821return symbol;822}823const item = this._cache.get(...symbol.cacheId);824if (item) {825const value = await this._provider.resolveWorkspaceSymbol(item, token);826return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);827}828return undefined;829}830831releaseWorkspaceSymbols(id: number): any {832this._cache.delete(id);833}834}835836class RenameAdapter {837838static supportsResolving(provider: vscode.RenameProvider): boolean {839return typeof provider.prepareRename === 'function';840}841842constructor(843private readonly _documents: ExtHostDocuments,844private readonly _provider: vscode.RenameProvider,845private readonly _logService: ILogService846) { }847848async provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto & languages.Rejection | undefined> {849850const doc = this._documents.getDocument(resource);851const pos = typeConvert.Position.to(position);852853try {854const value = await this._provider.provideRenameEdits(doc, pos, newName, token);855if (!value) {856return undefined;857}858return typeConvert.WorkspaceEdit.from(value);859860} catch (err) {861const rejectReason = RenameAdapter._asMessage(err);862if (rejectReason) {863return { rejectReason, edits: undefined! };864} else {865// generic error866return Promise.reject<extHostProtocol.IWorkspaceEditDto>(err);867}868}869}870871async resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Promise<(languages.RenameLocation & languages.Rejection) | undefined> {872if (typeof this._provider.prepareRename !== 'function') {873return Promise.resolve(undefined);874}875876const doc = this._documents.getDocument(resource);877const pos = typeConvert.Position.to(position);878879try {880const rangeOrLocation = await this._provider.prepareRename(doc, pos, token);881882let range: vscode.Range | undefined;883let text: string | undefined;884if (Range.isRange(rangeOrLocation)) {885range = rangeOrLocation;886text = doc.getText(rangeOrLocation);887888} else if (isObject(rangeOrLocation)) {889range = rangeOrLocation.range;890text = rangeOrLocation.placeholder;891}892893if (!range || !text) {894return undefined;895}896if (range.start.line > pos.line || range.end.line < pos.line) {897this._logService.warn('INVALID rename location: position line must be within range start/end lines');898return undefined;899}900return { range: typeConvert.Range.from(range), text };901902} catch (err) {903const rejectReason = RenameAdapter._asMessage(err);904if (rejectReason) {905return { rejectReason, range: undefined!, text: undefined! };906} else {907return Promise.reject<any>(err);908}909}910}911912private static _asMessage(err: any): string | undefined {913if (typeof err === 'string') {914return err;915} else if (err instanceof Error && typeof err.message === 'string') {916return err.message;917} else {918return undefined;919}920}921}922923class NewSymbolNamesAdapter {924925private static languageTriggerKindToVSCodeTriggerKind: Record<languages.NewSymbolNameTriggerKind, vscode.NewSymbolNameTriggerKind> = {926[languages.NewSymbolNameTriggerKind.Invoke]: NewSymbolNameTriggerKind.Invoke,927[languages.NewSymbolNameTriggerKind.Automatic]: NewSymbolNameTriggerKind.Automatic,928};929930constructor(931private readonly _documents: ExtHostDocuments,932private readonly _provider: vscode.NewSymbolNamesProvider,933private readonly _logService: ILogService934) { }935936async supportsAutomaticNewSymbolNamesTriggerKind() {937return this._provider.supportsAutomaticTriggerKind;938}939940async provideNewSymbolNames(resource: URI, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {941942const doc = this._documents.getDocument(resource);943const pos = typeConvert.Range.to(range);944945try {946const kind = NewSymbolNamesAdapter.languageTriggerKindToVSCodeTriggerKind[triggerKind];947const value = await this._provider.provideNewSymbolNames(doc, pos, kind, token);948if (!value) {949return undefined;950}951return value.map(v =>952typeof v === 'string' /* @ulugbekna: for backward compatibility because `value` used to be just `string[]` */953? { newSymbolName: v }954: { newSymbolName: v.newSymbolName, tags: v.tags }955);956} catch (err: unknown) {957this._logService.error(NewSymbolNamesAdapter._asMessage(err) ?? JSON.stringify(err, null, '\t') /* @ulugbekna: assuming `err` doesn't have circular references that could result in an exception when converting to JSON */);958return undefined;959}960}961962// @ulugbekna: this method is also defined in RenameAdapter but seems OK to be duplicated963private static _asMessage(err: any): string | undefined {964if (typeof err === 'string') {965return err;966} else if (err instanceof Error && typeof err.message === 'string') {967return err.message;968} else {969return undefined;970}971}972}973974class SemanticTokensPreviousResult {975constructor(976readonly resultId: string | undefined,977readonly tokens?: Uint32Array,978) { }979}980981type RelaxedSemanticTokens = { readonly resultId?: string; readonly data: number[] };982type RelaxedSemanticTokensEdit = { readonly start: number; readonly deleteCount: number; readonly data?: number[] };983type RelaxedSemanticTokensEdits = { readonly resultId?: string; readonly edits: RelaxedSemanticTokensEdit[] };984985type ProvidedSemanticTokens = vscode.SemanticTokens | RelaxedSemanticTokens;986type ProvidedSemanticTokensEdits = vscode.SemanticTokensEdits | RelaxedSemanticTokensEdits;987988class DocumentSemanticTokensAdapter {989990private readonly _previousResults: Map<number, SemanticTokensPreviousResult>;991private _nextResultId = 1;992993constructor(994private readonly _documents: ExtHostDocuments,995private readonly _provider: vscode.DocumentSemanticTokensProvider,996) {997this._previousResults = new Map<number, SemanticTokensPreviousResult>();998}9991000async provideDocumentSemanticTokens(resource: URI, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {1001const doc = this._documents.getDocument(resource);1002const previousResult = (previousResultId !== 0 ? this._previousResults.get(previousResultId) : null);1003let value = typeof previousResult?.resultId === 'string' && typeof this._provider.provideDocumentSemanticTokensEdits === 'function'1004? await this._provider.provideDocumentSemanticTokensEdits(doc, previousResult.resultId, token)1005: await this._provider.provideDocumentSemanticTokens(doc, token);10061007if (previousResult) {1008this._previousResults.delete(previousResultId);1009}1010if (!value) {1011return null;1012}1013value = DocumentSemanticTokensAdapter._fixProvidedSemanticTokens(value);1014return this._send(DocumentSemanticTokensAdapter._convertToEdits(previousResult, value), value);1015}10161017async releaseDocumentSemanticColoring(semanticColoringResultId: number): Promise<void> {1018this._previousResults.delete(semanticColoringResultId);1019}10201021private static _fixProvidedSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {1022if (DocumentSemanticTokensAdapter._isSemanticTokens(v)) {1023if (DocumentSemanticTokensAdapter._isCorrectSemanticTokens(v)) {1024return v;1025}1026return new SemanticTokens(new Uint32Array(v.data), v.resultId);1027} else if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(v)) {1028if (DocumentSemanticTokensAdapter._isCorrectSemanticTokensEdits(v)) {1029return v;1030}1031return new SemanticTokensEdits(v.edits.map(edit => new SemanticTokensEdit(edit.start, edit.deleteCount, edit.data ? new Uint32Array(edit.data) : edit.data)), v.resultId);1032}1033return v;1034}10351036private static _isSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokens {1037return v && !!((v as ProvidedSemanticTokens).data);1038}10391040private static _isCorrectSemanticTokens(v: ProvidedSemanticTokens): v is vscode.SemanticTokens {1041return (v.data instanceof Uint32Array);1042}10431044private static _isSemanticTokensEdits(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokensEdits {1045return v && Array.isArray((v as ProvidedSemanticTokensEdits).edits);1046}10471048private static _isCorrectSemanticTokensEdits(v: ProvidedSemanticTokensEdits): v is vscode.SemanticTokensEdits {1049for (const edit of v.edits) {1050if (!(edit.data instanceof Uint32Array)) {1051return false;1052}1053}1054return true;1055}10561057private static _convertToEdits(previousResult: SemanticTokensPreviousResult | null | undefined, newResult: vscode.SemanticTokens | vscode.SemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {1058if (!DocumentSemanticTokensAdapter._isSemanticTokens(newResult)) {1059return newResult;1060}1061if (!previousResult || !previousResult.tokens) {1062return newResult;1063}1064const oldData = previousResult.tokens;1065const oldLength = oldData.length;1066const newData = newResult.data;1067const newLength = newData.length;10681069let commonPrefixLength = 0;1070const maxCommonPrefixLength = Math.min(oldLength, newLength);1071while (commonPrefixLength < maxCommonPrefixLength && oldData[commonPrefixLength] === newData[commonPrefixLength]) {1072commonPrefixLength++;1073}10741075if (commonPrefixLength === oldLength && commonPrefixLength === newLength) {1076// complete overlap!1077return new SemanticTokensEdits([], newResult.resultId);1078}10791080let commonSuffixLength = 0;1081const maxCommonSuffixLength = maxCommonPrefixLength - commonPrefixLength;1082while (commonSuffixLength < maxCommonSuffixLength && oldData[oldLength - commonSuffixLength - 1] === newData[newLength - commonSuffixLength - 1]) {1083commonSuffixLength++;1084}10851086return new SemanticTokensEdits([{1087start: commonPrefixLength,1088deleteCount: (oldLength - commonPrefixLength - commonSuffixLength),1089data: newData.subarray(commonPrefixLength, newLength - commonSuffixLength)1090}], newResult.resultId);1091}10921093private _send(value: vscode.SemanticTokens | vscode.SemanticTokensEdits, original: vscode.SemanticTokens | vscode.SemanticTokensEdits): VSBuffer | null {1094if (DocumentSemanticTokensAdapter._isSemanticTokens(value)) {1095const myId = this._nextResultId++;1096this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId, value.data));1097return encodeSemanticTokensDto({1098id: myId,1099type: 'full',1100data: value.data1101});1102}11031104if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(value)) {1105const myId = this._nextResultId++;1106if (DocumentSemanticTokensAdapter._isSemanticTokens(original)) {1107// store the original1108this._previousResults.set(myId, new SemanticTokensPreviousResult(original.resultId, original.data));1109} else {1110this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId));1111}1112return encodeSemanticTokensDto({1113id: myId,1114type: 'delta',1115deltas: (value.edits || []).map(edit => ({ start: edit.start, deleteCount: edit.deleteCount, data: edit.data }))1116});1117}11181119return null;1120}1121}11221123class DocumentRangeSemanticTokensAdapter {11241125constructor(1126private readonly _documents: ExtHostDocuments,1127private readonly _provider: vscode.DocumentRangeSemanticTokensProvider,1128) { }11291130async provideDocumentRangeSemanticTokens(resource: URI, range: IRange, token: CancellationToken): Promise<VSBuffer | null> {1131const doc = this._documents.getDocument(resource);1132const value = await this._provider.provideDocumentRangeSemanticTokens(doc, typeConvert.Range.to(range), token);1133if (!value) {1134return null;1135}1136return this._send(value);1137}11381139private _send(value: vscode.SemanticTokens): VSBuffer {1140return encodeSemanticTokensDto({1141id: 0,1142type: 'full',1143data: value.data1144});1145}1146}11471148class CompletionsAdapter {11491150static supportsResolving(provider: vscode.CompletionItemProvider): boolean {1151return typeof provider.resolveCompletionItem === 'function';1152}11531154private _cache = new Cache<vscode.CompletionItem>('CompletionItem');1155private _disposables = new Map<number, DisposableStore>();11561157constructor(1158private readonly _documents: ExtHostDocuments,1159private readonly _commands: CommandsConverter,1160private readonly _provider: vscode.CompletionItemProvider,1161private readonly _apiDeprecation: IExtHostApiDeprecationService,1162private readonly _extension: IExtensionDescription,1163) { }11641165async provideCompletionItems(resource: URI, position: IPosition, context: languages.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {11661167const doc = this._documents.getDocument(resource);1168const pos = typeConvert.Position.to(position);11691170// The default insert/replace ranges. It's important to compute them1171// before asynchronously asking the provider for its results. See1172// https://github.com/microsoft/vscode/issues/83400#issuecomment-5468514211173const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);1174const insertRange = replaceRange.with({ end: pos });11751176const sw = new StopWatch();1177const itemsOrList = await this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context));11781179if (!itemsOrList) {1180// undefined and null are valid results1181return undefined;1182}11831184if (token.isCancellationRequested) {1185// cancelled -> return without further ado, esp no caching1186// of results as they will leak1187return undefined;1188}11891190const list = Array.isArray(itemsOrList) ? new CompletionList(itemsOrList) : itemsOrList;11911192// keep result for providers that support resolving1193const pid: number = CompletionsAdapter.supportsResolving(this._provider) ? this._cache.add(list.items) : this._cache.add([]);1194const disposables = new DisposableStore();1195this._disposables.set(pid, disposables);11961197const completions: extHostProtocol.ISuggestDataDto[] = [];1198const result: extHostProtocol.ISuggestResultDto = {1199x: pid,1200[extHostProtocol.ISuggestResultDtoField.completions]: completions,1201[extHostProtocol.ISuggestResultDtoField.defaultRanges]: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },1202[extHostProtocol.ISuggestResultDtoField.isIncomplete]: list.isIncomplete || undefined,1203[extHostProtocol.ISuggestResultDtoField.duration]: sw.elapsed()1204};12051206for (let i = 0; i < list.items.length; i++) {1207const item = list.items[i];1208// check for bad completion item first1209const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);1210completions.push(dto);1211}12121213return result;1214}12151216async resolveCompletionItem(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {12171218if (typeof this._provider.resolveCompletionItem !== 'function') {1219return undefined;1220}12211222const item = this._cache.get(...id);1223if (!item) {1224return undefined;1225}12261227const dto1 = this._convertCompletionItem(item, id);12281229const resolvedItem = await this._provider.resolveCompletionItem(item, token);12301231if (!resolvedItem) {1232return undefined;1233}12341235const dto2 = this._convertCompletionItem(resolvedItem, id);12361237if (dto1[extHostProtocol.ISuggestDataDtoField.insertText] !== dto2[extHostProtocol.ISuggestDataDtoField.insertText]1238|| dto1[extHostProtocol.ISuggestDataDtoField.insertTextRules] !== dto2[extHostProtocol.ISuggestDataDtoField.insertTextRules]1239) {1240this._apiDeprecation.report('CompletionItem.insertText', this._extension, 'extension MAY NOT change \'insertText\' of a CompletionItem during resolve');1241}12421243if (dto1[extHostProtocol.ISuggestDataDtoField.commandIdent] !== dto2[extHostProtocol.ISuggestDataDtoField.commandIdent]1244|| dto1[extHostProtocol.ISuggestDataDtoField.commandId] !== dto2[extHostProtocol.ISuggestDataDtoField.commandId]1245|| !equals(dto1[extHostProtocol.ISuggestDataDtoField.commandArguments], dto2[extHostProtocol.ISuggestDataDtoField.commandArguments])1246) {1247this._apiDeprecation.report('CompletionItem.command', this._extension, 'extension MAY NOT change \'command\' of a CompletionItem during resolve');1248}12491250return {1251...dto1,1252[extHostProtocol.ISuggestDataDtoField.documentation]: dto2[extHostProtocol.ISuggestDataDtoField.documentation],1253[extHostProtocol.ISuggestDataDtoField.detail]: dto2[extHostProtocol.ISuggestDataDtoField.detail],1254[extHostProtocol.ISuggestDataDtoField.additionalTextEdits]: dto2[extHostProtocol.ISuggestDataDtoField.additionalTextEdits],12551256// (fishy) async insertText1257[extHostProtocol.ISuggestDataDtoField.insertText]: dto2[extHostProtocol.ISuggestDataDtoField.insertText],1258[extHostProtocol.ISuggestDataDtoField.insertTextRules]: dto2[extHostProtocol.ISuggestDataDtoField.insertTextRules],12591260// (fishy) async command1261[extHostProtocol.ISuggestDataDtoField.commandIdent]: dto2[extHostProtocol.ISuggestDataDtoField.commandIdent],1262[extHostProtocol.ISuggestDataDtoField.commandId]: dto2[extHostProtocol.ISuggestDataDtoField.commandId],1263[extHostProtocol.ISuggestDataDtoField.commandArguments]: dto2[extHostProtocol.ISuggestDataDtoField.commandArguments],1264};1265}12661267releaseCompletionItems(id: number): any {1268this._disposables.get(id)?.dispose();1269this._disposables.delete(id);1270this._cache.delete(id);1271}12721273private _convertCompletionItem(item: vscode.CompletionItem, id: extHostProtocol.ChainedCacheId, defaultInsertRange?: vscode.Range, defaultReplaceRange?: vscode.Range): extHostProtocol.ISuggestDataDto {12741275const disposables = this._disposables.get(id[0]);1276if (!disposables) {1277throw Error('DisposableStore is missing...');1278}12791280const command = this._commands.toInternal(item.command, disposables);1281const result: extHostProtocol.ISuggestDataDto = {1282//1283x: id,1284//1285[extHostProtocol.ISuggestDataDtoField.label]: item.label,1286[extHostProtocol.ISuggestDataDtoField.kind]: item.kind !== undefined ? typeConvert.CompletionItemKind.from(item.kind) : undefined,1287[extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),1288[extHostProtocol.ISuggestDataDtoField.detail]: item.detail,1289[extHostProtocol.ISuggestDataDtoField.documentation]: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),1290[extHostProtocol.ISuggestDataDtoField.sortText]: item.sortText !== item.label ? item.sortText : undefined,1291[extHostProtocol.ISuggestDataDtoField.filterText]: item.filterText !== item.label ? item.filterText : undefined,1292[extHostProtocol.ISuggestDataDtoField.preselect]: item.preselect || undefined,1293[extHostProtocol.ISuggestDataDtoField.insertTextRules]: item.keepWhitespace ? languages.CompletionItemInsertTextRule.KeepWhitespace : languages.CompletionItemInsertTextRule.None,1294[extHostProtocol.ISuggestDataDtoField.commitCharacters]: item.commitCharacters?.join(''),1295[extHostProtocol.ISuggestDataDtoField.additionalTextEdits]: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),1296[extHostProtocol.ISuggestDataDtoField.commandIdent]: command?.$ident,1297[extHostProtocol.ISuggestDataDtoField.commandId]: command?.id,1298[extHostProtocol.ISuggestDataDtoField.commandArguments]: command?.$ident ? undefined : command?.arguments, // filled in on main side from $ident1299};13001301// 'insertText'-logic1302if (item.textEdit) {1303this._apiDeprecation.report('CompletionItem.textEdit', this._extension, `Use 'CompletionItem.insertText' and 'CompletionItem.range' instead.`);1304result[extHostProtocol.ISuggestDataDtoField.insertText] = item.textEdit.newText;13051306} else if (typeof item.insertText === 'string') {1307result[extHostProtocol.ISuggestDataDtoField.insertText] = item.insertText;13081309} else if (item.insertText instanceof SnippetString) {1310result[extHostProtocol.ISuggestDataDtoField.insertText] = item.insertText.value;1311result[extHostProtocol.ISuggestDataDtoField.insertTextRules]! |= languages.CompletionItemInsertTextRule.InsertAsSnippet;1312}13131314// 'overwrite[Before|After]'-logic1315let range: vscode.Range | { inserting: vscode.Range; replacing: vscode.Range } | undefined;1316if (item.textEdit) {1317range = item.textEdit.range;1318} else if (item.range) {1319range = item.range;1320}13211322if (Range.isRange(range)) {1323// "old" range1324result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);13251326} else if (range && (!defaultInsertRange?.isEqual(range.inserting) || !defaultReplaceRange?.isEqual(range.replacing))) {1327// ONLY send range when it's different from the default ranges (safe bandwidth)1328result[extHostProtocol.ISuggestDataDtoField.range] = {1329insert: typeConvert.Range.from(range.inserting),1330replace: typeConvert.Range.from(range.replacing)1331};1332}13331334return result;1335}1336}13371338class InlineCompletionAdapter {1339private readonly _references = new ReferenceMap<{1340dispose(): void;1341items: readonly vscode.InlineCompletionItem[];1342list: vscode.InlineCompletionList | undefined;1343}>();13441345private readonly _isAdditionsProposedApiEnabled: boolean;13461347constructor(1348private readonly _extension: IExtensionDescription,1349private readonly _documents: ExtHostDocuments,1350private readonly _provider: vscode.InlineCompletionItemProvider,1351private readonly _commands: CommandsConverter,1352) {1353this._isAdditionsProposedApiEnabled = isProposedApiEnabled(this._extension, 'inlineCompletionsAdditions');1354}13551356public get supportsHandleEvents(): boolean {1357return isProposedApiEnabled(this._extension, 'inlineCompletionsAdditions')1358&& (typeof this._provider.handleDidShowCompletionItem === 'function'1359|| typeof this._provider.handleDidPartiallyAcceptCompletionItem === 'function'1360|| typeof this._provider.handleDidRejectCompletionItem === 'function'1361|| typeof this._provider.handleEndOfLifetime === 'function'1362);1363}13641365public get supportsSetModelId(): boolean {1366return isProposedApiEnabled(this._extension, 'inlineCompletionsAdditions')1367&& typeof this._provider.setCurrentModelId === 'function';1368}13691370private readonly languageTriggerKindToVSCodeTriggerKind: Record<languages.InlineCompletionTriggerKind, InlineCompletionTriggerKind> = {1371[languages.InlineCompletionTriggerKind.Automatic]: InlineCompletionTriggerKind.Automatic,1372[languages.InlineCompletionTriggerKind.Explicit]: InlineCompletionTriggerKind.Invoke,1373};13741375public get modelInfo(): extHostProtocol.IInlineCompletionModelInfoDto | undefined {1376if (!this._isAdditionsProposedApiEnabled) {1377return undefined;1378}1379return this._provider.modelInfo ? {1380models: this._provider.modelInfo.models,1381currentModelId: this._provider.modelInfo.currentModelId1382} : undefined;1383}13841385setCurrentModelId(modelId: string): void {1386if (!this._isAdditionsProposedApiEnabled) {1387return;1388}1389this._provider.setCurrentModelId?.(modelId);1390}13911392async provideInlineCompletions(resource: URI, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {1393const doc = this._documents.getDocument(resource);1394const pos = typeConvert.Position.to(position);13951396const result = await this._provider.provideInlineCompletionItems(doc, pos, {1397selectedCompletionInfo:1398context.selectedSuggestionInfo1399? {1400range: typeConvert.Range.to(context.selectedSuggestionInfo.range),1401text: context.selectedSuggestionInfo.text1402}1403: undefined,1404triggerKind: this.languageTriggerKindToVSCodeTriggerKind[context.triggerKind],1405requestUuid: context.requestUuid,1406requestIssuedDateTime: context.requestIssuedDateTime,1407earliestShownDateTime: context.earliestShownDateTime,1408changeHint: context.changeHint,1409}, token);14101411if (!result) {1412// undefined and null are valid results1413return undefined;1414}14151416const { resultItems, list } = Array.isArray(result) ? { resultItems: result, list: undefined } : { resultItems: result.items, list: result };1417const commands = this._isAdditionsProposedApiEnabled ? Array.isArray(result) ? [] : result.commands || [] : [];1418const enableForwardStability = this._isAdditionsProposedApiEnabled && !Array.isArray(result) ? result.enableForwardStability : undefined;14191420let disposableStore: DisposableStore | undefined = undefined;1421const pid = this._references.createReferenceId({1422dispose() {1423disposableStore?.dispose();1424},1425items: resultItems,1426list,1427});14281429const items = {1430pid,1431languageId: doc.languageId,1432items: resultItems.map<extHostProtocol.IdentifiableInlineCompletion>((item, idx) => {1433let command: languages.Command | undefined = undefined;1434if (item.command) {1435if (!disposableStore) {1436disposableStore = new DisposableStore();1437}1438command = this._commands.toInternal(item.command, disposableStore);1439}14401441let action: languages.Command | undefined = undefined;1442if (item.action) {1443if (!disposableStore) {1444disposableStore = new DisposableStore();1445}1446action = this._commands.toInternal(item.action, disposableStore);1447}14481449const insertText = item.insertText;1450return ({1451insertText: insertText === undefined ? undefined : (typeof insertText === 'string' ? insertText : { snippet: insertText.value }),1452range: item.range ? typeConvert.Range.from(item.range) : undefined,1453showRange: (this._isAdditionsProposedApiEnabled && item.showRange) ? typeConvert.Range.from(item.showRange) : undefined,1454command,1455gutterMenuLinkAction: action,1456idx: idx,1457completeBracketPairs: this._isAdditionsProposedApiEnabled ? item.completeBracketPairs : false,1458isInlineEdit: this._isAdditionsProposedApiEnabled ? item.isInlineEdit : false,1459showInlineEditMenu: this._isAdditionsProposedApiEnabled ? item.showInlineEditMenu : false,1460hint: (item.displayLocation && this._isAdditionsProposedApiEnabled) ? {1461range: typeConvert.Range.from(item.displayLocation.range),1462content: item.displayLocation.label,1463style: item.displayLocation.kind ? typeConvert.InlineCompletionHintStyle.from(item.displayLocation.kind) : languages.InlineCompletionHintStyle.Code,1464} : undefined,1465warning: (item.warning && this._isAdditionsProposedApiEnabled) ? {1466message: typeConvert.MarkdownString.from(item.warning.message),1467icon: item.warning.icon ? typeConvert.IconPath.fromThemeIcon(item.warning.icon) : undefined,1468} : undefined,1469correlationId: this._isAdditionsProposedApiEnabled ? item.correlationId : undefined,1470suggestionId: undefined,1471uri: (this._isAdditionsProposedApiEnabled && item.uri) ? item.uri : undefined,1472supportsRename: this._isAdditionsProposedApiEnabled ? item.supportsRename : false,1473jumpToPosition: (this._isAdditionsProposedApiEnabled && item.jumpToPosition) ? typeConvert.Position.from(item.jumpToPosition) : undefined,1474});1475}),1476commands: commands.map(c => {1477if (!disposableStore) {1478disposableStore = new DisposableStore();1479}1480return typeConvert.CompletionCommand.from(c, this._commands, disposableStore);1481}),1482suppressSuggestions: false,1483enableForwardStability,1484} satisfies extHostProtocol.IdentifiableInlineCompletions;1485return items;1486}14871488disposeCompletions(pid: number, reason: languages.InlineCompletionsDisposeReason) {1489const completionList = this._references.get(pid);1490if (this._provider.handleListEndOfLifetime && this._isAdditionsProposedApiEnabled && completionList?.list) {1491function translateReason(reason: languages.InlineCompletionsDisposeReason): vscode.InlineCompletionsDisposeReason {1492switch (reason.kind) {1493case 'lostRace':1494return { kind: InlineCompletionsDisposeReasonKind.LostRace };1495case 'tokenCancellation':1496return { kind: InlineCompletionsDisposeReasonKind.TokenCancellation };1497case 'other':1498return { kind: InlineCompletionsDisposeReasonKind.Other };1499case 'empty':1500return { kind: InlineCompletionsDisposeReasonKind.Empty };1501case 'notTaken':1502return { kind: InlineCompletionsDisposeReasonKind.NotTaken };1503default:1504return { kind: InlineCompletionsDisposeReasonKind.Other };1505}1506}15071508this._provider.handleListEndOfLifetime(completionList.list, translateReason(reason));1509}15101511const data = this._references.disposeReferenceId(pid);1512data?.dispose();1513}15141515handleDidShowCompletionItem(pid: number, idx: number, updatedInsertText: string): void {1516const completionItem = this._references.get(pid)?.items[idx];1517if (completionItem) {1518if (this._provider.handleDidShowCompletionItem && this._isAdditionsProposedApiEnabled) {1519this._provider.handleDidShowCompletionItem(completionItem, updatedInsertText);1520}1521}1522}15231524handlePartialAccept(pid: number, idx: number, acceptedCharacters: number, info: languages.PartialAcceptInfo): void {1525const completionItem = this._references.get(pid)?.items[idx];1526if (completionItem) {1527if (this._provider.handleDidPartiallyAcceptCompletionItem && this._isAdditionsProposedApiEnabled) {1528this._provider.handleDidPartiallyAcceptCompletionItem(completionItem, acceptedCharacters);1529this._provider.handleDidPartiallyAcceptCompletionItem(completionItem, typeConvert.PartialAcceptInfo.to(info));1530}1531}1532}15331534handleEndOfLifetime(pid: number, idx: number, reason: languages.InlineCompletionEndOfLifeReason<{ pid: number; idx: number }>): void {1535const completionItem = this._references.get(pid)?.items[idx];1536if (completionItem) {1537if (this._provider.handleEndOfLifetime && this._isAdditionsProposedApiEnabled) {1538const r = typeConvert.InlineCompletionEndOfLifeReason.to(reason, ref => this._references.get(ref.pid)?.items[ref.idx]);1539this._provider.handleEndOfLifetime(completionItem, r);1540}1541}1542}15431544handleRejection(pid: number, idx: number): void {1545const completionItem = this._references.get(pid)?.items[idx];1546if (completionItem) {1547if (this._provider.handleDidRejectCompletionItem && this._isAdditionsProposedApiEnabled) {1548this._provider.handleDidRejectCompletionItem(completionItem);1549}1550}1551}1552}15531554class ReferenceMap<T> {1555private readonly _references = new Map<number, T>();1556private _idPool = 1;15571558createReferenceId(value: T): number {1559const id = this._idPool++;1560this._references.set(id, value);1561return id;1562}15631564disposeReferenceId(referenceId: number): T | undefined {1565const value = this._references.get(referenceId);1566this._references.delete(referenceId);1567return value;1568}15691570get(referenceId: number): T | undefined {1571return this._references.get(referenceId);1572}1573}15741575class SignatureHelpAdapter {15761577private readonly _cache = new Cache<vscode.SignatureHelp>('SignatureHelp');15781579constructor(1580private readonly _documents: ExtHostDocuments,1581private readonly _provider: vscode.SignatureHelpProvider,1582) { }15831584async provideSignatureHelp(resource: URI, position: IPosition, context: extHostProtocol.ISignatureHelpContextDto, token: CancellationToken): Promise<extHostProtocol.ISignatureHelpDto | undefined> {1585const doc = this._documents.getDocument(resource);1586const pos = typeConvert.Position.to(position);1587const vscodeContext = this.reviveContext(context);15881589const value = await this._provider.provideSignatureHelp(doc, pos, token, vscodeContext);1590if (value) {1591const id = this._cache.add([value]);1592return { ...typeConvert.SignatureHelp.from(value), id };1593}1594return undefined;1595}15961597private reviveContext(context: extHostProtocol.ISignatureHelpContextDto): vscode.SignatureHelpContext {1598let activeSignatureHelp: vscode.SignatureHelp | undefined = undefined;1599if (context.activeSignatureHelp) {1600const revivedSignatureHelp = typeConvert.SignatureHelp.to(context.activeSignatureHelp);1601const saved = this._cache.get(context.activeSignatureHelp.id, 0);1602if (saved) {1603activeSignatureHelp = saved;1604activeSignatureHelp.activeSignature = revivedSignatureHelp.activeSignature;1605activeSignatureHelp.activeParameter = revivedSignatureHelp.activeParameter;1606} else {1607activeSignatureHelp = revivedSignatureHelp;1608}1609}1610return { ...context, activeSignatureHelp };1611}16121613releaseSignatureHelp(id: number): any {1614this._cache.delete(id);1615}1616}16171618class InlayHintsAdapter {16191620private _cache = new Cache<vscode.InlayHint>('InlayHints');1621private readonly _disposables = new Map<number, DisposableStore>();16221623constructor(1624private readonly _documents: ExtHostDocuments,1625private readonly _commands: CommandsConverter,1626private readonly _provider: vscode.InlayHintsProvider,1627private readonly _logService: ILogService,1628private readonly _extension: IExtensionDescription1629) { }16301631async provideInlayHints(resource: URI, ran: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {1632const doc = this._documents.getDocument(resource);1633const range = typeConvert.Range.to(ran);16341635const hints = await this._provider.provideInlayHints(doc, range, token);1636if (!Array.isArray(hints) || hints.length === 0) {1637// bad result1638this._logService.trace(`[InlayHints] NO inlay hints from '${this._extension.identifier.value}' for range ${JSON.stringify(ran)}`);1639return undefined;1640}1641if (token.isCancellationRequested) {1642// cancelled -> return without further ado, esp no caching1643// of results as they will leak1644return undefined;1645}1646const pid = this._cache.add(hints);1647this._disposables.set(pid, new DisposableStore());1648const result: extHostProtocol.IInlayHintsDto = { hints: [], cacheId: pid };1649for (let i = 0; i < hints.length; i++) {1650if (this._isValidInlayHint(hints[i], range)) {1651result.hints.push(this._convertInlayHint(hints[i], [pid, i]));1652}1653}1654this._logService.trace(`[InlayHints] ${result.hints.length} inlay hints from '${this._extension.identifier.value}' for range ${JSON.stringify(ran)}`);1655return result;1656}16571658async resolveInlayHint(id: extHostProtocol.ChainedCacheId, token: CancellationToken) {1659if (typeof this._provider.resolveInlayHint !== 'function') {1660return undefined;1661}1662const item = this._cache.get(...id);1663if (!item) {1664return undefined;1665}1666const hint = await this._provider.resolveInlayHint(item, token);1667if (!hint) {1668return undefined;1669}1670if (!this._isValidInlayHint(hint)) {1671return undefined;1672}1673return this._convertInlayHint(hint, id);1674}16751676releaseHints(id: number): any {1677this._disposables.get(id)?.dispose();1678this._disposables.delete(id);1679this._cache.delete(id);1680}16811682private _isValidInlayHint(hint: vscode.InlayHint, range?: vscode.Range): boolean {1683if (hint.label.length === 0 || Array.isArray(hint.label) && hint.label.every(part => part.value.length === 0)) {1684console.log('INVALID inlay hint, empty label', hint);1685return false;1686}1687if (range && !range.contains(hint.position)) {1688// console.log('INVALID inlay hint, position outside range', range, hint);1689return false;1690}1691return true;1692}16931694private _convertInlayHint(hint: vscode.InlayHint, id: extHostProtocol.ChainedCacheId): extHostProtocol.IInlayHintDto {16951696const disposables = this._disposables.get(id[0]);1697if (!disposables) {1698throw Error('DisposableStore is missing...');1699}17001701const result: extHostProtocol.IInlayHintDto = {1702label: '', // fill-in below1703cacheId: id,1704tooltip: typeConvert.MarkdownString.fromStrict(hint.tooltip),1705position: typeConvert.Position.from(hint.position),1706textEdits: hint.textEdits && hint.textEdits.map(typeConvert.TextEdit.from),1707kind: hint.kind && typeConvert.InlayHintKind.from(hint.kind),1708paddingLeft: hint.paddingLeft,1709paddingRight: hint.paddingRight,1710};17111712if (typeof hint.label === 'string') {1713result.label = hint.label;1714} else {1715const parts: languages.InlayHintLabelPart[] = [];1716result.label = parts;17171718for (const part of hint.label) {1719if (!part.value) {1720console.warn('INVALID inlay hint, empty label part', this._extension.identifier.value);1721continue;1722}1723const part2: languages.InlayHintLabelPart = {1724label: part.value,1725tooltip: typeConvert.MarkdownString.fromStrict(part.tooltip)1726};1727if (Location.isLocation(part.location)) {1728part2.location = typeConvert.location.from(part.location);1729}1730if (part.command) {1731part2.command = this._commands.toInternal(part.command, disposables);1732}1733parts.push(part2);1734}1735}1736return result;1737}1738}17391740class LinkProviderAdapter {17411742private _cache = new Cache<vscode.DocumentLink>('DocumentLink');17431744constructor(1745private readonly _documents: ExtHostDocuments,1746private readonly _provider: vscode.DocumentLinkProvider1747) { }17481749async provideLinks(resource: URI, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {1750const doc = this._documents.getDocument(resource);17511752const links = await this._provider.provideDocumentLinks(doc, token);1753if (!Array.isArray(links) || links.length === 0) {1754// bad result1755return undefined;1756}1757if (token.isCancellationRequested) {1758// cancelled -> return without further ado, esp no caching1759// of results as they will leak1760return undefined;1761}1762if (typeof this._provider.resolveDocumentLink !== 'function') {1763// no resolve -> no caching1764return { links: links.filter(LinkProviderAdapter._validateLink).map(typeConvert.DocumentLink.from) };17651766} else {1767// cache links for future resolving1768const pid = this._cache.add(links);1769const result: extHostProtocol.ILinksListDto = { links: [], cacheId: pid };1770for (let i = 0; i < links.length; i++) {17711772if (!LinkProviderAdapter._validateLink(links[i])) {1773continue;1774}17751776const dto: extHostProtocol.ILinkDto = typeConvert.DocumentLink.from(links[i]);1777dto.cacheId = [pid, i];1778result.links.push(dto);1779}1780return result;1781}1782}17831784private static _validateLink(link: vscode.DocumentLink): boolean {1785if (link.target && link.target.path.length > 50_000) {1786console.warn('DROPPING link because it is too long');1787return false;1788}1789return true;1790}17911792async resolveLink(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {1793if (typeof this._provider.resolveDocumentLink !== 'function') {1794return undefined;1795}1796const item = this._cache.get(...id);1797if (!item) {1798return undefined;1799}1800const link = await this._provider.resolveDocumentLink(item, token);1801if (!link || !LinkProviderAdapter._validateLink(link)) {1802return undefined;1803}1804return typeConvert.DocumentLink.from(link);1805}18061807releaseLinks(id: number): any {1808this._cache.delete(id);1809}1810}18111812class ColorProviderAdapter {18131814constructor(1815private _documents: ExtHostDocuments,1816private _provider: vscode.DocumentColorProvider1817) { }18181819async provideColors(resource: URI, token: CancellationToken): Promise<extHostProtocol.IRawColorInfo[]> {1820const doc = this._documents.getDocument(resource);1821const colors = await this._provider.provideDocumentColors(doc, token);1822if (!Array.isArray(colors)) {1823return [];1824}1825const colorInfos: extHostProtocol.IRawColorInfo[] = colors.map(ci => {1826return {1827color: typeConvert.Color.from(ci.color),1828range: typeConvert.Range.from(ci.range)1829};1830});1831return colorInfos;1832}18331834async provideColorPresentations(resource: URI, raw: extHostProtocol.IRawColorInfo, token: CancellationToken): Promise<languages.IColorPresentation[] | undefined> {1835const document = this._documents.getDocument(resource);1836const range = typeConvert.Range.to(raw.range);1837const color = typeConvert.Color.to(raw.color);1838const value = await this._provider.provideColorPresentations(color, { document, range }, token);1839if (!Array.isArray(value)) {1840return undefined;1841}1842return value.map(typeConvert.ColorPresentation.from);1843}1844}18451846class FoldingProviderAdapter {18471848constructor(1849private _documents: ExtHostDocuments,1850private _provider: vscode.FoldingRangeProvider1851) { }18521853async provideFoldingRanges(resource: URI, context: languages.FoldingContext, token: CancellationToken): Promise<languages.FoldingRange[] | undefined> {1854const doc = this._documents.getDocument(resource);1855const ranges = await this._provider.provideFoldingRanges(doc, context, token);1856if (!Array.isArray(ranges)) {1857return undefined;1858}1859return ranges.map(typeConvert.FoldingRange.from);1860}1861}18621863class SelectionRangeAdapter {18641865constructor(1866private readonly _documents: ExtHostDocuments,1867private readonly _provider: vscode.SelectionRangeProvider,1868private readonly _logService: ILogService1869) { }18701871async provideSelectionRanges(resource: URI, pos: IPosition[], token: CancellationToken): Promise<languages.SelectionRange[][]> {1872const document = this._documents.getDocument(resource);1873const positions = pos.map(typeConvert.Position.to);18741875const allProviderRanges = await this._provider.provideSelectionRanges(document, positions, token);1876if (!isNonEmptyArray(allProviderRanges)) {1877return [];1878}1879if (allProviderRanges.length !== positions.length) {1880this._logService.warn('BAD selection ranges, provider must return ranges for each position');1881return [];1882}1883const allResults: languages.SelectionRange[][] = [];1884for (let i = 0; i < positions.length; i++) {1885const oneResult: languages.SelectionRange[] = [];1886allResults.push(oneResult);18871888let last: vscode.Position | vscode.Range = positions[i];1889let selectionRange = allProviderRanges[i];18901891while (true) {1892if (!selectionRange.range.contains(last)) {1893throw new Error('INVALID selection range, must contain the previous range');1894}1895oneResult.push(typeConvert.SelectionRange.from(selectionRange));1896if (!selectionRange.parent) {1897break;1898}1899last = selectionRange.range;1900selectionRange = selectionRange.parent;1901}1902}1903return allResults;1904}1905}19061907class CallHierarchyAdapter {19081909private readonly _idPool = new IdGenerator('');1910private readonly _cache = new Map<string, Map<string, vscode.CallHierarchyItem>>();19111912constructor(1913private readonly _documents: ExtHostDocuments,1914private readonly _provider: vscode.CallHierarchyProvider1915) { }19161917async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {1918const doc = this._documents.getDocument(uri);1919const pos = typeConvert.Position.to(position);19201921const items = await this._provider.prepareCallHierarchy(doc, pos, token);1922if (!items) {1923return undefined;1924}19251926const sessionId = this._idPool.nextId();1927this._cache.set(sessionId, new Map());19281929if (Array.isArray(items)) {1930return items.map(item => this._cacheAndConvertItem(sessionId, item));1931} else {1932return [this._cacheAndConvertItem(sessionId, items)];1933}1934}19351936async provideCallsTo(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {1937const item = this._itemFromCache(sessionId, itemId);1938if (!item) {1939throw new Error('missing call hierarchy item');1940}1941const calls = await this._provider.provideCallHierarchyIncomingCalls(item, token);1942if (!calls) {1943return undefined;1944}1945return calls.map(call => {1946return {1947from: this._cacheAndConvertItem(sessionId, call.from),1948fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))1949};1950});1951}19521953async provideCallsFrom(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {1954const item = this._itemFromCache(sessionId, itemId);1955if (!item) {1956throw new Error('missing call hierarchy item');1957}1958const calls = await this._provider.provideCallHierarchyOutgoingCalls(item, token);1959if (!calls) {1960return undefined;1961}1962return calls.map(call => {1963return {1964to: this._cacheAndConvertItem(sessionId, call.to),1965fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))1966};1967});1968}19691970releaseSession(sessionId: string): void {1971this._cache.delete(sessionId);1972}19731974private _cacheAndConvertItem(sessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {1975const map = this._cache.get(sessionId)!;1976const dto = typeConvert.CallHierarchyItem.from(item, sessionId, map.size.toString(36));1977map.set(dto._itemId, item);1978return dto;1979}19801981private _itemFromCache(sessionId: string, itemId: string): vscode.CallHierarchyItem | undefined {1982const map = this._cache.get(sessionId);1983return map?.get(itemId);1984}1985}19861987class TypeHierarchyAdapter {19881989private readonly _idPool = new IdGenerator('');1990private readonly _cache = new Map<string, Map<string, vscode.TypeHierarchyItem>>();19911992constructor(1993private readonly _documents: ExtHostDocuments,1994private readonly _provider: vscode.TypeHierarchyProvider1995) { }19961997async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {1998const doc = this._documents.getDocument(uri);1999const pos = typeConvert.Position.to(position);20002001const items = await this._provider.prepareTypeHierarchy(doc, pos, token);2002if (!items) {2003return undefined;2004}20052006const sessionId = this._idPool.nextId();2007this._cache.set(sessionId, new Map());20082009if (Array.isArray(items)) {2010return items.map(item => this._cacheAndConvertItem(sessionId, item));2011} else {2012return [this._cacheAndConvertItem(sessionId, items)];2013}2014}20152016async provideSupertypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2017const item = this._itemFromCache(sessionId, itemId);2018if (!item) {2019throw new Error('missing type hierarchy item');2020}2021const supertypes = await this._provider.provideTypeHierarchySupertypes(item, token);2022if (!supertypes) {2023return undefined;2024}2025return supertypes.map(supertype => {2026return this._cacheAndConvertItem(sessionId, supertype);2027});2028}20292030async provideSubtypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2031const item = this._itemFromCache(sessionId, itemId);2032if (!item) {2033throw new Error('missing type hierarchy item');2034}2035const subtypes = await this._provider.provideTypeHierarchySubtypes(item, token);2036if (!subtypes) {2037return undefined;2038}2039return subtypes.map(subtype => {2040return this._cacheAndConvertItem(sessionId, subtype);2041});2042}20432044releaseSession(sessionId: string): void {2045this._cache.delete(sessionId);2046}20472048private _cacheAndConvertItem(sessionId: string, item: vscode.TypeHierarchyItem): extHostProtocol.ITypeHierarchyItemDto {2049const map = this._cache.get(sessionId)!;2050const dto = typeConvert.TypeHierarchyItem.from(item, sessionId, map.size.toString(36));2051map.set(dto._itemId, item);2052return dto;2053}20542055private _itemFromCache(sessionId: string, itemId: string): vscode.TypeHierarchyItem | undefined {2056const map = this._cache.get(sessionId);2057return map?.get(itemId);2058}2059}20602061class DocumentDropEditAdapter {20622063private readonly _cache = new Cache<vscode.DocumentDropEdit>('DocumentDropEdit');20642065constructor(2066private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,2067private readonly _documents: ExtHostDocuments,2068private readonly _provider: vscode.DocumentDropEditProvider,2069private readonly _handle: number,2070private readonly _extension: IExtensionDescription,2071) { }20722073async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentDropEditDto[] | undefined> {2074const doc = this._documents.getDocument(uri);2075const pos = typeConvert.Position.to(position);2076const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (id) => {2077return (await this._proxy.$resolveDocumentOnDropFileData(this._handle, requestId, id)).buffer;2078});20792080const edits = await this._provider.provideDocumentDropEdits(doc, pos, dataTransfer, token);2081if (!edits) {2082return undefined;2083}20842085const editsArray = asArray(edits);2086const cacheId = this._cache.add(editsArray);20872088return editsArray.map((edit, i): extHostProtocol.IDocumentDropEditDto => ({2089_cacheId: [cacheId, i],2090title: edit.title ?? localize('defaultDropLabel', "Drop using '{0}' extension", this._extension.displayName || this._extension.name),2091kind: edit.kind?.value,2092yieldTo: edit.yieldTo?.map(x => x.value),2093insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },2094additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,2095}));2096}20972098async resolveDropEdit(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2099const [sessionId, itemId] = id;2100const item = this._cache.get(sessionId, itemId);2101if (!item || !this._provider.resolveDocumentDropEdit) {2102return {}; // this should not happen...2103}21042105const resolvedItem = (await this._provider.resolveDocumentDropEdit(item, token)) ?? item;2106const additionalEdit = resolvedItem.additionalEdit ? typeConvert.WorkspaceEdit.from(resolvedItem.additionalEdit, undefined) : undefined;2107return { additionalEdit };2108}21092110releaseDropEdits(id: number): any {2111this._cache.delete(id);2112}2113}21142115type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter2116| DocumentHighlightAdapter | MultiDocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter2117| DocumentPasteEditProvider | DocumentFormattingAdapter | RangeFormattingAdapter2118| OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter2119| CompletionsAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter2120| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter2121| SelectionRangeAdapter | CallHierarchyAdapter | TypeHierarchyAdapter2122| DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter2123| EvaluatableExpressionAdapter | InlineValuesAdapter2124| LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter2125| DocumentDropEditAdapter | NewSymbolNamesAdapter;21262127class AdapterData {2128constructor(2129readonly adapter: Adapter,2130readonly extension: IExtensionDescription2131) { }2132}21332134export class ExtHostLanguageFeatures extends CoreDisposable implements extHostProtocol.ExtHostLanguageFeaturesShape {21352136private static _handlePool: number = 0;21372138private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;2139private readonly _adapter = new Map<number, AdapterData>();21402141private _inlineCompletionsUnificationState: vscode.InlineCompletionsUnificationState;2142public get inlineCompletionsUnificationState(): vscode.InlineCompletionsUnificationState {2143return this._inlineCompletionsUnificationState;2144}21452146private readonly _onDidChangeInlineCompletionsUnificationState = this._register(new Emitter<void>());2147readonly onDidChangeInlineCompletionsUnificationState = this._onDidChangeInlineCompletionsUnificationState.event;21482149constructor(2150mainContext: extHostProtocol.IMainContext,2151private readonly _uriTransformer: IURITransformer,2152private readonly _documents: ExtHostDocuments,2153private readonly _commands: ExtHostCommands,2154private readonly _diagnostics: ExtHostDiagnostics,2155private readonly _logService: ILogService,2156private readonly _apiDeprecation: IExtHostApiDeprecationService,2157private readonly _extensionTelemetry: IExtHostTelemetry2158) {2159super();2160this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures);2161this._inlineCompletionsUnificationState = {2162codeUnification: false,2163modelUnification: false,2164extensionUnification: false,2165expAssignments: []2166};2167}21682169private _transformDocumentSelector(selector: vscode.DocumentSelector, extension: IExtensionDescription): Array<extHostProtocol.IDocumentFilterDto> {2170return typeConvert.DocumentSelector.from(selector, this._uriTransformer, extension);2171}21722173private _createDisposable(handle: number): Disposable {2174return new Disposable(() => {2175this._adapter.delete(handle);2176this._proxy.$unregister(handle);2177});2178}21792180private _nextHandle(): number {2181return ExtHostLanguageFeatures._handlePool++;2182}21832184private async _withAdapter<A, R>(2185handle: number,2186ctor: { new(...args: any[]): A },2187callback: (adapter: A, extension: IExtensionDescription) => Promise<R>,2188fallbackValue: R,2189tokenToRaceAgainst: CancellationToken | undefined,2190doNotLog: boolean = false2191): Promise<R> {2192const data = this._adapter.get(handle);2193if (!data || !(data.adapter instanceof ctor)) {2194return fallbackValue;2195}21962197const t1: number = Date.now();2198if (!doNotLog) {2199this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${callback.toString().replace(/[\r\n]/g, '')}'`);2200}22012202const result = callback(data.adapter, data.extension);22032204// logging,tracing2205Promise.resolve(result).catch(err => {2206if (!isCancellationError(err)) {2207this._logService.error(`[${data.extension.identifier.value}] provider FAILED`);2208this._logService.error(err);22092210this._extensionTelemetry.onExtensionError(data.extension.identifier, err);2211}2212}).finally(() => {2213if (!doNotLog) {2214this._logService.trace(`[${data.extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`);2215}2216});22172218if (CancellationToken.isCancellationToken(tokenToRaceAgainst)) {2219return raceCancellationError(result, tokenToRaceAgainst);2220}2221return result;2222}22232224private _addNewAdapter(adapter: Adapter, extension: IExtensionDescription): number {2225const handle = this._nextHandle();2226this._adapter.set(handle, new AdapterData(adapter, extension));2227return handle;2228}22292230private static _extLabel(ext: IExtensionDescription): string {2231return ext.displayName || ext.name;2232}22332234private static _extId(ext: IExtensionDescription): string {2235return ext.identifier.value;2236}22372238// --- outline22392240registerDocumentSymbolProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable {2241const handle = this._addNewAdapter(new DocumentSymbolAdapter(this._documents, provider), extension);2242const displayName = (metadata && metadata.label) || ExtHostLanguageFeatures._extLabel(extension);2243this._proxy.$registerDocumentSymbolProvider(handle, this._transformDocumentSelector(selector, extension), displayName);2244return this._createDisposable(handle);2245}22462247$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<languages.DocumentSymbol[] | undefined> {2248return this._withAdapter(handle, DocumentSymbolAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource), token), undefined, token);2249}22502251// --- code lens22522253registerCodeLensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {2254const handle = this._nextHandle();2255const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;22562257this._adapter.set(handle, new AdapterData(new CodeLensAdapter(this._documents, this._commands.converter, provider, extension, this._extensionTelemetry, this._logService), extension));2258this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector, extension), eventHandle);2259let result = this._createDisposable(handle);22602261if (eventHandle !== undefined) {2262const subscription = provider.onDidChangeCodeLenses!(_ => this._proxy.$emitCodeLensEvent(eventHandle));2263result = Disposable.from(result, subscription);2264}22652266return result;2267}22682269$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.ICodeLensListDto | undefined> {2270return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), undefined, token, resource.scheme === 'output');2271}22722273$resolveCodeLens(handle: number, symbol: extHostProtocol.ICodeLensDto, token: CancellationToken): Promise<extHostProtocol.ICodeLensDto | undefined> {2274return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(symbol, token), undefined, undefined, true);2275}22762277$releaseCodeLenses(handle: number, cacheId: number): void {2278this._withAdapter(handle, CodeLensAdapter, adapter => Promise.resolve(adapter.releaseCodeLenses(cacheId)), undefined, undefined, true);2279}22802281// --- declaration22822283registerDefinitionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {2284const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider), extension);2285this._proxy.$registerDefinitionSupport(handle, this._transformDocumentSelector(selector, extension));2286return this._createDisposable(handle);2287}22882289$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2290return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position, token), [], token);2291}22922293registerDeclarationProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DeclarationProvider): vscode.Disposable {2294const handle = this._addNewAdapter(new DeclarationAdapter(this._documents, provider), extension);2295this._proxy.$registerDeclarationSupport(handle, this._transformDocumentSelector(selector, extension));2296return this._createDisposable(handle);2297}22982299$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2300return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.provideDeclaration(URI.revive(resource), position, token), [], token);2301}23022303registerImplementationProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {2304const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider), extension);2305this._proxy.$registerImplementationSupport(handle, this._transformDocumentSelector(selector, extension));2306return this._createDisposable(handle);2307}23082309$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2310return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position, token), [], token);2311}23122313registerTypeDefinitionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {2314const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider), extension);2315this._proxy.$registerTypeDefinitionSupport(handle, this._transformDocumentSelector(selector, extension));2316return this._createDisposable(handle);2317}23182319$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2320return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(URI.revive(resource), position, token), [], token);2321}23222323// --- extra info23242325registerHoverProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {2326const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider), extension);2327this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector, extension));2328return this._createDisposable(handle);2329}23302331$provideHover(handle: number, resource: UriComponents, position: IPosition, context: languages.HoverContext<{ id: number }> | undefined, token: CancellationToken,): Promise<extHostProtocol.HoverWithId | undefined> {2332return this._withAdapter(handle, HoverAdapter, adapter => adapter.provideHover(URI.revive(resource), position, context, token), undefined, token);2333}23342335$releaseHover(handle: number, id: number): void {2336this._withAdapter(handle, HoverAdapter, adapter => Promise.resolve(adapter.releaseHover(id)), undefined, undefined);2337}23382339// --- debug hover23402341registerEvaluatableExpressionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.EvaluatableExpressionProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {2342const handle = this._addNewAdapter(new EvaluatableExpressionAdapter(this._documents, provider), extension);2343this._proxy.$registerEvaluatableExpressionProvider(handle, this._transformDocumentSelector(selector, extension));2344return this._createDisposable(handle);2345}23462347$provideEvaluatableExpression(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.EvaluatableExpression | undefined> {2348return this._withAdapter(handle, EvaluatableExpressionAdapter, adapter => adapter.provideEvaluatableExpression(URI.revive(resource), position, token), undefined, token);2349}23502351// --- debug inline values23522353registerInlineValuesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineValuesProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {23542355const eventHandle = typeof provider.onDidChangeInlineValues === 'function' ? this._nextHandle() : undefined;2356const handle = this._addNewAdapter(new InlineValuesAdapter(this._documents, provider), extension);23572358this._proxy.$registerInlineValuesProvider(handle, this._transformDocumentSelector(selector, extension), eventHandle);2359let result = this._createDisposable(handle);23602361if (eventHandle !== undefined) {2362const subscription = provider.onDidChangeInlineValues!(_ => this._proxy.$emitInlineValuesEvent(eventHandle));2363result = Disposable.from(result, subscription);2364}2365return result;2366}23672368$provideInlineValues(handle: number, resource: UriComponents, range: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<languages.InlineValue[] | undefined> {2369return this._withAdapter(handle, InlineValuesAdapter, adapter => adapter.provideInlineValues(URI.revive(resource), range, context, token), undefined, token);2370}23712372// --- occurrences23732374registerDocumentHighlightProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {2375const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider), extension);2376this._proxy.$registerDocumentHighlightProvider(handle, this._transformDocumentSelector(selector, extension));2377return this._createDisposable(handle);2378}23792380registerMultiDocumentHighlightProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.MultiDocumentHighlightProvider): vscode.Disposable {2381const handle = this._addNewAdapter(new MultiDocumentHighlightAdapter(this._documents, provider, this._logService), extension);2382this._proxy.$registerMultiDocumentHighlightProvider(handle, this._transformDocumentSelector(selector, extension));2383return this._createDisposable(handle);2384}23852386$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.DocumentHighlight[] | undefined> {2387return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position, token), undefined, token);2388}23892390$provideMultiDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, otherModels: UriComponents[], token: CancellationToken): Promise<languages.MultiDocumentHighlight[] | undefined> {2391return this._withAdapter(handle, MultiDocumentHighlightAdapter, adapter => adapter.provideMultiDocumentHighlights(URI.revive(resource), position, otherModels.map(model => URI.revive(model)), token), undefined, token);2392}23932394// --- linked editing23952396registerLinkedEditingRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.LinkedEditingRangeProvider): vscode.Disposable {2397const handle = this._addNewAdapter(new LinkedEditingRangeAdapter(this._documents, provider), extension);2398this._proxy.$registerLinkedEditingRangeProvider(handle, this._transformDocumentSelector(selector, extension));2399return this._createDisposable(handle);2400}24012402$provideLinkedEditingRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ILinkedEditingRangesDto | undefined> {2403return this._withAdapter(handle, LinkedEditingRangeAdapter, async adapter => {2404const res = await adapter.provideLinkedEditingRanges(URI.revive(resource), position, token);2405if (res) {2406return {2407ranges: res.ranges,2408wordPattern: res.wordPattern ? ExtHostLanguageFeatures._serializeRegExp(res.wordPattern) : undefined2409};2410}2411return undefined;2412}, undefined, token);2413}24142415// --- references24162417registerReferenceProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {2418const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider), extension);2419this._proxy.$registerReferenceSupport(handle, this._transformDocumentSelector(selector, extension));2420return this._createDisposable(handle);2421}24222423$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: languages.ReferenceContext, token: CancellationToken): Promise<languages.Location[] | undefined> {2424return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context, token), undefined, token);2425}24262427// --- code actions24282429registerCodeActionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {2430const store = new DisposableStore();2431const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider, this._logService, extension, this._apiDeprecation), extension);2432this._proxy.$registerCodeActionSupport(handle, this._transformDocumentSelector(selector, extension), {2433providedKinds: metadata?.providedCodeActionKinds?.map(kind => kind.value),2434documentation: metadata?.documentation?.map(x => ({2435kind: x.kind.value,2436command: this._commands.converter.toInternal(x.command, store),2437}))2438}, ExtHostLanguageFeatures._extLabel(extension), ExtHostLanguageFeatures._extId(extension), Boolean(provider.resolveCodeAction));2439store.add(this._createDisposable(handle));2440return store;2441}244224432444$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<extHostProtocol.ICodeActionListDto | undefined> {2445return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token), undefined, token);2446}24472448$resolveCodeAction(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ edit?: extHostProtocol.IWorkspaceEditDto; command?: extHostProtocol.ICommandDto }> {2449return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.resolveCodeAction(id, token), {}, undefined);2450}24512452$releaseCodeActions(handle: number, cacheId: number): void {2453this._withAdapter(handle, CodeActionAdapter, adapter => Promise.resolve(adapter.releaseCodeActions(cacheId)), undefined, undefined);2454}24552456// --- formatting24572458registerDocumentFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {2459const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider), extension);2460this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector, extension), extension.identifier, extension.displayName || extension.name);2461return this._createDisposable(handle);2462}24632464$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2465return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options, token), undefined, token);2466}24672468registerDocumentRangeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {2469const canFormatMultipleRanges = typeof provider.provideDocumentRangesFormattingEdits === 'function';2470const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider), extension);2471this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector, extension), extension.identifier, extension.displayName || extension.name, canFormatMultipleRanges);2472return this._createDisposable(handle);2473}24742475$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2476return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options, token), undefined, token);2477}24782479$provideDocumentRangesFormattingEdits(handle: number, resource: UriComponents, ranges: IRange[], options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2480return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangesFormattingEdits(URI.revive(resource), ranges, options, token), undefined, token);2481}24822483registerOnTypeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {2484const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider), extension);2485this._proxy.$registerOnTypeFormattingSupport(handle, this._transformDocumentSelector(selector, extension), triggerCharacters, extension.identifier);2486return this._createDisposable(handle);2487}24882489$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2490return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options, token), undefined, token);2491}24922493// --- navigate types24942495registerWorkspaceSymbolProvider(extension: IExtensionDescription, provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {2496const handle = this._addNewAdapter(new NavigateTypeAdapter(provider, this._logService), extension);2497this._proxy.$registerNavigateTypeSupport(handle, typeof provider.resolveWorkspaceSymbol === 'function');2498return this._createDisposable(handle);2499}25002501$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolsDto> {2502return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search, token), { symbols: [] }, token);2503}25042505$resolveWorkspaceSymbol(handle: number, symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {2506return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol, token), undefined, undefined);2507}25082509$releaseWorkspaceSymbols(handle: number, id: number): void {2510this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id), undefined, undefined);2511}25122513// --- rename25142515registerRenameProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {2516const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider, this._logService), extension);2517this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector, extension), RenameAdapter.supportsResolving(provider));2518return this._createDisposable(handle);2519}25202521$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto | undefined> {2522return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName, token), undefined, token);2523}25242525$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Promise<languages.RenameLocation | undefined> {2526return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token), undefined, token);2527}25282529registerNewSymbolNamesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.NewSymbolNamesProvider): vscode.Disposable {2530const handle = this._addNewAdapter(new NewSymbolNamesAdapter(this._documents, provider, this._logService), extension);2531this._proxy.$registerNewSymbolNamesProvider(handle, this._transformDocumentSelector(selector, extension));2532return this._createDisposable(handle);2533}25342535$supportsAutomaticNewSymbolNamesTriggerKind(handle: number): Promise<boolean | undefined> {2536return this._withAdapter(2537handle,2538NewSymbolNamesAdapter,2539adapter => adapter.supportsAutomaticNewSymbolNamesTriggerKind(),2540false,2541undefined2542);2543}25442545$provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {2546return this._withAdapter(handle, NewSymbolNamesAdapter, adapter => adapter.provideNewSymbolNames(URI.revive(resource), range, triggerKind, token), undefined, token);2547}25482549//#region semantic coloring25502551registerDocumentSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {2552const handle = this._addNewAdapter(new DocumentSemanticTokensAdapter(this._documents, provider), extension);2553const eventHandle = (typeof provider.onDidChangeSemanticTokens === 'function' ? this._nextHandle() : undefined);2554this._proxy.$registerDocumentSemanticTokensProvider(handle, this._transformDocumentSelector(selector, extension), legend, eventHandle);2555let result = this._createDisposable(handle);25562557if (eventHandle) {2558const subscription = provider.onDidChangeSemanticTokens!(_ => this._proxy.$emitDocumentSemanticTokensEvent(eventHandle));2559result = Disposable.from(result, subscription);2560}25612562return result;2563}25642565$provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {2566return this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.provideDocumentSemanticTokens(URI.revive(resource), previousResultId, token), null, token);2567}25682569$releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void {2570this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.releaseDocumentSemanticColoring(semanticColoringResultId), undefined, undefined);2571}25722573registerDocumentRangeSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {2574const handle = this._addNewAdapter(new DocumentRangeSemanticTokensAdapter(this._documents, provider), extension);2575const eventHandle = (typeof provider.onDidChangeSemanticTokens === 'function' ? this._nextHandle() : undefined);2576this._proxy.$registerDocumentRangeSemanticTokensProvider(handle, this._transformDocumentSelector(selector, extension), legend, eventHandle);2577let result = this._createDisposable(handle);25782579if (eventHandle) {2580const subscription = provider.onDidChangeSemanticTokens!(_ => this._proxy.$emitDocumentRangeSemanticTokensEvent(eventHandle));2581result = Disposable.from(result, subscription);2582}25832584return result;2585}25862587$provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<VSBuffer | null> {2588return this._withAdapter(handle, DocumentRangeSemanticTokensAdapter, adapter => adapter.provideDocumentRangeSemanticTokens(URI.revive(resource), range, token), null, token);2589}25902591//#endregion25922593// --- suggestion25942595registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {2596const handle = this._addNewAdapter(new CompletionsAdapter(this._documents, this._commands.converter, provider, this._apiDeprecation, extension), extension);2597this._proxy.$registerCompletionsProvider(handle, this._transformDocumentSelector(selector, extension), triggerCharacters, CompletionsAdapter.supportsResolving(provider), extension.identifier);2598return this._createDisposable(handle);2599}26002601$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: languages.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {2602return this._withAdapter(handle, CompletionsAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined, token);2603}26042605$resolveCompletionItem(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {2606return this._withAdapter(handle, CompletionsAdapter, adapter => adapter.resolveCompletionItem(id, token), undefined, token);2607}26082609$releaseCompletionItems(handle: number, id: number): void {2610this._withAdapter(handle, CompletionsAdapter, adapter => adapter.releaseCompletionItems(id), undefined, undefined);2611}26122613// --- ghost text26142615registerInlineCompletionsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider, metadata: vscode.InlineCompletionItemProviderMetadata | undefined): vscode.Disposable {2616const adapter = new InlineCompletionAdapter(extension, this._documents, provider, this._commands.converter);2617const handle = this._addNewAdapter(adapter, extension);2618let result = this._createDisposable(handle);26192620const supportsOnDidChange = isProposedApiEnabled(extension, 'inlineCompletionsAdditions') && typeof provider.onDidChange === 'function';2621if (supportsOnDidChange) {2622const subscription = provider.onDidChange!(e => this._proxy.$emitInlineCompletionsChange(handle, e ? { data: e.data } : undefined));2623result = Disposable.from(result, subscription);2624}26252626const supportsOnDidChangeModelInfo = isProposedApiEnabled(extension, 'inlineCompletionsAdditions') && typeof provider.onDidChangeModelInfo === 'function';2627if (supportsOnDidChangeModelInfo) {2628const subscription = provider.onDidChangeModelInfo!(_ => this._proxy.$emitInlineCompletionModelInfoChange(handle, adapter.modelInfo));2629result = Disposable.from(result, subscription);2630}2631this._proxy.$registerInlineCompletionsSupport(2632handle,2633this._transformDocumentSelector(selector, extension),2634adapter.supportsHandleEvents,2635ExtensionIdentifier.toKey(extension.identifier.value),2636extension.version,2637metadata?.groupId ? ExtensionIdentifier.toKey(metadata.groupId) : undefined,2638metadata?.yieldTo?.map(extId => ExtensionIdentifier.toKey(extId)) || [],2639metadata?.displayName,2640metadata?.debounceDelayMs,2641metadata?.excludes?.map(extId => ExtensionIdentifier.toKey(extId)) || [],2642supportsOnDidChange,2643adapter.supportsSetModelId,2644adapter.modelInfo,2645supportsOnDidChangeModelInfo,2646);2647return result;2648}26492650$provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {2651return this._withAdapter(handle, InlineCompletionAdapter, adapter => adapter.provideInlineCompletions(URI.revive(resource), position, context, token), undefined, undefined);2652}26532654$handleInlineCompletionDidShow(handle: number, pid: number, idx: number, updatedInsertText: string): void {2655this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2656adapter.handleDidShowCompletionItem(pid, idx, updatedInsertText);2657}, undefined, undefined);2658}26592660$handleInlineCompletionPartialAccept(handle: number, pid: number, idx: number, acceptedCharacters: number, info: languages.PartialAcceptInfo): void {2661this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2662adapter.handlePartialAccept(pid, idx, acceptedCharacters, info);2663}, undefined, undefined);2664}26652666$handleInlineCompletionEndOfLifetime(handle: number, pid: number, idx: number, reason: languages.InlineCompletionEndOfLifeReason<{ pid: number; idx: number }>): void {2667this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2668adapter.handleEndOfLifetime(pid, idx, reason);2669}, undefined, undefined);2670}26712672$handleInlineCompletionRejection(handle: number, pid: number, idx: number): void {2673this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2674adapter.handleRejection(pid, idx);2675}, undefined, undefined);2676}26772678$freeInlineCompletionsList(handle: number, pid: number, reason: languages.InlineCompletionsDisposeReason): void {2679this._withAdapter(handle, InlineCompletionAdapter, async adapter => { adapter.disposeCompletions(pid, reason); }, undefined, undefined);2680}26812682$acceptInlineCompletionsUnificationState(state: IInlineCompletionsUnificationState): void {2683this._inlineCompletionsUnificationState = state;2684this._onDidChangeInlineCompletionsUnificationState.fire();2685}26862687$handleInlineCompletionSetCurrentModelId(handle: number, modelId: string): void {2688this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2689adapter.setCurrentModelId(modelId);2690}, undefined, undefined);2691}26922693// --- parameter hints26942695registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {2696const metadata: extHostProtocol.ISignatureHelpProviderMetadataDto | undefined = Array.isArray(metadataOrTriggerChars)2697? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }2698: metadataOrTriggerChars;26992700const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider), extension);2701this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector, extension), metadata);2702return this._createDisposable(handle);2703}27042705$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: extHostProtocol.ISignatureHelpContextDto, token: CancellationToken): Promise<extHostProtocol.ISignatureHelpDto | undefined> {2706return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token), undefined, token);2707}27082709$releaseSignatureHelp(handle: number, id: number): void {2710this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.releaseSignatureHelp(id), undefined, undefined);2711}27122713// --- inline hints27142715registerInlayHintsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {27162717const eventHandle = typeof provider.onDidChangeInlayHints === 'function' ? this._nextHandle() : undefined;2718const handle = this._addNewAdapter(new InlayHintsAdapter(this._documents, this._commands.converter, provider, this._logService, extension), extension);27192720this._proxy.$registerInlayHintsProvider(handle, this._transformDocumentSelector(selector, extension), typeof provider.resolveInlayHint === 'function', eventHandle, ExtHostLanguageFeatures._extLabel(extension));2721let result = this._createDisposable(handle);27222723if (eventHandle !== undefined) {2724const subscription = provider.onDidChangeInlayHints!(uri => this._proxy.$emitInlayHintsEvent(eventHandle));2725result = Disposable.from(result, subscription);2726}2727return result;2728}27292730$provideInlayHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {2731return this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.provideInlayHints(URI.revive(resource), range, token), undefined, token);2732}27332734$resolveInlayHint(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.IInlayHintDto | undefined> {2735return this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.resolveInlayHint(id, token), undefined, token);2736}27372738$releaseInlayHints(handle: number, id: number): void {2739this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.releaseHints(id), undefined, undefined);2740}27412742// --- links27432744registerDocumentLinkProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {2745const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, provider), extension);2746this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector, extension), typeof provider.resolveDocumentLink === 'function');2747return this._createDisposable(handle);2748}27492750$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {2751return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token), undefined, token, resource.scheme === 'output');2752}27532754$resolveDocumentLink(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {2755return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(id, token), undefined, undefined, true);2756}27572758$releaseDocumentLinks(handle: number, id: number): void {2759this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.releaseLinks(id), undefined, undefined, true);2760}27612762registerColorProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {2763const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider), extension);2764this._proxy.$registerDocumentColorProvider(handle, this._transformDocumentSelector(selector, extension));2765return this._createDisposable(handle);2766}27672768$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.IRawColorInfo[]> {2769return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource), token), [], token);2770}27712772$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: extHostProtocol.IRawColorInfo, token: CancellationToken): Promise<languages.IColorPresentation[] | undefined> {2773return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo, token), undefined, token);2774}27752776registerFoldingRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable {2777const handle = this._nextHandle();2778const eventHandle = typeof provider.onDidChangeFoldingRanges === 'function' ? this._nextHandle() : undefined;27792780this._adapter.set(handle, new AdapterData(new FoldingProviderAdapter(this._documents, provider), extension));2781this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector, extension), extension.identifier, eventHandle);2782let result = this._createDisposable(handle);27832784if (eventHandle !== undefined) {2785const subscription = provider.onDidChangeFoldingRanges!(() => this._proxy.$emitFoldingRangeEvent(eventHandle));2786result = Disposable.from(result, subscription);2787}27882789return result;2790}27912792$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext, token: CancellationToken): Promise<languages.FoldingRange[] | undefined> {2793return this._withAdapter(2794handle,2795FoldingProviderAdapter,2796(adapter) =>2797adapter.provideFoldingRanges(URI.revive(resource), context, token),2798undefined,2799token2800);2801}28022803// --- smart select28042805registerSelectionRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SelectionRangeProvider): vscode.Disposable {2806const handle = this._addNewAdapter(new SelectionRangeAdapter(this._documents, provider, this._logService), extension);2807this._proxy.$registerSelectionRangeProvider(handle, this._transformDocumentSelector(selector, extension));2808return this._createDisposable(handle);2809}28102811$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<languages.SelectionRange[][]> {2812return this._withAdapter(handle, SelectionRangeAdapter, adapter => adapter.provideSelectionRanges(URI.revive(resource), positions, token), [], token);2813}28142815// --- call hierarchy28162817registerCallHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CallHierarchyProvider): vscode.Disposable {2818const handle = this._addNewAdapter(new CallHierarchyAdapter(this._documents, provider), extension);2819this._proxy.$registerCallHierarchyProvider(handle, this._transformDocumentSelector(selector, extension));2820return this._createDisposable(handle);2821}28222823$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {2824return this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined, token);2825}28262827$provideCallHierarchyIncomingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {2828return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsTo(sessionId, itemId, token), undefined, token);2829}28302831$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {2832return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsFrom(sessionId, itemId, token), undefined, token);2833}28342835$releaseCallHierarchy(handle: number, sessionId: string): void {2836this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined, undefined);2837}28382839// --- type hierarchy2840registerTypeHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.TypeHierarchyProvider): vscode.Disposable {2841const handle = this._addNewAdapter(new TypeHierarchyAdapter(this._documents, provider), extension);2842this._proxy.$registerTypeHierarchyProvider(handle, this._transformDocumentSelector(selector, extension));2843return this._createDisposable(handle);2844}28452846$prepareTypeHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2847return this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined, token);2848}28492850$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2851return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSupertypes(sessionId, itemId, token), undefined, token);2852}28532854$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2855return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSubtypes(sessionId, itemId, token), undefined, token);2856}28572858$releaseTypeHierarchy(handle: number, sessionId: string): void {2859this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined, undefined);2860}28612862// --- Document on drop28632864registerDocumentOnDropEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentDropEditProvider, metadata?: vscode.DocumentDropEditProviderMetadata) {2865const handle = this._nextHandle();2866this._adapter.set(handle, new AdapterData(new DocumentDropEditAdapter(this._proxy, this._documents, provider, handle, extension), extension));28672868this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), metadata ? {2869supportsResolve: !!provider.resolveDocumentDropEdit,2870dropMimeTypes: metadata.dropMimeTypes,2871providedDropKinds: metadata.providedDropEditKinds?.map(x => x.value),2872} : undefined);28732874return this._createDisposable(handle);2875}28762877$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentDropEditDto[] | undefined> {2878return this._withAdapter(handle, DocumentDropEditAdapter, adapter =>2879Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined);2880}28812882$resolveDropEdit(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2883return this._withAdapter(handle, DocumentDropEditAdapter, adapter => adapter.resolveDropEdit(id, token), {}, undefined);2884}28852886$releaseDocumentOnDropEdits(handle: number, cacheId: number): void {2887this._withAdapter(handle, DocumentDropEditAdapter, adapter => Promise.resolve(adapter.releaseDropEdits(cacheId)), undefined, undefined);2888}28892890// --- copy/paste actions28912892registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable {2893const handle = this._nextHandle();2894this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle, extension), extension));2895this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector, extension), {2896supportsCopy: !!provider.prepareDocumentPaste,2897supportsPaste: !!provider.provideDocumentPasteEdits,2898supportsResolve: !!provider.resolveDocumentPasteEdit,2899providedPasteEditKinds: metadata.providedPasteEditKinds?.map(x => x.value),2900copyMimeTypes: metadata.copyMimeTypes,2901pasteMimeTypes: metadata.pasteMimeTypes,2902});2903return this._createDisposable(handle);2904}29052906$prepareDocumentPaste(handle: number, resource: UriComponents, ranges: IRange[], dataTransfer: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {2907return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.prepareDocumentPaste(URI.revive(resource), ranges, dataTransfer, token), undefined, token);2908}29092910$providePasteEdits(handle: number, requestId: number, resource: UriComponents, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, context: extHostProtocol.IDocumentPasteContextDto, token: CancellationToken): Promise<extHostProtocol.IPasteEditDto[] | undefined> {2911return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.providePasteEdits(requestId, URI.revive(resource), ranges, dataTransferDto, context, token), undefined, token);2912}29132914$resolvePasteEdit(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2915return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.resolvePasteEdit(id, token), {}, undefined);2916}29172918$releasePasteEdits(handle: number, cacheId: number): void {2919this._withAdapter(handle, DocumentPasteEditProvider, adapter => Promise.resolve(adapter.releasePasteEdits(cacheId)), undefined, undefined);2920}29212922// --- configuration29232924private static _serializeRegExp(regExp: RegExp): extHostProtocol.IRegExpDto {2925return {2926pattern: regExp.source,2927flags: regExp.flags,2928};2929}29302931private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): extHostProtocol.IIndentationRuleDto {2932return {2933decreaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.decreaseIndentPattern),2934increaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.increaseIndentPattern),2935indentNextLinePattern: indentationRule.indentNextLinePattern ? ExtHostLanguageFeatures._serializeRegExp(indentationRule.indentNextLinePattern) : undefined,2936unIndentedLinePattern: indentationRule.unIndentedLinePattern ? ExtHostLanguageFeatures._serializeRegExp(indentationRule.unIndentedLinePattern) : undefined,2937};2938}29392940private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): extHostProtocol.IOnEnterRuleDto {2941return {2942beforeText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.beforeText),2943afterText: onEnterRule.afterText ? ExtHostLanguageFeatures._serializeRegExp(onEnterRule.afterText) : undefined,2944previousLineText: onEnterRule.previousLineText ? ExtHostLanguageFeatures._serializeRegExp(onEnterRule.previousLineText) : undefined,2945action: onEnterRule.action2946};2947}29482949private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): extHostProtocol.IOnEnterRuleDto[] {2950return onEnterRules.map(ExtHostLanguageFeatures._serializeOnEnterRule);2951}29522953private static _serializeAutoClosingPair(autoClosingPair: vscode.AutoClosingPair): IAutoClosingPairConditional {2954return {2955open: autoClosingPair.open,2956close: autoClosingPair.close,2957notIn: autoClosingPair.notIn ? autoClosingPair.notIn.map(v => SyntaxTokenType.toString(v)) : undefined,2958};2959}29602961private static _serializeAutoClosingPairs(autoClosingPairs: vscode.AutoClosingPair[]): IAutoClosingPairConditional[] {2962return autoClosingPairs.map(ExtHostLanguageFeatures._serializeAutoClosingPair);2963}29642965setLanguageConfiguration(extension: IExtensionDescription, languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {2966const { wordPattern } = configuration;29672968// check for a valid word pattern2969if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {2970throw new Error(`Invalid language configuration: wordPattern '${wordPattern}' is not allowed to match the empty string.`);2971}29722973// word definition2974if (wordPattern) {2975this._documents.setWordDefinitionFor(languageId, wordPattern);2976} else {2977this._documents.setWordDefinitionFor(languageId, undefined);2978}29792980if (configuration.__electricCharacterSupport) {2981this._apiDeprecation.report('LanguageConfiguration.__electricCharacterSupport', extension,2982`Do not use.`);2983}29842985if (configuration.__characterPairSupport) {2986this._apiDeprecation.report('LanguageConfiguration.__characterPairSupport', extension,2987`Do not use.`);2988}29892990const handle = this._nextHandle();2991const serializedConfiguration: extHostProtocol.ILanguageConfigurationDto = {2992comments: configuration.comments,2993brackets: configuration.brackets,2994wordPattern: configuration.wordPattern ? ExtHostLanguageFeatures._serializeRegExp(configuration.wordPattern) : undefined,2995indentationRules: configuration.indentationRules ? ExtHostLanguageFeatures._serializeIndentationRule(configuration.indentationRules) : undefined,2996onEnterRules: configuration.onEnterRules ? ExtHostLanguageFeatures._serializeOnEnterRules(configuration.onEnterRules) : undefined,2997__electricCharacterSupport: configuration.__electricCharacterSupport,2998__characterPairSupport: configuration.__characterPairSupport,2999autoClosingPairs: configuration.autoClosingPairs ? ExtHostLanguageFeatures._serializeAutoClosingPairs(configuration.autoClosingPairs) : undefined,3000};30013002this._proxy.$setLanguageConfiguration(handle, languageId, serializedConfiguration);3003return this._createDisposable(handle);3004}30053006$setWordDefinitions(wordDefinitions: extHostProtocol.ILanguageWordDefinitionDto[]): void {3007for (const wordDefinition of wordDefinitions) {3008this._documents.setWordDefinitionFor(wordDefinition.languageId, new RegExp(wordDefinition.regexSource, wordDefinition.regexFlags));3009}3010}3011}301230133014