Path: blob/main/src/vs/workbench/api/common/extHostLanguageFeatures.ts
3296 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, InlineCompletionDisplayLocationKind, 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)) {196return (<any>value).map(typeConvert.DefinitionLink.from);197} else if (value) {198return [typeConvert.DefinitionLink.from(value)];199}200return [];201}202203class DefinitionAdapter {204205constructor(206private readonly _documents: ExtHostDocuments,207private readonly _provider: vscode.DefinitionProvider208) { }209210async provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {211const doc = this._documents.getDocument(resource);212const pos = typeConvert.Position.to(position);213const value = await this._provider.provideDefinition(doc, pos, token);214return convertToLocationLinks(value);215}216}217218class DeclarationAdapter {219220constructor(221private readonly _documents: ExtHostDocuments,222private readonly _provider: vscode.DeclarationProvider223) { }224225async provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {226const doc = this._documents.getDocument(resource);227const pos = typeConvert.Position.to(position);228const value = await this._provider.provideDeclaration(doc, pos, token);229return convertToLocationLinks(value);230}231}232233class ImplementationAdapter {234235constructor(236private readonly _documents: ExtHostDocuments,237private readonly _provider: vscode.ImplementationProvider238) { }239240async provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {241const doc = this._documents.getDocument(resource);242const pos = typeConvert.Position.to(position);243const value = await this._provider.provideImplementation(doc, pos, token);244return convertToLocationLinks(value);245}246}247248class TypeDefinitionAdapter {249250constructor(251private readonly _documents: ExtHostDocuments,252private readonly _provider: vscode.TypeDefinitionProvider253) { }254255async provideTypeDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {256const doc = this._documents.getDocument(resource);257const pos = typeConvert.Position.to(position);258const value = await this._provider.provideTypeDefinition(doc, pos, token);259return convertToLocationLinks(value);260}261}262263class HoverAdapter {264265private _hoverCounter: number = 0;266private _hoverMap: Map<number, vscode.Hover> = new Map<number, vscode.Hover>();267268private static HOVER_MAP_MAX_SIZE = 10;269270constructor(271private readonly _documents: ExtHostDocuments,272private readonly _provider: vscode.HoverProvider,273) { }274275async provideHover(resource: URI, position: IPosition, context: languages.HoverContext<{ id: number }> | undefined, token: CancellationToken): Promise<extHostProtocol.HoverWithId | undefined> {276277const doc = this._documents.getDocument(resource);278const pos = typeConvert.Position.to(position);279280let value: vscode.Hover | null | undefined;281if (context && context.verbosityRequest) {282const previousHoverId = context.verbosityRequest.previousHover.id;283const previousHover = this._hoverMap.get(previousHoverId);284if (!previousHover) {285throw new Error(`Hover with id ${previousHoverId} not found`);286}287const hoverContext: vscode.HoverContext = { verbosityDelta: context.verbosityRequest.verbosityDelta, previousHover };288value = await this._provider.provideHover(doc, pos, token, hoverContext);289} else {290value = await this._provider.provideHover(doc, pos, token);291}292if (!value || isFalsyOrEmpty(value.contents)) {293return undefined;294}295if (!value.range) {296value.range = doc.getWordRangeAtPosition(pos);297}298if (!value.range) {299value.range = new Range(pos, pos);300}301const convertedHover: languages.Hover = typeConvert.Hover.from(value);302const id = this._hoverCounter;303// Check if hover map has more than 10 elements and if yes, remove oldest from the map304if (this._hoverMap.size === HoverAdapter.HOVER_MAP_MAX_SIZE) {305const minimumId = Math.min(...this._hoverMap.keys());306this._hoverMap.delete(minimumId);307}308this._hoverMap.set(id, value);309this._hoverCounter += 1;310const hover: extHostProtocol.HoverWithId = {311...convertedHover,312id313};314return hover;315}316317releaseHover(id: number): void {318this._hoverMap.delete(id);319}320}321322class EvaluatableExpressionAdapter {323324constructor(325private readonly _documents: ExtHostDocuments,326private readonly _provider: vscode.EvaluatableExpressionProvider,327) { }328329async provideEvaluatableExpression(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.EvaluatableExpression | undefined> {330331const doc = this._documents.getDocument(resource);332const pos = typeConvert.Position.to(position);333334const value = await this._provider.provideEvaluatableExpression(doc, pos, token);335if (value) {336return typeConvert.EvaluatableExpression.from(value);337}338return undefined;339}340}341342class InlineValuesAdapter {343344constructor(345private readonly _documents: ExtHostDocuments,346private readonly _provider: vscode.InlineValuesProvider,347) { }348349async provideInlineValues(resource: URI, viewPort: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<languages.InlineValue[] | undefined> {350const doc = this._documents.getDocument(resource);351const value = await this._provider.provideInlineValues(doc, typeConvert.Range.to(viewPort), typeConvert.InlineValueContext.to(context), token);352if (Array.isArray(value)) {353return value.map(iv => typeConvert.InlineValue.from(iv));354}355return undefined;356}357}358359class DocumentHighlightAdapter {360361constructor(362private readonly _documents: ExtHostDocuments,363private readonly _provider: vscode.DocumentHighlightProvider364) { }365366async provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.DocumentHighlight[] | undefined> {367368const doc = this._documents.getDocument(resource);369const pos = typeConvert.Position.to(position);370371const value = await this._provider.provideDocumentHighlights(doc, pos, token);372if (Array.isArray(value)) {373return value.map(typeConvert.DocumentHighlight.from);374}375return undefined;376}377}378379class MultiDocumentHighlightAdapter {380381constructor(382private readonly _documents: ExtHostDocuments,383private readonly _provider: vscode.MultiDocumentHighlightProvider,384private readonly _logService: ILogService,385) { }386387async provideMultiDocumentHighlights(resource: URI, position: IPosition, otherResources: URI[], token: CancellationToken): Promise<languages.MultiDocumentHighlight[] | undefined> {388const doc = this._documents.getDocument(resource);389const otherDocuments = otherResources.map(r => {390try {391return this._documents.getDocument(r);392} catch (err) {393this._logService.error('Error: Unable to retrieve document from URI: ' + r + '. Error message: ' + err);394return undefined;395}396}).filter(doc => doc !== undefined);397398const pos = typeConvert.Position.to(position);399400const value = await this._provider.provideMultiDocumentHighlights(doc, pos, otherDocuments, token);401if (Array.isArray(value)) {402return value.map(typeConvert.MultiDocumentHighlight.from);403}404return undefined;405}406}407408class LinkedEditingRangeAdapter {409constructor(410private readonly _documents: ExtHostDocuments,411private readonly _provider: vscode.LinkedEditingRangeProvider412) { }413414async provideLinkedEditingRanges(resource: URI, position: IPosition, token: CancellationToken): Promise<languages.LinkedEditingRanges | undefined> {415416const doc = this._documents.getDocument(resource);417const pos = typeConvert.Position.to(position);418419const value = await this._provider.provideLinkedEditingRanges(doc, pos, token);420if (value && Array.isArray(value.ranges)) {421return {422ranges: coalesce(value.ranges.map(typeConvert.Range.from)),423wordPattern: value.wordPattern424};425}426return undefined;427}428}429430class ReferenceAdapter {431432constructor(433private readonly _documents: ExtHostDocuments,434private readonly _provider: vscode.ReferenceProvider435) { }436437async provideReferences(resource: URI, position: IPosition, context: languages.ReferenceContext, token: CancellationToken): Promise<languages.Location[] | undefined> {438const doc = this._documents.getDocument(resource);439const pos = typeConvert.Position.to(position);440441const value = await this._provider.provideReferences(doc, pos, context, token);442if (Array.isArray(value)) {443return value.map(typeConvert.location.from);444}445return undefined;446}447}448449export interface CustomCodeAction extends extHostProtocol.ICodeActionDto {450_isSynthetic?: boolean;451}452453class CodeActionAdapter {454private static readonly _maxCodeActionsPerFile: number = 1000;455456private readonly _cache = new Cache<vscode.CodeAction | vscode.Command>('CodeAction');457private readonly _disposables = new Map<number, DisposableStore>();458459constructor(460private readonly _documents: ExtHostDocuments,461private readonly _commands: CommandsConverter,462private readonly _diagnostics: ExtHostDiagnostics,463private readonly _provider: vscode.CodeActionProvider,464private readonly _logService: ILogService,465private readonly _extension: IExtensionDescription,466private readonly _apiDeprecation: IExtHostApiDeprecationService,467) { }468469async provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<extHostProtocol.ICodeActionListDto | undefined> {470471const doc = this._documents.getDocument(resource);472const ran = Selection.isISelection(rangeOrSelection)473? <vscode.Selection>typeConvert.Selection.to(rangeOrSelection)474: <vscode.Range>typeConvert.Range.to(rangeOrSelection);475const allDiagnostics: vscode.Diagnostic[] = [];476477for (const diagnostic of this._diagnostics.getDiagnostics(resource)) {478if (ran.intersection(diagnostic.range)) {479const newLen = allDiagnostics.push(diagnostic);480if (newLen > CodeActionAdapter._maxCodeActionsPerFile) {481break;482}483}484}485486const codeActionContext: vscode.CodeActionContext = {487diagnostics: allDiagnostics,488only: context.only ? new CodeActionKind(context.only) : undefined,489triggerKind: typeConvert.CodeActionTriggerKind.to(context.trigger),490};491492const commandsOrActions = await this._provider.provideCodeActions(doc, ran, codeActionContext, token);493if (!isNonEmptyArray(commandsOrActions) || token.isCancellationRequested) {494return undefined;495}496497const cacheId = this._cache.add(commandsOrActions);498const disposables = new DisposableStore();499this._disposables.set(cacheId, disposables);500const actions: CustomCodeAction[] = [];501for (let i = 0; i < commandsOrActions.length; i++) {502const candidate = commandsOrActions[i];503if (!candidate) {504continue;505}506507if (CodeActionAdapter._isCommand(candidate) && !(candidate instanceof CodeAction)) {508// old school: synthetic code action509this._apiDeprecation.report('CodeActionProvider.provideCodeActions - return commands', this._extension,510`Return 'CodeAction' instances instead.`);511512actions.push({513_isSynthetic: true,514title: candidate.title,515command: this._commands.toInternal(candidate, disposables),516});517} else {518const toConvert = candidate as vscode.CodeAction;519520// new school: convert code action521if (codeActionContext.only) {522if (!toConvert.kind) {523this._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'.`);524} else if (!codeActionContext.only.contains(toConvert.kind)) {525this._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.`);526}527}528529// Ensures that this is either a Range[] or an empty array so we don't get Array<Range | undefined>530const range = toConvert.ranges ?? [];531532actions.push({533cacheId: [cacheId, i],534title: toConvert.title,535command: toConvert.command && this._commands.toInternal(toConvert.command, disposables),536diagnostics: toConvert.diagnostics && toConvert.diagnostics.map(typeConvert.Diagnostic.from),537edit: toConvert.edit && typeConvert.WorkspaceEdit.from(toConvert.edit, undefined),538kind: toConvert.kind && toConvert.kind.value,539isPreferred: toConvert.isPreferred,540isAI: isProposedApiEnabled(this._extension, 'codeActionAI') ? toConvert.isAI : false,541ranges: isProposedApiEnabled(this._extension, 'codeActionRanges') ? coalesce(range.map(typeConvert.Range.from)) : undefined,542disabled: toConvert.disabled?.reason543});544}545}546return { cacheId, actions };547}548549async resolveCodeAction(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ edit?: extHostProtocol.IWorkspaceEditDto; command?: extHostProtocol.ICommandDto }> {550const [sessionId, itemId] = id;551const item = this._cache.get(sessionId, itemId);552if (!item || CodeActionAdapter._isCommand(item)) {553return {}; // code actions only!554}555if (!this._provider.resolveCodeAction) {556return {}; // this should not happen...557}558559560const resolvedItem = (await this._provider.resolveCodeAction(item, token)) ?? item;561562let resolvedEdit: extHostProtocol.IWorkspaceEditDto | undefined;563if (resolvedItem.edit) {564resolvedEdit = typeConvert.WorkspaceEdit.from(resolvedItem.edit, undefined);565}566567let resolvedCommand: extHostProtocol.ICommandDto | undefined;568if (resolvedItem.command) {569const disposables = this._disposables.get(sessionId);570if (disposables) {571resolvedCommand = this._commands.toInternal(resolvedItem.command, disposables);572}573}574575return { edit: resolvedEdit, command: resolvedCommand };576}577578releaseCodeActions(cachedId: number): void {579this._disposables.get(cachedId)?.dispose();580this._disposables.delete(cachedId);581this._cache.delete(cachedId);582}583584private static _isCommand(thing: any): thing is vscode.Command {585return typeof (<vscode.Command>thing).command === 'string' && typeof (<vscode.Command>thing).title === 'string';586}587}588589class DocumentPasteEditProvider {590591private _cachedPrepare?: Map<string, vscode.DataTransferItem>;592593private readonly _editsCache = new Cache<vscode.DocumentPasteEdit>('DocumentPasteEdit.edits');594595constructor(596private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,597private readonly _documents: ExtHostDocuments,598private readonly _provider: vscode.DocumentPasteEditProvider,599private readonly _handle: number,600private readonly _extension: IExtensionDescription,601) { }602603async prepareDocumentPaste(resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {604if (!this._provider.prepareDocumentPaste) {605return;606}607608this._cachedPrepare = undefined;609610const doc = this._documents.getDocument(resource);611const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));612613const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, () => {614throw new NotImplementedError();615});616await this._provider.prepareDocumentPaste(doc, vscodeRanges, dataTransfer, token);617if (token.isCancellationRequested) {618return;619}620621// Only send back values that have been added to the data transfer622const newEntries = Array.from(dataTransfer).filter(([, value]) => !(value instanceof InternalDataTransferItem));623624// Store off original data transfer items so we can retrieve them on paste625const newCache = new Map<string, vscode.DataTransferItem>();626627const items = await Promise.all(Array.from(newEntries, async ([mime, value]) => {628const id = generateUuid();629newCache.set(id, value);630return [mime, await typeConvert.DataTransferItem.from(mime, value, id)] as const;631}));632633this._cachedPrepare = newCache;634635return { items };636}637638async providePasteEdits(requestId: number, resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, context: extHostProtocol.IDocumentPasteContextDto, token: CancellationToken): Promise<extHostProtocol.IPasteEditDto[]> {639if (!this._provider.provideDocumentPasteEdits) {640return [];641}642643const doc = this._documents.getDocument(resource);644const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));645646const items = dataTransferDto.items.map(([mime, value]): [string, vscode.DataTransferItem] => {647const cached = this._cachedPrepare?.get(value.id);648if (cached) {649return [mime, cached];650}651652return [653mime,654typeConvert.DataTransferItem.to(mime, value, async id => {655return (await this._proxy.$resolvePasteFileData(this._handle, requestId, id)).buffer;656})657];658});659660const dataTransfer = new DataTransfer(items);661662const edits = await this._provider.provideDocumentPasteEdits(doc, vscodeRanges, dataTransfer, {663only: context.only ? new DocumentDropOrPasteEditKind(context.only) : undefined,664triggerKind: context.triggerKind,665}, token);666if (!edits || token.isCancellationRequested) {667return [];668}669670const cacheId = this._editsCache.add(edits);671672return edits.map((edit, i): extHostProtocol.IPasteEditDto => ({673_cacheId: [cacheId, i],674title: edit.title ?? localize('defaultPasteLabel', "Paste using '{0}' extension", this._extension.displayName || this._extension.name),675kind: edit.kind,676yieldTo: edit.yieldTo?.map(x => x.value),677insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },678additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,679}));680}681682async resolvePasteEdit(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ insertText?: string | vscode.SnippetString; additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {683const [sessionId, itemId] = id;684const item = this._editsCache.get(sessionId, itemId);685if (!item || !this._provider.resolveDocumentPasteEdit) {686return {}; // this should not happen...687}688689const resolvedItem = (await this._provider.resolveDocumentPasteEdit(item, token)) ?? item;690return {691insertText: resolvedItem.insertText,692additionalEdit: resolvedItem.additionalEdit ? typeConvert.WorkspaceEdit.from(resolvedItem.additionalEdit, undefined) : undefined693};694}695696releasePasteEdits(id: number): any {697this._editsCache.delete(id);698}699}700701class DocumentFormattingAdapter {702703constructor(704private readonly _documents: ExtHostDocuments,705private readonly _provider: vscode.DocumentFormattingEditProvider706) { }707708async provideDocumentFormattingEdits(resource: URI, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {709710const document = this._documents.getDocument(resource);711712const value = await this._provider.provideDocumentFormattingEdits(document, <any>options, token);713if (Array.isArray(value)) {714return value.map(typeConvert.TextEdit.from);715}716return undefined;717}718}719720class RangeFormattingAdapter {721722constructor(723private readonly _documents: ExtHostDocuments,724private readonly _provider: vscode.DocumentRangeFormattingEditProvider725) { }726727async provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {728729const document = this._documents.getDocument(resource);730const ran = typeConvert.Range.to(range);731732const value = await this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token);733if (Array.isArray(value)) {734return value.map(typeConvert.TextEdit.from);735}736return undefined;737}738739async provideDocumentRangesFormattingEdits(resource: URI, ranges: IRange[], options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {740assertType(typeof this._provider.provideDocumentRangesFormattingEdits === 'function', 'INVALID invocation of `provideDocumentRangesFormattingEdits`');741742const document = this._documents.getDocument(resource);743const _ranges = <Range[]>ranges.map(typeConvert.Range.to);744const value = await this._provider.provideDocumentRangesFormattingEdits(document, _ranges, <any>options, token);745if (Array.isArray(value)) {746return value.map(typeConvert.TextEdit.from);747}748return undefined;749}750}751752class OnTypeFormattingAdapter {753754constructor(755private readonly _documents: ExtHostDocuments,756private readonly _provider: vscode.OnTypeFormattingEditProvider757) { }758759autoFormatTriggerCharacters: string[] = []; // not here760761async provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {762763const document = this._documents.getDocument(resource);764const pos = typeConvert.Position.to(position);765766const value = await this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token);767if (Array.isArray(value)) {768return value.map(typeConvert.TextEdit.from);769}770return undefined;771}772}773774class NavigateTypeAdapter {775776private readonly _cache = new Cache<vscode.SymbolInformation>('WorkspaceSymbols');777778constructor(779private readonly _provider: vscode.WorkspaceSymbolProvider,780private readonly _logService: ILogService781) { }782783async provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolsDto> {784const value = await this._provider.provideWorkspaceSymbols(search, token);785786if (!isNonEmptyArray(value)) {787return { symbols: [] };788}789790const sid = this._cache.add(value);791const result: extHostProtocol.IWorkspaceSymbolsDto = {792cacheId: sid,793symbols: []794};795796for (let i = 0; i < value.length; i++) {797const item = value[i];798if (!item || !item.name) {799this._logService.warn('INVALID SymbolInformation', item);800continue;801}802result.symbols.push({803...typeConvert.WorkspaceSymbol.from(item),804cacheId: [sid, i]805});806}807808return result;809}810811async resolveWorkspaceSymbol(symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {812if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {813return symbol;814}815if (!symbol.cacheId) {816return symbol;817}818const item = this._cache.get(...symbol.cacheId);819if (item) {820const value = await this._provider.resolveWorkspaceSymbol(item, token);821return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);822}823return undefined;824}825826releaseWorkspaceSymbols(id: number): any {827this._cache.delete(id);828}829}830831class RenameAdapter {832833static supportsResolving(provider: vscode.RenameProvider): boolean {834return typeof provider.prepareRename === 'function';835}836837constructor(838private readonly _documents: ExtHostDocuments,839private readonly _provider: vscode.RenameProvider,840private readonly _logService: ILogService841) { }842843async provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto & languages.Rejection | undefined> {844845const doc = this._documents.getDocument(resource);846const pos = typeConvert.Position.to(position);847848try {849const value = await this._provider.provideRenameEdits(doc, pos, newName, token);850if (!value) {851return undefined;852}853return typeConvert.WorkspaceEdit.from(value);854855} catch (err) {856const rejectReason = RenameAdapter._asMessage(err);857if (rejectReason) {858return { rejectReason, edits: undefined! };859} else {860// generic error861return Promise.reject<extHostProtocol.IWorkspaceEditDto>(err);862}863}864}865866async resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Promise<(languages.RenameLocation & languages.Rejection) | undefined> {867if (typeof this._provider.prepareRename !== 'function') {868return Promise.resolve(undefined);869}870871const doc = this._documents.getDocument(resource);872const pos = typeConvert.Position.to(position);873874try {875const rangeOrLocation = await this._provider.prepareRename(doc, pos, token);876877let range: vscode.Range | undefined;878let text: string | undefined;879if (Range.isRange(rangeOrLocation)) {880range = rangeOrLocation;881text = doc.getText(rangeOrLocation);882883} else if (isObject(rangeOrLocation)) {884range = rangeOrLocation.range;885text = rangeOrLocation.placeholder;886}887888if (!range || !text) {889return undefined;890}891if (range.start.line > pos.line || range.end.line < pos.line) {892this._logService.warn('INVALID rename location: position line must be within range start/end lines');893return undefined;894}895return { range: typeConvert.Range.from(range), text };896897} catch (err) {898const rejectReason = RenameAdapter._asMessage(err);899if (rejectReason) {900return { rejectReason, range: undefined!, text: undefined! };901} else {902return Promise.reject<any>(err);903}904}905}906907private static _asMessage(err: any): string | undefined {908if (typeof err === 'string') {909return err;910} else if (err instanceof Error && typeof err.message === 'string') {911return err.message;912} else {913return undefined;914}915}916}917918class NewSymbolNamesAdapter {919920private static languageTriggerKindToVSCodeTriggerKind: Record<languages.NewSymbolNameTriggerKind, vscode.NewSymbolNameTriggerKind> = {921[languages.NewSymbolNameTriggerKind.Invoke]: NewSymbolNameTriggerKind.Invoke,922[languages.NewSymbolNameTriggerKind.Automatic]: NewSymbolNameTriggerKind.Automatic,923};924925constructor(926private readonly _documents: ExtHostDocuments,927private readonly _provider: vscode.NewSymbolNamesProvider,928private readonly _logService: ILogService929) { }930931async supportsAutomaticNewSymbolNamesTriggerKind() {932return this._provider.supportsAutomaticTriggerKind;933}934935async provideNewSymbolNames(resource: URI, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {936937const doc = this._documents.getDocument(resource);938const pos = typeConvert.Range.to(range);939940try {941const kind = NewSymbolNamesAdapter.languageTriggerKindToVSCodeTriggerKind[triggerKind];942const value = await this._provider.provideNewSymbolNames(doc, pos, kind, token);943if (!value) {944return undefined;945}946return value.map(v =>947typeof v === 'string' /* @ulugbekna: for backward compatibility because `value` used to be just `string[]` */948? { newSymbolName: v }949: { newSymbolName: v.newSymbolName, tags: v.tags }950);951} catch (err: unknown) {952this._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 */);953return undefined;954}955}956957// @ulugbekna: this method is also defined in RenameAdapter but seems OK to be duplicated958private static _asMessage(err: any): string | undefined {959if (typeof err === 'string') {960return err;961} else if (err instanceof Error && typeof err.message === 'string') {962return err.message;963} else {964return undefined;965}966}967}968969class SemanticTokensPreviousResult {970constructor(971readonly resultId: string | undefined,972readonly tokens?: Uint32Array,973) { }974}975976type RelaxedSemanticTokens = { readonly resultId?: string; readonly data: number[] };977type RelaxedSemanticTokensEdit = { readonly start: number; readonly deleteCount: number; readonly data?: number[] };978type RelaxedSemanticTokensEdits = { readonly resultId?: string; readonly edits: RelaxedSemanticTokensEdit[] };979980type ProvidedSemanticTokens = vscode.SemanticTokens | RelaxedSemanticTokens;981type ProvidedSemanticTokensEdits = vscode.SemanticTokensEdits | RelaxedSemanticTokensEdits;982983class DocumentSemanticTokensAdapter {984985private readonly _previousResults: Map<number, SemanticTokensPreviousResult>;986private _nextResultId = 1;987988constructor(989private readonly _documents: ExtHostDocuments,990private readonly _provider: vscode.DocumentSemanticTokensProvider,991) {992this._previousResults = new Map<number, SemanticTokensPreviousResult>();993}994995async provideDocumentSemanticTokens(resource: URI, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {996const doc = this._documents.getDocument(resource);997const previousResult = (previousResultId !== 0 ? this._previousResults.get(previousResultId) : null);998let value = typeof previousResult?.resultId === 'string' && typeof this._provider.provideDocumentSemanticTokensEdits === 'function'999? await this._provider.provideDocumentSemanticTokensEdits(doc, previousResult.resultId, token)1000: await this._provider.provideDocumentSemanticTokens(doc, token);10011002if (previousResult) {1003this._previousResults.delete(previousResultId);1004}1005if (!value) {1006return null;1007}1008value = DocumentSemanticTokensAdapter._fixProvidedSemanticTokens(value);1009return this._send(DocumentSemanticTokensAdapter._convertToEdits(previousResult, value), value);1010}10111012async releaseDocumentSemanticColoring(semanticColoringResultId: number): Promise<void> {1013this._previousResults.delete(semanticColoringResultId);1014}10151016private static _fixProvidedSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {1017if (DocumentSemanticTokensAdapter._isSemanticTokens(v)) {1018if (DocumentSemanticTokensAdapter._isCorrectSemanticTokens(v)) {1019return v;1020}1021return new SemanticTokens(new Uint32Array(v.data), v.resultId);1022} else if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(v)) {1023if (DocumentSemanticTokensAdapter._isCorrectSemanticTokensEdits(v)) {1024return v;1025}1026return new SemanticTokensEdits(v.edits.map(edit => new SemanticTokensEdit(edit.start, edit.deleteCount, edit.data ? new Uint32Array(edit.data) : edit.data)), v.resultId);1027}1028return v;1029}10301031private static _isSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokens {1032return v && !!((v as ProvidedSemanticTokens).data);1033}10341035private static _isCorrectSemanticTokens(v: ProvidedSemanticTokens): v is vscode.SemanticTokens {1036return (v.data instanceof Uint32Array);1037}10381039private static _isSemanticTokensEdits(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokensEdits {1040return v && Array.isArray((v as ProvidedSemanticTokensEdits).edits);1041}10421043private static _isCorrectSemanticTokensEdits(v: ProvidedSemanticTokensEdits): v is vscode.SemanticTokensEdits {1044for (const edit of v.edits) {1045if (!(edit.data instanceof Uint32Array)) {1046return false;1047}1048}1049return true;1050}10511052private static _convertToEdits(previousResult: SemanticTokensPreviousResult | null | undefined, newResult: vscode.SemanticTokens | vscode.SemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {1053if (!DocumentSemanticTokensAdapter._isSemanticTokens(newResult)) {1054return newResult;1055}1056if (!previousResult || !previousResult.tokens) {1057return newResult;1058}1059const oldData = previousResult.tokens;1060const oldLength = oldData.length;1061const newData = newResult.data;1062const newLength = newData.length;10631064let commonPrefixLength = 0;1065const maxCommonPrefixLength = Math.min(oldLength, newLength);1066while (commonPrefixLength < maxCommonPrefixLength && oldData[commonPrefixLength] === newData[commonPrefixLength]) {1067commonPrefixLength++;1068}10691070if (commonPrefixLength === oldLength && commonPrefixLength === newLength) {1071// complete overlap!1072return new SemanticTokensEdits([], newResult.resultId);1073}10741075let commonSuffixLength = 0;1076const maxCommonSuffixLength = maxCommonPrefixLength - commonPrefixLength;1077while (commonSuffixLength < maxCommonSuffixLength && oldData[oldLength - commonSuffixLength - 1] === newData[newLength - commonSuffixLength - 1]) {1078commonSuffixLength++;1079}10801081return new SemanticTokensEdits([{1082start: commonPrefixLength,1083deleteCount: (oldLength - commonPrefixLength - commonSuffixLength),1084data: newData.subarray(commonPrefixLength, newLength - commonSuffixLength)1085}], newResult.resultId);1086}10871088private _send(value: vscode.SemanticTokens | vscode.SemanticTokensEdits, original: vscode.SemanticTokens | vscode.SemanticTokensEdits): VSBuffer | null {1089if (DocumentSemanticTokensAdapter._isSemanticTokens(value)) {1090const myId = this._nextResultId++;1091this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId, value.data));1092return encodeSemanticTokensDto({1093id: myId,1094type: 'full',1095data: value.data1096});1097}10981099if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(value)) {1100const myId = this._nextResultId++;1101if (DocumentSemanticTokensAdapter._isSemanticTokens(original)) {1102// store the original1103this._previousResults.set(myId, new SemanticTokensPreviousResult(original.resultId, original.data));1104} else {1105this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId));1106}1107return encodeSemanticTokensDto({1108id: myId,1109type: 'delta',1110deltas: (value.edits || []).map(edit => ({ start: edit.start, deleteCount: edit.deleteCount, data: edit.data }))1111});1112}11131114return null;1115}1116}11171118class DocumentRangeSemanticTokensAdapter {11191120constructor(1121private readonly _documents: ExtHostDocuments,1122private readonly _provider: vscode.DocumentRangeSemanticTokensProvider,1123) { }11241125async provideDocumentRangeSemanticTokens(resource: URI, range: IRange, token: CancellationToken): Promise<VSBuffer | null> {1126const doc = this._documents.getDocument(resource);1127const value = await this._provider.provideDocumentRangeSemanticTokens(doc, typeConvert.Range.to(range), token);1128if (!value) {1129return null;1130}1131return this._send(value);1132}11331134private _send(value: vscode.SemanticTokens): VSBuffer {1135return encodeSemanticTokensDto({1136id: 0,1137type: 'full',1138data: value.data1139});1140}1141}11421143class CompletionsAdapter {11441145static supportsResolving(provider: vscode.CompletionItemProvider): boolean {1146return typeof provider.resolveCompletionItem === 'function';1147}11481149private _cache = new Cache<vscode.CompletionItem>('CompletionItem');1150private _disposables = new Map<number, DisposableStore>();11511152constructor(1153private readonly _documents: ExtHostDocuments,1154private readonly _commands: CommandsConverter,1155private readonly _provider: vscode.CompletionItemProvider,1156private readonly _apiDeprecation: IExtHostApiDeprecationService,1157private readonly _extension: IExtensionDescription,1158) { }11591160async provideCompletionItems(resource: URI, position: IPosition, context: languages.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {11611162const doc = this._documents.getDocument(resource);1163const pos = typeConvert.Position.to(position);11641165// The default insert/replace ranges. It's important to compute them1166// before asynchronously asking the provider for its results. See1167// https://github.com/microsoft/vscode/issues/83400#issuecomment-5468514211168const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);1169const insertRange = replaceRange.with({ end: pos });11701171const sw = new StopWatch();1172const itemsOrList = await this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context));11731174if (!itemsOrList) {1175// undefined and null are valid results1176return undefined;1177}11781179if (token.isCancellationRequested) {1180// cancelled -> return without further ado, esp no caching1181// of results as they will leak1182return undefined;1183}11841185const list = Array.isArray(itemsOrList) ? new CompletionList(itemsOrList) : itemsOrList;11861187// keep result for providers that support resolving1188const pid: number = CompletionsAdapter.supportsResolving(this._provider) ? this._cache.add(list.items) : this._cache.add([]);1189const disposables = new DisposableStore();1190this._disposables.set(pid, disposables);11911192const completions: extHostProtocol.ISuggestDataDto[] = [];1193const result: extHostProtocol.ISuggestResultDto = {1194x: pid,1195[extHostProtocol.ISuggestResultDtoField.completions]: completions,1196[extHostProtocol.ISuggestResultDtoField.defaultRanges]: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },1197[extHostProtocol.ISuggestResultDtoField.isIncomplete]: list.isIncomplete || undefined,1198[extHostProtocol.ISuggestResultDtoField.duration]: sw.elapsed()1199};12001201for (let i = 0; i < list.items.length; i++) {1202const item = list.items[i];1203// check for bad completion item first1204const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);1205completions.push(dto);1206}12071208return result;1209}12101211async resolveCompletionItem(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {12121213if (typeof this._provider.resolveCompletionItem !== 'function') {1214return undefined;1215}12161217const item = this._cache.get(...id);1218if (!item) {1219return undefined;1220}12211222const dto1 = this._convertCompletionItem(item, id);12231224const resolvedItem = await this._provider.resolveCompletionItem(item, token);12251226if (!resolvedItem) {1227return undefined;1228}12291230const dto2 = this._convertCompletionItem(resolvedItem, id);12311232if (dto1[extHostProtocol.ISuggestDataDtoField.insertText] !== dto2[extHostProtocol.ISuggestDataDtoField.insertText]1233|| dto1[extHostProtocol.ISuggestDataDtoField.insertTextRules] !== dto2[extHostProtocol.ISuggestDataDtoField.insertTextRules]1234) {1235this._apiDeprecation.report('CompletionItem.insertText', this._extension, 'extension MAY NOT change \'insertText\' of a CompletionItem during resolve');1236}12371238if (dto1[extHostProtocol.ISuggestDataDtoField.commandIdent] !== dto2[extHostProtocol.ISuggestDataDtoField.commandIdent]1239|| dto1[extHostProtocol.ISuggestDataDtoField.commandId] !== dto2[extHostProtocol.ISuggestDataDtoField.commandId]1240|| !equals(dto1[extHostProtocol.ISuggestDataDtoField.commandArguments], dto2[extHostProtocol.ISuggestDataDtoField.commandArguments])1241) {1242this._apiDeprecation.report('CompletionItem.command', this._extension, 'extension MAY NOT change \'command\' of a CompletionItem during resolve');1243}12441245return {1246...dto1,1247[extHostProtocol.ISuggestDataDtoField.documentation]: dto2[extHostProtocol.ISuggestDataDtoField.documentation],1248[extHostProtocol.ISuggestDataDtoField.detail]: dto2[extHostProtocol.ISuggestDataDtoField.detail],1249[extHostProtocol.ISuggestDataDtoField.additionalTextEdits]: dto2[extHostProtocol.ISuggestDataDtoField.additionalTextEdits],12501251// (fishy) async insertText1252[extHostProtocol.ISuggestDataDtoField.insertText]: dto2[extHostProtocol.ISuggestDataDtoField.insertText],1253[extHostProtocol.ISuggestDataDtoField.insertTextRules]: dto2[extHostProtocol.ISuggestDataDtoField.insertTextRules],12541255// (fishy) async command1256[extHostProtocol.ISuggestDataDtoField.commandIdent]: dto2[extHostProtocol.ISuggestDataDtoField.commandIdent],1257[extHostProtocol.ISuggestDataDtoField.commandId]: dto2[extHostProtocol.ISuggestDataDtoField.commandId],1258[extHostProtocol.ISuggestDataDtoField.commandArguments]: dto2[extHostProtocol.ISuggestDataDtoField.commandArguments],1259};1260}12611262releaseCompletionItems(id: number): any {1263this._disposables.get(id)?.dispose();1264this._disposables.delete(id);1265this._cache.delete(id);1266}12671268private _convertCompletionItem(item: vscode.CompletionItem, id: extHostProtocol.ChainedCacheId, defaultInsertRange?: vscode.Range, defaultReplaceRange?: vscode.Range): extHostProtocol.ISuggestDataDto {12691270const disposables = this._disposables.get(id[0]);1271if (!disposables) {1272throw Error('DisposableStore is missing...');1273}12741275const command = this._commands.toInternal(item.command, disposables);1276const result: extHostProtocol.ISuggestDataDto = {1277//1278x: id,1279//1280[extHostProtocol.ISuggestDataDtoField.label]: item.label,1281[extHostProtocol.ISuggestDataDtoField.kind]: item.kind !== undefined ? typeConvert.CompletionItemKind.from(item.kind) : undefined,1282[extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),1283[extHostProtocol.ISuggestDataDtoField.detail]: item.detail,1284[extHostProtocol.ISuggestDataDtoField.documentation]: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),1285[extHostProtocol.ISuggestDataDtoField.sortText]: item.sortText !== item.label ? item.sortText : undefined,1286[extHostProtocol.ISuggestDataDtoField.filterText]: item.filterText !== item.label ? item.filterText : undefined,1287[extHostProtocol.ISuggestDataDtoField.preselect]: item.preselect || undefined,1288[extHostProtocol.ISuggestDataDtoField.insertTextRules]: item.keepWhitespace ? languages.CompletionItemInsertTextRule.KeepWhitespace : languages.CompletionItemInsertTextRule.None,1289[extHostProtocol.ISuggestDataDtoField.commitCharacters]: item.commitCharacters?.join(''),1290[extHostProtocol.ISuggestDataDtoField.additionalTextEdits]: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),1291[extHostProtocol.ISuggestDataDtoField.commandIdent]: command?.$ident,1292[extHostProtocol.ISuggestDataDtoField.commandId]: command?.id,1293[extHostProtocol.ISuggestDataDtoField.commandArguments]: command?.$ident ? undefined : command?.arguments, // filled in on main side from $ident1294};12951296// 'insertText'-logic1297if (item.textEdit) {1298this._apiDeprecation.report('CompletionItem.textEdit', this._extension, `Use 'CompletionItem.insertText' and 'CompletionItem.range' instead.`);1299result[extHostProtocol.ISuggestDataDtoField.insertText] = item.textEdit.newText;13001301} else if (typeof item.insertText === 'string') {1302result[extHostProtocol.ISuggestDataDtoField.insertText] = item.insertText;13031304} else if (item.insertText instanceof SnippetString) {1305result[extHostProtocol.ISuggestDataDtoField.insertText] = item.insertText.value;1306result[extHostProtocol.ISuggestDataDtoField.insertTextRules]! |= languages.CompletionItemInsertTextRule.InsertAsSnippet;1307}13081309// 'overwrite[Before|After]'-logic1310let range: vscode.Range | { inserting: vscode.Range; replacing: vscode.Range } | undefined;1311if (item.textEdit) {1312range = item.textEdit.range;1313} else if (item.range) {1314range = item.range;1315}13161317if (Range.isRange(range)) {1318// "old" range1319result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);13201321} else if (range && (!defaultInsertRange?.isEqual(range.inserting) || !defaultReplaceRange?.isEqual(range.replacing))) {1322// ONLY send range when it's different from the default ranges (safe bandwidth)1323result[extHostProtocol.ISuggestDataDtoField.range] = {1324insert: typeConvert.Range.from(range.inserting),1325replace: typeConvert.Range.from(range.replacing)1326};1327}13281329return result;1330}1331}13321333class InlineCompletionAdapter {1334private readonly _references = new ReferenceMap<{1335dispose(): void;1336items: readonly vscode.InlineCompletionItem[];1337list: vscode.InlineCompletionList | undefined;1338}>();13391340private readonly _isAdditionsProposedApiEnabled: boolean;13411342constructor(1343private readonly _extension: IExtensionDescription,1344private readonly _documents: ExtHostDocuments,1345private readonly _provider: vscode.InlineCompletionItemProvider,1346private readonly _commands: CommandsConverter,1347) {1348this._isAdditionsProposedApiEnabled = isProposedApiEnabled(this._extension, 'inlineCompletionsAdditions');1349}13501351public get supportsHandleEvents(): boolean {1352return isProposedApiEnabled(this._extension, 'inlineCompletionsAdditions')1353&& (typeof this._provider.handleDidShowCompletionItem === 'function'1354|| typeof this._provider.handleDidPartiallyAcceptCompletionItem === 'function'1355|| typeof this._provider.handleDidRejectCompletionItem === 'function'1356|| typeof this._provider.handleEndOfLifetime === 'function'1357);1358}13591360private readonly languageTriggerKindToVSCodeTriggerKind: Record<languages.InlineCompletionTriggerKind, InlineCompletionTriggerKind> = {1361[languages.InlineCompletionTriggerKind.Automatic]: InlineCompletionTriggerKind.Automatic,1362[languages.InlineCompletionTriggerKind.Explicit]: InlineCompletionTriggerKind.Invoke,1363};13641365async provideInlineCompletions(resource: URI, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {1366const doc = this._documents.getDocument(resource);1367const pos = typeConvert.Position.to(position);13681369const result = await this._provider.provideInlineCompletionItems(doc, pos, {1370selectedCompletionInfo:1371context.selectedSuggestionInfo1372? {1373range: typeConvert.Range.to(context.selectedSuggestionInfo.range),1374text: context.selectedSuggestionInfo.text1375}1376: undefined,1377triggerKind: this.languageTriggerKindToVSCodeTriggerKind[context.triggerKind],1378requestUuid: context.requestUuid,1379requestIssuedDateTime: context.requestIssuedDateTime,1380earliestShownDateTime: context.earliestShownDateTime,1381}, token);13821383if (!result) {1384// undefined and null are valid results1385return undefined;1386}13871388const { resultItems, list } = Array.isArray(result) ? { resultItems: result, list: undefined } : { resultItems: result.items, list: result };1389const commands = this._isAdditionsProposedApiEnabled ? Array.isArray(result) ? [] : result.commands || [] : [];1390const enableForwardStability = this._isAdditionsProposedApiEnabled && !Array.isArray(result) ? result.enableForwardStability : undefined;13911392let disposableStore: DisposableStore | undefined = undefined;1393const pid = this._references.createReferenceId({1394dispose() {1395disposableStore?.dispose();1396},1397items: resultItems,1398list,1399});14001401return {1402pid,1403languageId: doc.languageId,1404items: resultItems.map<extHostProtocol.IdentifiableInlineCompletion>((item, idx) => {1405let command: languages.Command | undefined = undefined;1406if (item.command) {1407if (!disposableStore) {1408disposableStore = new DisposableStore();1409}1410command = this._commands.toInternal(item.command, disposableStore);1411}14121413let action: languages.Command | undefined = undefined;1414if (item.action) {1415if (!disposableStore) {1416disposableStore = new DisposableStore();1417}1418action = this._commands.toInternal(item.action, disposableStore);1419}14201421const insertText = item.insertText;1422return ({1423insertText: typeof insertText === 'string' ? insertText : { snippet: insertText.value },1424filterText: item.filterText,1425range: item.range ? typeConvert.Range.from(item.range) : undefined,1426showRange: (this._isAdditionsProposedApiEnabled && item.showRange) ? typeConvert.Range.from(item.showRange) : undefined,1427command,1428action,1429idx: idx,1430completeBracketPairs: this._isAdditionsProposedApiEnabled ? item.completeBracketPairs : false,1431isInlineEdit: this._isAdditionsProposedApiEnabled ? item.isInlineEdit : false,1432showInlineEditMenu: this._isAdditionsProposedApiEnabled ? item.showInlineEditMenu : false,1433displayLocation: (item.displayLocation && this._isAdditionsProposedApiEnabled) ? {1434range: typeConvert.Range.from(item.displayLocation.range),1435label: item.displayLocation.label,1436kind: item.displayLocation.kind ? typeConvert.InlineCompletionDisplayLocationKind.from(item.displayLocation.kind) : InlineCompletionDisplayLocationKind.Code,1437} : undefined,1438warning: (item.warning && this._isAdditionsProposedApiEnabled) ? {1439message: typeConvert.MarkdownString.from(item.warning.message),1440icon: item.warning.icon ? typeConvert.IconPath.fromThemeIcon(item.warning.icon) : undefined,1441} : undefined,1442correlationId: this._isAdditionsProposedApiEnabled ? item.correlationId : undefined,1443suggestionId: undefined,1444});1445}),1446commands: commands.map(c => {1447if (!disposableStore) {1448disposableStore = new DisposableStore();1449}1450return typeConvert.CompletionCommand.from(c, this._commands, disposableStore);1451}),1452suppressSuggestions: false,1453enableForwardStability,1454};1455}14561457disposeCompletions(pid: number, reason: languages.InlineCompletionsDisposeReason) {1458const completionList = this._references.get(pid);1459if (this._provider.handleListEndOfLifetime && this._isAdditionsProposedApiEnabled && completionList?.list) {1460function translateReason(reason: languages.InlineCompletionsDisposeReason): vscode.InlineCompletionsDisposeReason {1461switch (reason.kind) {1462case 'lostRace':1463return { kind: InlineCompletionsDisposeReasonKind.LostRace };1464case 'tokenCancellation':1465return { kind: InlineCompletionsDisposeReasonKind.TokenCancellation };1466case 'other':1467return { kind: InlineCompletionsDisposeReasonKind.Other };1468case 'empty':1469return { kind: InlineCompletionsDisposeReasonKind.Empty };1470case 'notTaken':1471return { kind: InlineCompletionsDisposeReasonKind.NotTaken };1472default:1473return { kind: InlineCompletionsDisposeReasonKind.Other };1474}1475}14761477this._provider.handleListEndOfLifetime(completionList.list, translateReason(reason));1478}14791480const data = this._references.disposeReferenceId(pid);1481data?.dispose();1482}14831484handleDidShowCompletionItem(pid: number, idx: number, updatedInsertText: string): void {1485const completionItem = this._references.get(pid)?.items[idx];1486if (completionItem) {1487if (this._provider.handleDidShowCompletionItem && this._isAdditionsProposedApiEnabled) {1488this._provider.handleDidShowCompletionItem(completionItem, updatedInsertText);1489}1490}1491}14921493handlePartialAccept(pid: number, idx: number, acceptedCharacters: number, info: languages.PartialAcceptInfo): void {1494const completionItem = this._references.get(pid)?.items[idx];1495if (completionItem) {1496if (this._provider.handleDidPartiallyAcceptCompletionItem && this._isAdditionsProposedApiEnabled) {1497this._provider.handleDidPartiallyAcceptCompletionItem(completionItem, acceptedCharacters);1498this._provider.handleDidPartiallyAcceptCompletionItem(completionItem, typeConvert.PartialAcceptInfo.to(info));1499}1500}1501}15021503handleEndOfLifetime(pid: number, idx: number, reason: languages.InlineCompletionEndOfLifeReason<{ pid: number; idx: number }>): void {1504const completionItem = this._references.get(pid)?.items[idx];1505if (completionItem) {1506if (this._provider.handleEndOfLifetime && this._isAdditionsProposedApiEnabled) {1507const r = typeConvert.InlineCompletionEndOfLifeReason.to(reason, ref => this._references.get(ref.pid)?.items[ref.idx]);1508this._provider.handleEndOfLifetime(completionItem, r);1509}1510}1511}15121513handleRejection(pid: number, idx: number): void {1514const completionItem = this._references.get(pid)?.items[idx];1515if (completionItem) {1516if (this._provider.handleDidRejectCompletionItem && this._isAdditionsProposedApiEnabled) {1517this._provider.handleDidRejectCompletionItem(completionItem);1518}1519}1520}1521}15221523class ReferenceMap<T> {1524private readonly _references = new Map<number, T>();1525private _idPool = 1;15261527createReferenceId(value: T): number {1528const id = this._idPool++;1529this._references.set(id, value);1530return id;1531}15321533disposeReferenceId(referenceId: number): T | undefined {1534const value = this._references.get(referenceId);1535this._references.delete(referenceId);1536return value;1537}15381539get(referenceId: number): T | undefined {1540return this._references.get(referenceId);1541}1542}15431544class SignatureHelpAdapter {15451546private readonly _cache = new Cache<vscode.SignatureHelp>('SignatureHelp');15471548constructor(1549private readonly _documents: ExtHostDocuments,1550private readonly _provider: vscode.SignatureHelpProvider,1551) { }15521553async provideSignatureHelp(resource: URI, position: IPosition, context: extHostProtocol.ISignatureHelpContextDto, token: CancellationToken): Promise<extHostProtocol.ISignatureHelpDto | undefined> {1554const doc = this._documents.getDocument(resource);1555const pos = typeConvert.Position.to(position);1556const vscodeContext = this.reviveContext(context);15571558const value = await this._provider.provideSignatureHelp(doc, pos, token, vscodeContext);1559if (value) {1560const id = this._cache.add([value]);1561return { ...typeConvert.SignatureHelp.from(value), id };1562}1563return undefined;1564}15651566private reviveContext(context: extHostProtocol.ISignatureHelpContextDto): vscode.SignatureHelpContext {1567let activeSignatureHelp: vscode.SignatureHelp | undefined = undefined;1568if (context.activeSignatureHelp) {1569const revivedSignatureHelp = typeConvert.SignatureHelp.to(context.activeSignatureHelp);1570const saved = this._cache.get(context.activeSignatureHelp.id, 0);1571if (saved) {1572activeSignatureHelp = saved;1573activeSignatureHelp.activeSignature = revivedSignatureHelp.activeSignature;1574activeSignatureHelp.activeParameter = revivedSignatureHelp.activeParameter;1575} else {1576activeSignatureHelp = revivedSignatureHelp;1577}1578}1579return { ...context, activeSignatureHelp };1580}15811582releaseSignatureHelp(id: number): any {1583this._cache.delete(id);1584}1585}15861587class InlayHintsAdapter {15881589private _cache = new Cache<vscode.InlayHint>('InlayHints');1590private readonly _disposables = new Map<number, DisposableStore>();15911592constructor(1593private readonly _documents: ExtHostDocuments,1594private readonly _commands: CommandsConverter,1595private readonly _provider: vscode.InlayHintsProvider,1596private readonly _logService: ILogService,1597private readonly _extension: IExtensionDescription1598) { }15991600async provideInlayHints(resource: URI, ran: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {1601const doc = this._documents.getDocument(resource);1602const range = typeConvert.Range.to(ran);16031604const hints = await this._provider.provideInlayHints(doc, range, token);1605if (!Array.isArray(hints) || hints.length === 0) {1606// bad result1607this._logService.trace(`[InlayHints] NO inlay hints from '${this._extension.identifier.value}' for range ${JSON.stringify(ran)}`);1608return undefined;1609}1610if (token.isCancellationRequested) {1611// cancelled -> return without further ado, esp no caching1612// of results as they will leak1613return undefined;1614}1615const pid = this._cache.add(hints);1616this._disposables.set(pid, new DisposableStore());1617const result: extHostProtocol.IInlayHintsDto = { hints: [], cacheId: pid };1618for (let i = 0; i < hints.length; i++) {1619if (this._isValidInlayHint(hints[i], range)) {1620result.hints.push(this._convertInlayHint(hints[i], [pid, i]));1621}1622}1623this._logService.trace(`[InlayHints] ${result.hints.length} inlay hints from '${this._extension.identifier.value}' for range ${JSON.stringify(ran)}`);1624return result;1625}16261627async resolveInlayHint(id: extHostProtocol.ChainedCacheId, token: CancellationToken) {1628if (typeof this._provider.resolveInlayHint !== 'function') {1629return undefined;1630}1631const item = this._cache.get(...id);1632if (!item) {1633return undefined;1634}1635const hint = await this._provider.resolveInlayHint(item, token);1636if (!hint) {1637return undefined;1638}1639if (!this._isValidInlayHint(hint)) {1640return undefined;1641}1642return this._convertInlayHint(hint, id);1643}16441645releaseHints(id: number): any {1646this._disposables.get(id)?.dispose();1647this._disposables.delete(id);1648this._cache.delete(id);1649}16501651private _isValidInlayHint(hint: vscode.InlayHint, range?: vscode.Range): boolean {1652if (hint.label.length === 0 || Array.isArray(hint.label) && hint.label.every(part => part.value.length === 0)) {1653console.log('INVALID inlay hint, empty label', hint);1654return false;1655}1656if (range && !range.contains(hint.position)) {1657// console.log('INVALID inlay hint, position outside range', range, hint);1658return false;1659}1660return true;1661}16621663private _convertInlayHint(hint: vscode.InlayHint, id: extHostProtocol.ChainedCacheId): extHostProtocol.IInlayHintDto {16641665const disposables = this._disposables.get(id[0]);1666if (!disposables) {1667throw Error('DisposableStore is missing...');1668}16691670const result: extHostProtocol.IInlayHintDto = {1671label: '', // fill-in below1672cacheId: id,1673tooltip: typeConvert.MarkdownString.fromStrict(hint.tooltip),1674position: typeConvert.Position.from(hint.position),1675textEdits: hint.textEdits && hint.textEdits.map(typeConvert.TextEdit.from),1676kind: hint.kind && typeConvert.InlayHintKind.from(hint.kind),1677paddingLeft: hint.paddingLeft,1678paddingRight: hint.paddingRight,1679};16801681if (typeof hint.label === 'string') {1682result.label = hint.label;1683} else {1684const parts: languages.InlayHintLabelPart[] = [];1685result.label = parts;16861687for (const part of hint.label) {1688if (!part.value) {1689console.warn('INVALID inlay hint, empty label part', this._extension.identifier.value);1690continue;1691}1692const part2: languages.InlayHintLabelPart = {1693label: part.value,1694tooltip: typeConvert.MarkdownString.fromStrict(part.tooltip)1695};1696if (Location.isLocation(part.location)) {1697part2.location = typeConvert.location.from(part.location);1698}1699if (part.command) {1700part2.command = this._commands.toInternal(part.command, disposables);1701}1702parts.push(part2);1703}1704}1705return result;1706}1707}17081709class LinkProviderAdapter {17101711private _cache = new Cache<vscode.DocumentLink>('DocumentLink');17121713constructor(1714private readonly _documents: ExtHostDocuments,1715private readonly _provider: vscode.DocumentLinkProvider1716) { }17171718async provideLinks(resource: URI, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {1719const doc = this._documents.getDocument(resource);17201721const links = await this._provider.provideDocumentLinks(doc, token);1722if (!Array.isArray(links) || links.length === 0) {1723// bad result1724return undefined;1725}1726if (token.isCancellationRequested) {1727// cancelled -> return without further ado, esp no caching1728// of results as they will leak1729return undefined;1730}1731if (typeof this._provider.resolveDocumentLink !== 'function') {1732// no resolve -> no caching1733return { links: links.filter(LinkProviderAdapter._validateLink).map(typeConvert.DocumentLink.from) };17341735} else {1736// cache links for future resolving1737const pid = this._cache.add(links);1738const result: extHostProtocol.ILinksListDto = { links: [], cacheId: pid };1739for (let i = 0; i < links.length; i++) {17401741if (!LinkProviderAdapter._validateLink(links[i])) {1742continue;1743}17441745const dto: extHostProtocol.ILinkDto = typeConvert.DocumentLink.from(links[i]);1746dto.cacheId = [pid, i];1747result.links.push(dto);1748}1749return result;1750}1751}17521753private static _validateLink(link: vscode.DocumentLink): boolean {1754if (link.target && link.target.path.length > 50_000) {1755console.warn('DROPPING link because it is too long');1756return false;1757}1758return true;1759}17601761async resolveLink(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {1762if (typeof this._provider.resolveDocumentLink !== 'function') {1763return undefined;1764}1765const item = this._cache.get(...id);1766if (!item) {1767return undefined;1768}1769const link = await this._provider.resolveDocumentLink(item, token);1770if (!link || !LinkProviderAdapter._validateLink(link)) {1771return undefined;1772}1773return typeConvert.DocumentLink.from(link);1774}17751776releaseLinks(id: number): any {1777this._cache.delete(id);1778}1779}17801781class ColorProviderAdapter {17821783constructor(1784private _documents: ExtHostDocuments,1785private _provider: vscode.DocumentColorProvider1786) { }17871788async provideColors(resource: URI, token: CancellationToken): Promise<extHostProtocol.IRawColorInfo[]> {1789const doc = this._documents.getDocument(resource);1790const colors = await this._provider.provideDocumentColors(doc, token);1791if (!Array.isArray(colors)) {1792return [];1793}1794const colorInfos: extHostProtocol.IRawColorInfo[] = colors.map(ci => {1795return {1796color: typeConvert.Color.from(ci.color),1797range: typeConvert.Range.from(ci.range)1798};1799});1800return colorInfos;1801}18021803async provideColorPresentations(resource: URI, raw: extHostProtocol.IRawColorInfo, token: CancellationToken): Promise<languages.IColorPresentation[] | undefined> {1804const document = this._documents.getDocument(resource);1805const range = typeConvert.Range.to(raw.range);1806const color = typeConvert.Color.to(raw.color);1807const value = await this._provider.provideColorPresentations(color, { document, range }, token);1808if (!Array.isArray(value)) {1809return undefined;1810}1811return value.map(typeConvert.ColorPresentation.from);1812}1813}18141815class FoldingProviderAdapter {18161817constructor(1818private _documents: ExtHostDocuments,1819private _provider: vscode.FoldingRangeProvider1820) { }18211822async provideFoldingRanges(resource: URI, context: languages.FoldingContext, token: CancellationToken): Promise<languages.FoldingRange[] | undefined> {1823const doc = this._documents.getDocument(resource);1824const ranges = await this._provider.provideFoldingRanges(doc, context, token);1825if (!Array.isArray(ranges)) {1826return undefined;1827}1828return ranges.map(typeConvert.FoldingRange.from);1829}1830}18311832class SelectionRangeAdapter {18331834constructor(1835private readonly _documents: ExtHostDocuments,1836private readonly _provider: vscode.SelectionRangeProvider,1837private readonly _logService: ILogService1838) { }18391840async provideSelectionRanges(resource: URI, pos: IPosition[], token: CancellationToken): Promise<languages.SelectionRange[][]> {1841const document = this._documents.getDocument(resource);1842const positions = pos.map(typeConvert.Position.to);18431844const allProviderRanges = await this._provider.provideSelectionRanges(document, positions, token);1845if (!isNonEmptyArray(allProviderRanges)) {1846return [];1847}1848if (allProviderRanges.length !== positions.length) {1849this._logService.warn('BAD selection ranges, provider must return ranges for each position');1850return [];1851}1852const allResults: languages.SelectionRange[][] = [];1853for (let i = 0; i < positions.length; i++) {1854const oneResult: languages.SelectionRange[] = [];1855allResults.push(oneResult);18561857let last: vscode.Position | vscode.Range = positions[i];1858let selectionRange = allProviderRanges[i];18591860while (true) {1861if (!selectionRange.range.contains(last)) {1862throw new Error('INVALID selection range, must contain the previous range');1863}1864oneResult.push(typeConvert.SelectionRange.from(selectionRange));1865if (!selectionRange.parent) {1866break;1867}1868last = selectionRange.range;1869selectionRange = selectionRange.parent;1870}1871}1872return allResults;1873}1874}18751876class CallHierarchyAdapter {18771878private readonly _idPool = new IdGenerator('');1879private readonly _cache = new Map<string, Map<string, vscode.CallHierarchyItem>>();18801881constructor(1882private readonly _documents: ExtHostDocuments,1883private readonly _provider: vscode.CallHierarchyProvider1884) { }18851886async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {1887const doc = this._documents.getDocument(uri);1888const pos = typeConvert.Position.to(position);18891890const items = await this._provider.prepareCallHierarchy(doc, pos, token);1891if (!items) {1892return undefined;1893}18941895const sessionId = this._idPool.nextId();1896this._cache.set(sessionId, new Map());18971898if (Array.isArray(items)) {1899return items.map(item => this._cacheAndConvertItem(sessionId, item));1900} else {1901return [this._cacheAndConvertItem(sessionId, items)];1902}1903}19041905async provideCallsTo(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {1906const item = this._itemFromCache(sessionId, itemId);1907if (!item) {1908throw new Error('missing call hierarchy item');1909}1910const calls = await this._provider.provideCallHierarchyIncomingCalls(item, token);1911if (!calls) {1912return undefined;1913}1914return calls.map(call => {1915return {1916from: this._cacheAndConvertItem(sessionId, call.from),1917fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))1918};1919});1920}19211922async provideCallsFrom(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {1923const item = this._itemFromCache(sessionId, itemId);1924if (!item) {1925throw new Error('missing call hierarchy item');1926}1927const calls = await this._provider.provideCallHierarchyOutgoingCalls(item, token);1928if (!calls) {1929return undefined;1930}1931return calls.map(call => {1932return {1933to: this._cacheAndConvertItem(sessionId, call.to),1934fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))1935};1936});1937}19381939releaseSession(sessionId: string): void {1940this._cache.delete(sessionId);1941}19421943private _cacheAndConvertItem(sessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {1944const map = this._cache.get(sessionId)!;1945const dto = typeConvert.CallHierarchyItem.from(item, sessionId, map.size.toString(36));1946map.set(dto._itemId, item);1947return dto;1948}19491950private _itemFromCache(sessionId: string, itemId: string): vscode.CallHierarchyItem | undefined {1951const map = this._cache.get(sessionId);1952return map?.get(itemId);1953}1954}19551956class TypeHierarchyAdapter {19571958private readonly _idPool = new IdGenerator('');1959private readonly _cache = new Map<string, Map<string, vscode.TypeHierarchyItem>>();19601961constructor(1962private readonly _documents: ExtHostDocuments,1963private readonly _provider: vscode.TypeHierarchyProvider1964) { }19651966async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {1967const doc = this._documents.getDocument(uri);1968const pos = typeConvert.Position.to(position);19691970const items = await this._provider.prepareTypeHierarchy(doc, pos, token);1971if (!items) {1972return undefined;1973}19741975const sessionId = this._idPool.nextId();1976this._cache.set(sessionId, new Map());19771978if (Array.isArray(items)) {1979return items.map(item => this._cacheAndConvertItem(sessionId, item));1980} else {1981return [this._cacheAndConvertItem(sessionId, items)];1982}1983}19841985async provideSupertypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {1986const item = this._itemFromCache(sessionId, itemId);1987if (!item) {1988throw new Error('missing type hierarchy item');1989}1990const supertypes = await this._provider.provideTypeHierarchySupertypes(item, token);1991if (!supertypes) {1992return undefined;1993}1994return supertypes.map(supertype => {1995return this._cacheAndConvertItem(sessionId, supertype);1996});1997}19981999async provideSubtypes(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2000const item = this._itemFromCache(sessionId, itemId);2001if (!item) {2002throw new Error('missing type hierarchy item');2003}2004const subtypes = await this._provider.provideTypeHierarchySubtypes(item, token);2005if (!subtypes) {2006return undefined;2007}2008return subtypes.map(subtype => {2009return this._cacheAndConvertItem(sessionId, subtype);2010});2011}20122013releaseSession(sessionId: string): void {2014this._cache.delete(sessionId);2015}20162017private _cacheAndConvertItem(sessionId: string, item: vscode.TypeHierarchyItem): extHostProtocol.ITypeHierarchyItemDto {2018const map = this._cache.get(sessionId)!;2019const dto = typeConvert.TypeHierarchyItem.from(item, sessionId, map.size.toString(36));2020map.set(dto._itemId, item);2021return dto;2022}20232024private _itemFromCache(sessionId: string, itemId: string): vscode.TypeHierarchyItem | undefined {2025const map = this._cache.get(sessionId);2026return map?.get(itemId);2027}2028}20292030class DocumentDropEditAdapter {20312032private readonly _cache = new Cache<vscode.DocumentDropEdit>('DocumentDropEdit');20332034constructor(2035private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,2036private readonly _documents: ExtHostDocuments,2037private readonly _provider: vscode.DocumentDropEditProvider,2038private readonly _handle: number,2039private readonly _extension: IExtensionDescription,2040) { }20412042async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentDropEditDto[] | undefined> {2043const doc = this._documents.getDocument(uri);2044const pos = typeConvert.Position.to(position);2045const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (id) => {2046return (await this._proxy.$resolveDocumentOnDropFileData(this._handle, requestId, id)).buffer;2047});20482049const edits = await this._provider.provideDocumentDropEdits(doc, pos, dataTransfer, token);2050if (!edits) {2051return undefined;2052}20532054const editsArray = asArray(edits);2055const cacheId = this._cache.add(editsArray);20562057return editsArray.map((edit, i): extHostProtocol.IDocumentDropEditDto => ({2058_cacheId: [cacheId, i],2059title: edit.title ?? localize('defaultDropLabel', "Drop using '{0}' extension", this._extension.displayName || this._extension.name),2060kind: edit.kind?.value,2061yieldTo: edit.yieldTo?.map(x => x.value),2062insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },2063additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit, undefined) : undefined,2064}));2065}20662067async resolveDropEdit(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2068const [sessionId, itemId] = id;2069const item = this._cache.get(sessionId, itemId);2070if (!item || !this._provider.resolveDocumentDropEdit) {2071return {}; // this should not happen...2072}20732074const resolvedItem = (await this._provider.resolveDocumentDropEdit(item, token)) ?? item;2075const additionalEdit = resolvedItem.additionalEdit ? typeConvert.WorkspaceEdit.from(resolvedItem.additionalEdit, undefined) : undefined;2076return { additionalEdit };2077}20782079releaseDropEdits(id: number): any {2080this._cache.delete(id);2081}2082}20832084type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter2085| DocumentHighlightAdapter | MultiDocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter2086| DocumentPasteEditProvider | DocumentFormattingAdapter | RangeFormattingAdapter2087| OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter2088| CompletionsAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter2089| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter2090| SelectionRangeAdapter | CallHierarchyAdapter | TypeHierarchyAdapter2091| DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter2092| EvaluatableExpressionAdapter | InlineValuesAdapter2093| LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter2094| DocumentDropEditAdapter | NewSymbolNamesAdapter;20952096class AdapterData {2097constructor(2098readonly adapter: Adapter,2099readonly extension: IExtensionDescription2100) { }2101}21022103export class ExtHostLanguageFeatures extends CoreDisposable implements extHostProtocol.ExtHostLanguageFeaturesShape {21042105private static _handlePool: number = 0;21062107private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;2108private readonly _adapter = new Map<number, AdapterData>();21092110private _inlineCompletionsUnificationState: vscode.InlineCompletionsUnificationState;2111public get inlineCompletionsUnificationState(): vscode.InlineCompletionsUnificationState {2112return this._inlineCompletionsUnificationState;2113}21142115private readonly _onDidChangeInlineCompletionsUnificationState = this._register(new Emitter<void>());2116readonly onDidChangeInlineCompletionsUnificationState = this._onDidChangeInlineCompletionsUnificationState.event;21172118constructor(2119mainContext: extHostProtocol.IMainContext,2120private readonly _uriTransformer: IURITransformer,2121private readonly _documents: ExtHostDocuments,2122private readonly _commands: ExtHostCommands,2123private readonly _diagnostics: ExtHostDiagnostics,2124private readonly _logService: ILogService,2125private readonly _apiDeprecation: IExtHostApiDeprecationService,2126private readonly _extensionTelemetry: IExtHostTelemetry2127) {2128super();2129this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures);2130this._inlineCompletionsUnificationState = {2131codeUnification: false,2132modelUnification: false,2133expAssignments: []2134};2135}21362137private _transformDocumentSelector(selector: vscode.DocumentSelector, extension: IExtensionDescription): Array<extHostProtocol.IDocumentFilterDto> {2138return typeConvert.DocumentSelector.from(selector, this._uriTransformer, extension);2139}21402141private _createDisposable(handle: number): Disposable {2142return new Disposable(() => {2143this._adapter.delete(handle);2144this._proxy.$unregister(handle);2145});2146}21472148private _nextHandle(): number {2149return ExtHostLanguageFeatures._handlePool++;2150}21512152private async _withAdapter<A, R>(2153handle: number,2154ctor: { new(...args: any[]): A },2155callback: (adapter: A, extension: IExtensionDescription) => Promise<R>,2156fallbackValue: R,2157tokenToRaceAgainst: CancellationToken | undefined,2158doNotLog: boolean = false2159): Promise<R> {2160const data = this._adapter.get(handle);2161if (!data || !(data.adapter instanceof ctor)) {2162return fallbackValue;2163}21642165const t1: number = Date.now();2166if (!doNotLog) {2167this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${callback.toString().replace(/[\r\n]/g, '')}'`);2168}21692170const result = callback(data.adapter, data.extension);21712172// logging,tracing2173Promise.resolve(result).catch(err => {2174if (!isCancellationError(err)) {2175this._logService.error(`[${data.extension.identifier.value}] provider FAILED`);2176this._logService.error(err);21772178this._extensionTelemetry.onExtensionError(data.extension.identifier, err);2179}2180}).finally(() => {2181if (!doNotLog) {2182this._logService.trace(`[${data.extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`);2183}2184});21852186if (CancellationToken.isCancellationToken(tokenToRaceAgainst)) {2187return raceCancellationError(result, tokenToRaceAgainst);2188}2189return result;2190}21912192private _addNewAdapter(adapter: Adapter, extension: IExtensionDescription): number {2193const handle = this._nextHandle();2194this._adapter.set(handle, new AdapterData(adapter, extension));2195return handle;2196}21972198private static _extLabel(ext: IExtensionDescription): string {2199return ext.displayName || ext.name;2200}22012202private static _extId(ext: IExtensionDescription): string {2203return ext.identifier.value;2204}22052206// --- outline22072208registerDocumentSymbolProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable {2209const handle = this._addNewAdapter(new DocumentSymbolAdapter(this._documents, provider), extension);2210const displayName = (metadata && metadata.label) || ExtHostLanguageFeatures._extLabel(extension);2211this._proxy.$registerDocumentSymbolProvider(handle, this._transformDocumentSelector(selector, extension), displayName);2212return this._createDisposable(handle);2213}22142215$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<languages.DocumentSymbol[] | undefined> {2216return this._withAdapter(handle, DocumentSymbolAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource), token), undefined, token);2217}22182219// --- code lens22202221registerCodeLensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {2222const handle = this._nextHandle();2223const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;22242225this._adapter.set(handle, new AdapterData(new CodeLensAdapter(this._documents, this._commands.converter, provider, extension, this._extensionTelemetry, this._logService), extension));2226this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector, extension), eventHandle);2227let result = this._createDisposable(handle);22282229if (eventHandle !== undefined) {2230const subscription = provider.onDidChangeCodeLenses!(_ => this._proxy.$emitCodeLensEvent(eventHandle));2231result = Disposable.from(result, subscription);2232}22332234return result;2235}22362237$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.ICodeLensListDto | undefined> {2238return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token), undefined, token, resource.scheme === 'output');2239}22402241$resolveCodeLens(handle: number, symbol: extHostProtocol.ICodeLensDto, token: CancellationToken): Promise<extHostProtocol.ICodeLensDto | undefined> {2242return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(symbol, token), undefined, undefined, true);2243}22442245$releaseCodeLenses(handle: number, cacheId: number): void {2246this._withAdapter(handle, CodeLensAdapter, adapter => Promise.resolve(adapter.releaseCodeLenses(cacheId)), undefined, undefined, true);2247}22482249// --- declaration22502251registerDefinitionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {2252const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider), extension);2253this._proxy.$registerDefinitionSupport(handle, this._transformDocumentSelector(selector, extension));2254return this._createDisposable(handle);2255}22562257$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2258return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position, token), [], token);2259}22602261registerDeclarationProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DeclarationProvider): vscode.Disposable {2262const handle = this._addNewAdapter(new DeclarationAdapter(this._documents, provider), extension);2263this._proxy.$registerDeclarationSupport(handle, this._transformDocumentSelector(selector, extension));2264return this._createDisposable(handle);2265}22662267$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2268return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.provideDeclaration(URI.revive(resource), position, token), [], token);2269}22702271registerImplementationProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {2272const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider), extension);2273this._proxy.$registerImplementationSupport(handle, this._transformDocumentSelector(selector, extension));2274return this._createDisposable(handle);2275}22762277$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2278return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position, token), [], token);2279}22802281registerTypeDefinitionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {2282const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider), extension);2283this._proxy.$registerTypeDefinitionSupport(handle, this._transformDocumentSelector(selector, extension));2284return this._createDisposable(handle);2285}22862287$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.LocationLink[]> {2288return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(URI.revive(resource), position, token), [], token);2289}22902291// --- extra info22922293registerHoverProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {2294const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider), extension);2295this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector, extension));2296return this._createDisposable(handle);2297}22982299$provideHover(handle: number, resource: UriComponents, position: IPosition, context: languages.HoverContext<{ id: number }> | undefined, token: CancellationToken,): Promise<extHostProtocol.HoverWithId | undefined> {2300return this._withAdapter(handle, HoverAdapter, adapter => adapter.provideHover(URI.revive(resource), position, context, token), undefined, token);2301}23022303$releaseHover(handle: number, id: number): void {2304this._withAdapter(handle, HoverAdapter, adapter => Promise.resolve(adapter.releaseHover(id)), undefined, undefined);2305}23062307// --- debug hover23082309registerEvaluatableExpressionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.EvaluatableExpressionProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {2310const handle = this._addNewAdapter(new EvaluatableExpressionAdapter(this._documents, provider), extension);2311this._proxy.$registerEvaluatableExpressionProvider(handle, this._transformDocumentSelector(selector, extension));2312return this._createDisposable(handle);2313}23142315$provideEvaluatableExpression(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.EvaluatableExpression | undefined> {2316return this._withAdapter(handle, EvaluatableExpressionAdapter, adapter => adapter.provideEvaluatableExpression(URI.revive(resource), position, token), undefined, token);2317}23182319// --- debug inline values23202321registerInlineValuesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineValuesProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {23222323const eventHandle = typeof provider.onDidChangeInlineValues === 'function' ? this._nextHandle() : undefined;2324const handle = this._addNewAdapter(new InlineValuesAdapter(this._documents, provider), extension);23252326this._proxy.$registerInlineValuesProvider(handle, this._transformDocumentSelector(selector, extension), eventHandle);2327let result = this._createDisposable(handle);23282329if (eventHandle !== undefined) {2330const subscription = provider.onDidChangeInlineValues!(_ => this._proxy.$emitInlineValuesEvent(eventHandle));2331result = Disposable.from(result, subscription);2332}2333return result;2334}23352336$provideInlineValues(handle: number, resource: UriComponents, range: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<languages.InlineValue[] | undefined> {2337return this._withAdapter(handle, InlineValuesAdapter, adapter => adapter.provideInlineValues(URI.revive(resource), range, context, token), undefined, token);2338}23392340// --- occurrences23412342registerDocumentHighlightProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {2343const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider), extension);2344this._proxy.$registerDocumentHighlightProvider(handle, this._transformDocumentSelector(selector, extension));2345return this._createDisposable(handle);2346}23472348registerMultiDocumentHighlightProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.MultiDocumentHighlightProvider): vscode.Disposable {2349const handle = this._addNewAdapter(new MultiDocumentHighlightAdapter(this._documents, provider, this._logService), extension);2350this._proxy.$registerMultiDocumentHighlightProvider(handle, this._transformDocumentSelector(selector, extension));2351return this._createDisposable(handle);2352}23532354$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.DocumentHighlight[] | undefined> {2355return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position, token), undefined, token);2356}23572358$provideMultiDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, otherModels: UriComponents[], token: CancellationToken): Promise<languages.MultiDocumentHighlight[] | undefined> {2359return this._withAdapter(handle, MultiDocumentHighlightAdapter, adapter => adapter.provideMultiDocumentHighlights(URI.revive(resource), position, otherModels.map(model => URI.revive(model)), token), undefined, token);2360}23612362// --- linked editing23632364registerLinkedEditingRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.LinkedEditingRangeProvider): vscode.Disposable {2365const handle = this._addNewAdapter(new LinkedEditingRangeAdapter(this._documents, provider), extension);2366this._proxy.$registerLinkedEditingRangeProvider(handle, this._transformDocumentSelector(selector, extension));2367return this._createDisposable(handle);2368}23692370$provideLinkedEditingRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ILinkedEditingRangesDto | undefined> {2371return this._withAdapter(handle, LinkedEditingRangeAdapter, async adapter => {2372const res = await adapter.provideLinkedEditingRanges(URI.revive(resource), position, token);2373if (res) {2374return {2375ranges: res.ranges,2376wordPattern: res.wordPattern ? ExtHostLanguageFeatures._serializeRegExp(res.wordPattern) : undefined2377};2378}2379return undefined;2380}, undefined, token);2381}23822383// --- references23842385registerReferenceProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {2386const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider), extension);2387this._proxy.$registerReferenceSupport(handle, this._transformDocumentSelector(selector, extension));2388return this._createDisposable(handle);2389}23902391$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: languages.ReferenceContext, token: CancellationToken): Promise<languages.Location[] | undefined> {2392return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context, token), undefined, token);2393}23942395// --- code actions23962397registerCodeActionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {2398const store = new DisposableStore();2399const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider, this._logService, extension, this._apiDeprecation), extension);2400this._proxy.$registerCodeActionSupport(handle, this._transformDocumentSelector(selector, extension), {2401providedKinds: metadata?.providedCodeActionKinds?.map(kind => kind.value),2402documentation: metadata?.documentation?.map(x => ({2403kind: x.kind.value,2404command: this._commands.converter.toInternal(x.command, store),2405}))2406}, ExtHostLanguageFeatures._extLabel(extension), ExtHostLanguageFeatures._extId(extension), Boolean(provider.resolveCodeAction));2407store.add(this._createDisposable(handle));2408return store;2409}241024112412$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<extHostProtocol.ICodeActionListDto | undefined> {2413return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token), undefined, token);2414}24152416$resolveCodeAction(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ edit?: extHostProtocol.IWorkspaceEditDto; command?: extHostProtocol.ICommandDto }> {2417return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.resolveCodeAction(id, token), {}, undefined);2418}24192420$releaseCodeActions(handle: number, cacheId: number): void {2421this._withAdapter(handle, CodeActionAdapter, adapter => Promise.resolve(adapter.releaseCodeActions(cacheId)), undefined, undefined);2422}24232424// --- formatting24252426registerDocumentFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {2427const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider), extension);2428this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector, extension), extension.identifier, extension.displayName || extension.name);2429return this._createDisposable(handle);2430}24312432$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2433return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options, token), undefined, token);2434}24352436registerDocumentRangeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {2437const canFormatMultipleRanges = typeof provider.provideDocumentRangesFormattingEdits === 'function';2438const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider), extension);2439this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector, extension), extension.identifier, extension.displayName || extension.name, canFormatMultipleRanges);2440return this._createDisposable(handle);2441}24422443$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2444return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options, token), undefined, token);2445}24462447$provideDocumentRangesFormattingEdits(handle: number, resource: UriComponents, ranges: IRange[], options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2448return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangesFormattingEdits(URI.revive(resource), ranges, options, token), undefined, token);2449}24502451registerOnTypeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {2452const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider), extension);2453this._proxy.$registerOnTypeFormattingSupport(handle, this._transformDocumentSelector(selector, extension), triggerCharacters, extension.identifier);2454return this._createDisposable(handle);2455}24562457$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<languages.TextEdit[] | undefined> {2458return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options, token), undefined, token);2459}24602461// --- navigate types24622463registerWorkspaceSymbolProvider(extension: IExtensionDescription, provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {2464const handle = this._addNewAdapter(new NavigateTypeAdapter(provider, this._logService), extension);2465this._proxy.$registerNavigateTypeSupport(handle, typeof provider.resolveWorkspaceSymbol === 'function');2466return this._createDisposable(handle);2467}24682469$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolsDto> {2470return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search, token), { symbols: [] }, token);2471}24722473$resolveWorkspaceSymbol(handle: number, symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {2474return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol, token), undefined, undefined);2475}24762477$releaseWorkspaceSymbols(handle: number, id: number): void {2478this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.releaseWorkspaceSymbols(id), undefined, undefined);2479}24802481// --- rename24822483registerRenameProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {2484const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider, this._logService), extension);2485this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector, extension), RenameAdapter.supportsResolving(provider));2486return this._createDisposable(handle);2487}24882489$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto | undefined> {2490return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName, token), undefined, token);2491}24922493$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Promise<languages.RenameLocation | undefined> {2494return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token), undefined, token);2495}24962497registerNewSymbolNamesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.NewSymbolNamesProvider): vscode.Disposable {2498const handle = this._addNewAdapter(new NewSymbolNamesAdapter(this._documents, provider, this._logService), extension);2499this._proxy.$registerNewSymbolNamesProvider(handle, this._transformDocumentSelector(selector, extension));2500return this._createDisposable(handle);2501}25022503$supportsAutomaticNewSymbolNamesTriggerKind(handle: number): Promise<boolean | undefined> {2504return this._withAdapter(2505handle,2506NewSymbolNamesAdapter,2507adapter => adapter.supportsAutomaticNewSymbolNamesTriggerKind(),2508false,2509undefined2510);2511}25122513$provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {2514return this._withAdapter(handle, NewSymbolNamesAdapter, adapter => adapter.provideNewSymbolNames(URI.revive(resource), range, triggerKind, token), undefined, token);2515}25162517//#region semantic coloring25182519registerDocumentSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {2520const handle = this._addNewAdapter(new DocumentSemanticTokensAdapter(this._documents, provider), extension);2521const eventHandle = (typeof provider.onDidChangeSemanticTokens === 'function' ? this._nextHandle() : undefined);2522this._proxy.$registerDocumentSemanticTokensProvider(handle, this._transformDocumentSelector(selector, extension), legend, eventHandle);2523let result = this._createDisposable(handle);25242525if (eventHandle) {2526const subscription = provider.onDidChangeSemanticTokens!(_ => this._proxy.$emitDocumentSemanticTokensEvent(eventHandle));2527result = Disposable.from(result, subscription);2528}25292530return result;2531}25322533$provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {2534return this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.provideDocumentSemanticTokens(URI.revive(resource), previousResultId, token), null, token);2535}25362537$releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void {2538this._withAdapter(handle, DocumentSemanticTokensAdapter, adapter => adapter.releaseDocumentSemanticColoring(semanticColoringResultId), undefined, undefined);2539}25402541registerDocumentRangeSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {2542const handle = this._addNewAdapter(new DocumentRangeSemanticTokensAdapter(this._documents, provider), extension);2543this._proxy.$registerDocumentRangeSemanticTokensProvider(handle, this._transformDocumentSelector(selector, extension), legend);2544return this._createDisposable(handle);2545}25462547$provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<VSBuffer | null> {2548return this._withAdapter(handle, DocumentRangeSemanticTokensAdapter, adapter => adapter.provideDocumentRangeSemanticTokens(URI.revive(resource), range, token), null, token);2549}25502551//#endregion25522553// --- suggestion25542555registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {2556const handle = this._addNewAdapter(new CompletionsAdapter(this._documents, this._commands.converter, provider, this._apiDeprecation, extension), extension);2557this._proxy.$registerCompletionsProvider(handle, this._transformDocumentSelector(selector, extension), triggerCharacters, CompletionsAdapter.supportsResolving(provider), extension.identifier);2558return this._createDisposable(handle);2559}25602561$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: languages.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {2562return this._withAdapter(handle, CompletionsAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined, token);2563}25642565$resolveCompletionItem(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {2566return this._withAdapter(handle, CompletionsAdapter, adapter => adapter.resolveCompletionItem(id, token), undefined, token);2567}25682569$releaseCompletionItems(handle: number, id: number): void {2570this._withAdapter(handle, CompletionsAdapter, adapter => adapter.releaseCompletionItems(id), undefined, undefined);2571}25722573// --- ghost text25742575registerInlineCompletionsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider, metadata: vscode.InlineCompletionItemProviderMetadata | undefined): vscode.Disposable {2576const eventHandle = typeof provider.onDidChange === 'function' && isProposedApiEnabled(extension, 'inlineCompletionsAdditions') ? this._nextHandle() : undefined;2577const adapter = new InlineCompletionAdapter(extension, this._documents, provider, this._commands.converter);2578const handle = this._addNewAdapter(adapter, extension);2579let result = this._createDisposable(handle);25802581if (eventHandle !== undefined) {2582const subscription = provider.onDidChange!(_ => this._proxy.$emitInlineCompletionsChange(eventHandle));2583result = Disposable.from(result, subscription);2584}25852586this._proxy.$registerInlineCompletionsSupport(2587handle,2588this._transformDocumentSelector(selector, extension),2589adapter.supportsHandleEvents,2590ExtensionIdentifier.toKey(extension.identifier.value),2591extension.version,2592metadata?.groupId ? ExtensionIdentifier.toKey(metadata.groupId) : undefined,2593metadata?.yieldTo?.map(extId => ExtensionIdentifier.toKey(extId)) || [],2594metadata?.displayName,2595metadata?.debounceDelayMs,2596metadata?.excludes?.map(extId => ExtensionIdentifier.toKey(extId)) || [],2597eventHandle,2598);2599return result;2600}26012602$provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<extHostProtocol.IdentifiableInlineCompletions | undefined> {2603return this._withAdapter(handle, InlineCompletionAdapter, adapter => adapter.provideInlineCompletions(URI.revive(resource), position, context, token), undefined, undefined);2604}26052606$handleInlineCompletionDidShow(handle: number, pid: number, idx: number, updatedInsertText: string): void {2607this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2608adapter.handleDidShowCompletionItem(pid, idx, updatedInsertText);2609}, undefined, undefined);2610}26112612$handleInlineCompletionPartialAccept(handle: number, pid: number, idx: number, acceptedCharacters: number, info: languages.PartialAcceptInfo): void {2613this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2614adapter.handlePartialAccept(pid, idx, acceptedCharacters, info);2615}, undefined, undefined);2616}26172618$handleInlineCompletionEndOfLifetime(handle: number, pid: number, idx: number, reason: languages.InlineCompletionEndOfLifeReason<{ pid: number; idx: number }>): void {2619this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2620adapter.handleEndOfLifetime(pid, idx, reason);2621}, undefined, undefined);2622}26232624$handleInlineCompletionRejection(handle: number, pid: number, idx: number): void {2625this._withAdapter(handle, InlineCompletionAdapter, async adapter => {2626adapter.handleRejection(pid, idx);2627}, undefined, undefined);2628}26292630$freeInlineCompletionsList(handle: number, pid: number, reason: languages.InlineCompletionsDisposeReason): void {2631this._withAdapter(handle, InlineCompletionAdapter, async adapter => { adapter.disposeCompletions(pid, reason); }, undefined, undefined);2632}26332634$acceptInlineCompletionsUnificationState(state: IInlineCompletionsUnificationState): void {2635this._inlineCompletionsUnificationState = state;2636this._onDidChangeInlineCompletionsUnificationState.fire();2637}26382639// --- parameter hints26402641registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {2642const metadata: extHostProtocol.ISignatureHelpProviderMetadataDto | undefined = Array.isArray(metadataOrTriggerChars)2643? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }2644: metadataOrTriggerChars;26452646const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider), extension);2647this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector, extension), metadata);2648return this._createDisposable(handle);2649}26502651$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: extHostProtocol.ISignatureHelpContextDto, token: CancellationToken): Promise<extHostProtocol.ISignatureHelpDto | undefined> {2652return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token), undefined, token);2653}26542655$releaseSignatureHelp(handle: number, id: number): void {2656this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.releaseSignatureHelp(id), undefined, undefined);2657}26582659// --- inline hints26602661registerInlayHintsProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlayHintsProvider): vscode.Disposable {26622663const eventHandle = typeof provider.onDidChangeInlayHints === 'function' ? this._nextHandle() : undefined;2664const handle = this._addNewAdapter(new InlayHintsAdapter(this._documents, this._commands.converter, provider, this._logService, extension), extension);26652666this._proxy.$registerInlayHintsProvider(handle, this._transformDocumentSelector(selector, extension), typeof provider.resolveInlayHint === 'function', eventHandle, ExtHostLanguageFeatures._extLabel(extension));2667let result = this._createDisposable(handle);26682669if (eventHandle !== undefined) {2670const subscription = provider.onDidChangeInlayHints!(uri => this._proxy.$emitInlayHintsEvent(eventHandle));2671result = Disposable.from(result, subscription);2672}2673return result;2674}26752676$provideInlayHints(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<extHostProtocol.IInlayHintsDto | undefined> {2677return this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.provideInlayHints(URI.revive(resource), range, token), undefined, token);2678}26792680$resolveInlayHint(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.IInlayHintDto | undefined> {2681return this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.resolveInlayHint(id, token), undefined, token);2682}26832684$releaseInlayHints(handle: number, id: number): void {2685this._withAdapter(handle, InlayHintsAdapter, adapter => adapter.releaseHints(id), undefined, undefined);2686}26872688// --- links26892690registerDocumentLinkProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {2691const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, provider), extension);2692this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector, extension), typeof provider.resolveDocumentLink === 'function');2693return this._createDisposable(handle);2694}26952696$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.ILinksListDto | undefined> {2697return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token), undefined, token, resource.scheme === 'output');2698}26992700$resolveDocumentLink(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ILinkDto | undefined> {2701return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(id, token), undefined, undefined, true);2702}27032704$releaseDocumentLinks(handle: number, id: number): void {2705this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.releaseLinks(id), undefined, undefined, true);2706}27072708registerColorProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {2709const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider), extension);2710this._proxy.$registerDocumentColorProvider(handle, this._transformDocumentSelector(selector, extension));2711return this._createDisposable(handle);2712}27132714$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<extHostProtocol.IRawColorInfo[]> {2715return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource), token), [], token);2716}27172718$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: extHostProtocol.IRawColorInfo, token: CancellationToken): Promise<languages.IColorPresentation[] | undefined> {2719return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo, token), undefined, token);2720}27212722registerFoldingRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable {2723const handle = this._nextHandle();2724const eventHandle = typeof provider.onDidChangeFoldingRanges === 'function' ? this._nextHandle() : undefined;27252726this._adapter.set(handle, new AdapterData(new FoldingProviderAdapter(this._documents, provider), extension));2727this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector, extension), extension.identifier, eventHandle);2728let result = this._createDisposable(handle);27292730if (eventHandle !== undefined) {2731const subscription = provider.onDidChangeFoldingRanges!(() => this._proxy.$emitFoldingRangeEvent(eventHandle));2732result = Disposable.from(result, subscription);2733}27342735return result;2736}27372738$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext, token: CancellationToken): Promise<languages.FoldingRange[] | undefined> {2739return this._withAdapter(2740handle,2741FoldingProviderAdapter,2742(adapter) =>2743adapter.provideFoldingRanges(URI.revive(resource), context, token),2744undefined,2745token2746);2747}27482749// --- smart select27502751registerSelectionRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SelectionRangeProvider): vscode.Disposable {2752const handle = this._addNewAdapter(new SelectionRangeAdapter(this._documents, provider, this._logService), extension);2753this._proxy.$registerSelectionRangeProvider(handle, this._transformDocumentSelector(selector, extension));2754return this._createDisposable(handle);2755}27562757$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<languages.SelectionRange[][]> {2758return this._withAdapter(handle, SelectionRangeAdapter, adapter => adapter.provideSelectionRanges(URI.revive(resource), positions, token), [], token);2759}27602761// --- call hierarchy27622763registerCallHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CallHierarchyProvider): vscode.Disposable {2764const handle = this._addNewAdapter(new CallHierarchyAdapter(this._documents, provider), extension);2765this._proxy.$registerCallHierarchyProvider(handle, this._transformDocumentSelector(selector, extension));2766return this._createDisposable(handle);2767}27682769$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {2770return this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined, token);2771}27722773$provideCallHierarchyIncomingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {2774return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsTo(sessionId, itemId, token), undefined, token);2775}27762777$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {2778return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsFrom(sessionId, itemId, token), undefined, token);2779}27802781$releaseCallHierarchy(handle: number, sessionId: string): void {2782this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined, undefined);2783}27842785// --- type hierarchy2786registerTypeHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.TypeHierarchyProvider): vscode.Disposable {2787const handle = this._addNewAdapter(new TypeHierarchyAdapter(this._documents, provider), extension);2788this._proxy.$registerTypeHierarchyProvider(handle, this._transformDocumentSelector(selector, extension));2789return this._createDisposable(handle);2790}27912792$prepareTypeHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2793return this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined, token);2794}27952796$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2797return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSupertypes(sessionId, itemId, token), undefined, token);2798}27992800$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.ITypeHierarchyItemDto[] | undefined> {2801return this._withAdapter(handle, TypeHierarchyAdapter, adapter => adapter.provideSubtypes(sessionId, itemId, token), undefined, token);2802}28032804$releaseTypeHierarchy(handle: number, sessionId: string): void {2805this._withAdapter(handle, TypeHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined, undefined);2806}28072808// --- Document on drop28092810registerDocumentOnDropEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentDropEditProvider, metadata?: vscode.DocumentDropEditProviderMetadata) {2811const handle = this._nextHandle();2812this._adapter.set(handle, new AdapterData(new DocumentDropEditAdapter(this._proxy, this._documents, provider, handle, extension), extension));28132814this._proxy.$registerDocumentOnDropEditProvider(handle, this._transformDocumentSelector(selector, extension), metadata ? {2815supportsResolve: !!provider.resolveDocumentDropEdit,2816dropMimeTypes: metadata.dropMimeTypes,2817providedDropKinds: metadata.providedDropEditKinds?.map(x => x.value),2818} : undefined);28192820return this._createDisposable(handle);2821}28222823$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentDropEditDto[] | undefined> {2824return this._withAdapter(handle, DocumentDropEditAdapter, adapter =>2825Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined);2826}28272828$resolveDropEdit(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2829return this._withAdapter(handle, DocumentDropEditAdapter, adapter => adapter.resolveDropEdit(id, token), {}, undefined);2830}28312832$releaseDocumentOnDropEdits(handle: number, cacheId: number): void {2833this._withAdapter(handle, DocumentDropEditAdapter, adapter => Promise.resolve(adapter.releaseDropEdits(cacheId)), undefined, undefined);2834}28352836// --- copy/paste actions28372838registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable {2839const handle = this._nextHandle();2840this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle, extension), extension));2841this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector, extension), {2842supportsCopy: !!provider.prepareDocumentPaste,2843supportsPaste: !!provider.provideDocumentPasteEdits,2844supportsResolve: !!provider.resolveDocumentPasteEdit,2845providedPasteEditKinds: metadata.providedPasteEditKinds?.map(x => x.value),2846copyMimeTypes: metadata.copyMimeTypes,2847pasteMimeTypes: metadata.pasteMimeTypes,2848});2849return this._createDisposable(handle);2850}28512852$prepareDocumentPaste(handle: number, resource: UriComponents, ranges: IRange[], dataTransfer: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {2853return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.prepareDocumentPaste(URI.revive(resource), ranges, dataTransfer, token), undefined, token);2854}28552856$providePasteEdits(handle: number, requestId: number, resource: UriComponents, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, context: extHostProtocol.IDocumentPasteContextDto, token: CancellationToken): Promise<extHostProtocol.IPasteEditDto[] | undefined> {2857return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.providePasteEdits(requestId, URI.revive(resource), ranges, dataTransferDto, context, token), undefined, token);2858}28592860$resolvePasteEdit(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<{ additionalEdit?: extHostProtocol.IWorkspaceEditDto }> {2861return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.resolvePasteEdit(id, token), {}, undefined);2862}28632864$releasePasteEdits(handle: number, cacheId: number): void {2865this._withAdapter(handle, DocumentPasteEditProvider, adapter => Promise.resolve(adapter.releasePasteEdits(cacheId)), undefined, undefined);2866}28672868// --- configuration28692870private static _serializeRegExp(regExp: RegExp): extHostProtocol.IRegExpDto {2871return {2872pattern: regExp.source,2873flags: regExp.flags,2874};2875}28762877private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): extHostProtocol.IIndentationRuleDto {2878return {2879decreaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.decreaseIndentPattern),2880increaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.increaseIndentPattern),2881indentNextLinePattern: indentationRule.indentNextLinePattern ? ExtHostLanguageFeatures._serializeRegExp(indentationRule.indentNextLinePattern) : undefined,2882unIndentedLinePattern: indentationRule.unIndentedLinePattern ? ExtHostLanguageFeatures._serializeRegExp(indentationRule.unIndentedLinePattern) : undefined,2883};2884}28852886private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): extHostProtocol.IOnEnterRuleDto {2887return {2888beforeText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.beforeText),2889afterText: onEnterRule.afterText ? ExtHostLanguageFeatures._serializeRegExp(onEnterRule.afterText) : undefined,2890previousLineText: onEnterRule.previousLineText ? ExtHostLanguageFeatures._serializeRegExp(onEnterRule.previousLineText) : undefined,2891action: onEnterRule.action2892};2893}28942895private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): extHostProtocol.IOnEnterRuleDto[] {2896return onEnterRules.map(ExtHostLanguageFeatures._serializeOnEnterRule);2897}28982899private static _serializeAutoClosingPair(autoClosingPair: vscode.AutoClosingPair): IAutoClosingPairConditional {2900return {2901open: autoClosingPair.open,2902close: autoClosingPair.close,2903notIn: autoClosingPair.notIn ? autoClosingPair.notIn.map(v => SyntaxTokenType.toString(v)) : undefined,2904};2905}29062907private static _serializeAutoClosingPairs(autoClosingPairs: vscode.AutoClosingPair[]): IAutoClosingPairConditional[] {2908return autoClosingPairs.map(ExtHostLanguageFeatures._serializeAutoClosingPair);2909}29102911setLanguageConfiguration(extension: IExtensionDescription, languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {2912const { wordPattern } = configuration;29132914// check for a valid word pattern2915if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {2916throw new Error(`Invalid language configuration: wordPattern '${wordPattern}' is not allowed to match the empty string.`);2917}29182919// word definition2920if (wordPattern) {2921this._documents.setWordDefinitionFor(languageId, wordPattern);2922} else {2923this._documents.setWordDefinitionFor(languageId, undefined);2924}29252926if (configuration.__electricCharacterSupport) {2927this._apiDeprecation.report('LanguageConfiguration.__electricCharacterSupport', extension,2928`Do not use.`);2929}29302931if (configuration.__characterPairSupport) {2932this._apiDeprecation.report('LanguageConfiguration.__characterPairSupport', extension,2933`Do not use.`);2934}29352936const handle = this._nextHandle();2937const serializedConfiguration: extHostProtocol.ILanguageConfigurationDto = {2938comments: configuration.comments,2939brackets: configuration.brackets,2940wordPattern: configuration.wordPattern ? ExtHostLanguageFeatures._serializeRegExp(configuration.wordPattern) : undefined,2941indentationRules: configuration.indentationRules ? ExtHostLanguageFeatures._serializeIndentationRule(configuration.indentationRules) : undefined,2942onEnterRules: configuration.onEnterRules ? ExtHostLanguageFeatures._serializeOnEnterRules(configuration.onEnterRules) : undefined,2943__electricCharacterSupport: configuration.__electricCharacterSupport,2944__characterPairSupport: configuration.__characterPairSupport,2945autoClosingPairs: configuration.autoClosingPairs ? ExtHostLanguageFeatures._serializeAutoClosingPairs(configuration.autoClosingPairs) : undefined,2946};29472948this._proxy.$setLanguageConfiguration(handle, languageId, serializedConfiguration);2949return this._createDisposable(handle);2950}29512952$setWordDefinitions(wordDefinitions: extHostProtocol.ILanguageWordDefinitionDto[]): void {2953for (const wordDefinition of wordDefinitions) {2954this._documents.setWordDefinitionFor(wordDefinition.languageId, new RegExp(wordDefinition.regexSource, wordDefinition.regexFlags));2955}2956}2957}295829592960