mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 17:23:31 -05:00
Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c (#8525)
* Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c * remove files we don't want * fix hygiene * update distro * update distro * fix hygiene * fix strict nulls * distro * distro * fix tests * fix tests * add another edit * fix viewlet icon * fix azure dialog * fix some padding * fix more padding issues
This commit is contained in:
@@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import * as vscode from 'vscode';
|
||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
@@ -26,6 +26,9 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokens';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
|
||||
// --- adapter
|
||||
|
||||
@@ -348,7 +351,7 @@ class CodeActionAdapter {
|
||||
only: context.only ? new CodeActionKind(context.only) : undefined
|
||||
};
|
||||
|
||||
return asPromise(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then(commandsOrActions => {
|
||||
return asPromise(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then((commandsOrActions): extHostProtocol.ICodeActionListDto | undefined => {
|
||||
if (!isNonEmptyArray(commandsOrActions) || token.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -386,11 +389,12 @@ class CodeActionAdapter {
|
||||
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
|
||||
kind: candidate.kind && candidate.kind.value,
|
||||
isPreferred: candidate.isPreferred,
|
||||
disabled: candidate.disabled
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return <extHostProtocol.ICodeActionListDto>{ cacheId, actions };
|
||||
return { cacheId, actions };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -471,13 +475,13 @@ class OnTypeFormattingAdapter {
|
||||
|
||||
class NavigateTypeAdapter {
|
||||
|
||||
private readonly _symbolCache: { [id: number]: vscode.SymbolInformation } = Object.create(null);
|
||||
private readonly _resultCache: { [id: number]: [number, number] } = Object.create(null);
|
||||
private readonly _provider: vscode.WorkspaceSymbolProvider;
|
||||
private readonly _symbolCache = new Map<number, vscode.SymbolInformation>();
|
||||
private readonly _resultCache = new Map<number, [number, number]>();
|
||||
|
||||
constructor(provider: vscode.WorkspaceSymbolProvider) {
|
||||
this._provider = provider;
|
||||
}
|
||||
constructor(
|
||||
private readonly _provider: vscode.WorkspaceSymbolProvider,
|
||||
private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolsDto> {
|
||||
const result: extHostProtocol.IWorkspaceSymbolsDto = extHostProtocol.IdObject.mixin({ symbols: [] });
|
||||
@@ -489,44 +493,42 @@ class NavigateTypeAdapter {
|
||||
continue;
|
||||
}
|
||||
if (!item.name) {
|
||||
console.warn('INVALID SymbolInformation, lacks name', item);
|
||||
this._logService.warn('INVALID SymbolInformation, lacks name', item);
|
||||
continue;
|
||||
}
|
||||
const symbol = extHostProtocol.IdObject.mixin(typeConvert.WorkspaceSymbol.from(item));
|
||||
this._symbolCache[symbol._id!] = item;
|
||||
this._symbolCache.set(symbol._id!, item);
|
||||
result.symbols.push(symbol);
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
if (result.symbols.length > 0) {
|
||||
this._resultCache[result._id!] = [result.symbols[0]._id!, result.symbols[result.symbols.length - 1]._id!];
|
||||
this._resultCache.set(result._id!, [result.symbols[0]._id!, result.symbols[result.symbols.length - 1]._id!]);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
resolveWorkspaceSymbol(symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {
|
||||
|
||||
async resolveWorkspaceSymbol(symbol: extHostProtocol.IWorkspaceSymbolDto, token: CancellationToken): Promise<extHostProtocol.IWorkspaceSymbolDto | undefined> {
|
||||
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
|
||||
return Promise.resolve(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
const item = this._symbolCache[symbol._id!];
|
||||
const item = this._symbolCache.get(symbol._id!);
|
||||
if (item) {
|
||||
return asPromise(() => this._provider.resolveWorkspaceSymbol!(item, token)).then(value => {
|
||||
return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);
|
||||
});
|
||||
const value = await asPromise(() => this._provider.resolveWorkspaceSymbol!(item, token));
|
||||
return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
releaseWorkspaceSymbols(id: number): any {
|
||||
const range = this._resultCache[id];
|
||||
const range = this._resultCache.get(id);
|
||||
if (range) {
|
||||
for (let [from, to] = range; from <= to; from++) {
|
||||
delete this._symbolCache[from];
|
||||
this._symbolCache.delete(from);
|
||||
}
|
||||
delete this._resultCache[id];
|
||||
this._resultCache.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -539,7 +541,8 @@ class RenameAdapter {
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.RenameProvider
|
||||
private readonly _provider: vscode.RenameProvider,
|
||||
private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto | undefined> {
|
||||
@@ -588,7 +591,7 @@ class RenameAdapter {
|
||||
return undefined;
|
||||
}
|
||||
if (range.start.line > pos.line || range.end.line < pos.line) {
|
||||
console.warn('INVALID rename location: position line must be within range start/end lines');
|
||||
this._logService.warn('INVALID rename location: position line must be within range start/end lines');
|
||||
return undefined;
|
||||
}
|
||||
return { range: typeConvert.Range.from(range), text };
|
||||
@@ -613,30 +616,148 @@ class RenameAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
class SemanticTokensPreviousResult {
|
||||
constructor(
|
||||
public readonly resultId: string | undefined,
|
||||
public readonly tokens?: Uint32Array,
|
||||
) { }
|
||||
}
|
||||
|
||||
export class SemanticTokensAdapter {
|
||||
|
||||
private readonly _previousResults: Map<number, SemanticTokensPreviousResult>;
|
||||
private _nextResultId = 1;
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.SemanticTokensProvider,
|
||||
) {
|
||||
this._previousResults = new Map<number, SemanticTokensPreviousResult>();
|
||||
}
|
||||
|
||||
provideSemanticTokens(resource: URI, ranges: IRange[] | null, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const previousResult = (previousResultId !== 0 ? this._previousResults.get(previousResultId) : null);
|
||||
const opts: vscode.SemanticTokensRequestOptions = {
|
||||
ranges: (Array.isArray(ranges) && ranges.length > 0 ? ranges.map<Range>(typeConvert.Range.to) : undefined),
|
||||
previousResultId: (previousResult ? previousResult.resultId : undefined)
|
||||
};
|
||||
return asPromise(() => this._provider.provideSemanticTokens(doc, opts, token)).then(value => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
if (previousResult) {
|
||||
this._previousResults.delete(previousResultId);
|
||||
}
|
||||
return this._send(SemanticTokensAdapter._convertToEdits(previousResult, value), value);
|
||||
});
|
||||
}
|
||||
|
||||
async releaseSemanticColoring(semanticColoringResultId: number): Promise<void> {
|
||||
this._previousResults.delete(semanticColoringResultId);
|
||||
}
|
||||
|
||||
private static _isSemanticTokens(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokens {
|
||||
return v && !!((v as vscode.SemanticTokens).data);
|
||||
}
|
||||
|
||||
private static _isSemanticTokensEdits(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokensEdits {
|
||||
return v && Array.isArray((v as vscode.SemanticTokensEdits).edits);
|
||||
}
|
||||
|
||||
private static _convertToEdits(previousResult: SemanticTokensPreviousResult | null | undefined, newResult: vscode.SemanticTokens | vscode.SemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {
|
||||
if (!SemanticTokensAdapter._isSemanticTokens(newResult)) {
|
||||
return newResult;
|
||||
}
|
||||
if (!previousResult || !previousResult.tokens) {
|
||||
return newResult;
|
||||
}
|
||||
const oldData = previousResult.tokens;
|
||||
const oldLength = oldData.length;
|
||||
const newData = newResult.data;
|
||||
const newLength = newData.length;
|
||||
|
||||
let commonPrefixLength = 0;
|
||||
const maxCommonPrefixLength = Math.min(oldLength, newLength);
|
||||
while (commonPrefixLength < maxCommonPrefixLength && oldData[commonPrefixLength] === newData[commonPrefixLength]) {
|
||||
commonPrefixLength++;
|
||||
}
|
||||
|
||||
if (commonPrefixLength === oldLength && commonPrefixLength === newLength) {
|
||||
// complete overlap!
|
||||
return new SemanticTokensEdits([], newResult.resultId);
|
||||
}
|
||||
|
||||
let commonSuffixLength = 0;
|
||||
const maxCommonSuffixLength = maxCommonPrefixLength - commonPrefixLength;
|
||||
while (commonSuffixLength < maxCommonSuffixLength && oldData[oldLength - commonSuffixLength - 1] === newData[newLength - commonSuffixLength - 1]) {
|
||||
commonSuffixLength++;
|
||||
}
|
||||
|
||||
return new SemanticTokensEdits([{
|
||||
start: commonPrefixLength,
|
||||
deleteCount: (oldLength - commonPrefixLength - commonSuffixLength),
|
||||
data: newData.subarray(commonPrefixLength, newLength - commonSuffixLength)
|
||||
}], newResult.resultId);
|
||||
}
|
||||
|
||||
private _send(value: vscode.SemanticTokens | vscode.SemanticTokensEdits, original: vscode.SemanticTokens | vscode.SemanticTokensEdits): VSBuffer | null {
|
||||
if (SemanticTokensAdapter._isSemanticTokens(value)) {
|
||||
const myId = this._nextResultId++;
|
||||
this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId, value.data));
|
||||
return encodeSemanticTokensDto({
|
||||
id: myId,
|
||||
type: 'full',
|
||||
data: value.data
|
||||
});
|
||||
}
|
||||
|
||||
if (SemanticTokensAdapter._isSemanticTokensEdits(value)) {
|
||||
const myId = this._nextResultId++;
|
||||
if (SemanticTokensAdapter._isSemanticTokens(original)) {
|
||||
// store the original
|
||||
this._previousResults.set(myId, new SemanticTokensPreviousResult(original.resultId, original.data));
|
||||
} else {
|
||||
this._previousResults.set(myId, new SemanticTokensPreviousResult(value.resultId));
|
||||
}
|
||||
return encodeSemanticTokensDto({
|
||||
id: myId,
|
||||
type: 'delta',
|
||||
deltas: (value.edits || []).map(edit => ({ start: edit.start, deleteCount: edit.deleteCount, data: edit.data }))
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class SuggestAdapter {
|
||||
|
||||
static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
|
||||
return typeof provider.resolveCompletionItem === 'function';
|
||||
}
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: CommandsConverter;
|
||||
private _provider: vscode.CompletionItemProvider;
|
||||
|
||||
private _cache = new Cache<vscode.CompletionItem>('CompletionItem');
|
||||
private _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(documents: ExtHostDocuments, commands: CommandsConverter, provider: vscode.CompletionItemProvider) {
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._provider = provider;
|
||||
}
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _commands: CommandsConverter,
|
||||
private readonly _provider: vscode.CompletionItemProvider,
|
||||
private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
|
||||
// The default insert/replace ranges. It's important to compute them
|
||||
// before asynchronously asking the provider for its results. See
|
||||
// https://github.com/microsoft/vscode/issues/83400#issuecomment-546851421
|
||||
const replaceRange = doc.getWordRangeAtPosition(pos) || new Range(pos, pos);
|
||||
const insertRange = replaceRange.with({ end: pos });
|
||||
|
||||
return asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))).then(value => {
|
||||
|
||||
if (!value) {
|
||||
@@ -657,14 +778,10 @@ class SuggestAdapter {
|
||||
const disposables = new DisposableStore();
|
||||
this._disposables.set(pid, disposables);
|
||||
|
||||
// the default text edit range
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
.with({ end: pos });
|
||||
|
||||
const result: extHostProtocol.ISuggestResultDto = {
|
||||
x: pid,
|
||||
b: [],
|
||||
a: typeConvert.Range.from(wordRangeBeforePos),
|
||||
a: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },
|
||||
c: list.isIncomplete || undefined
|
||||
};
|
||||
|
||||
@@ -711,7 +828,7 @@ class SuggestAdapter {
|
||||
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, id: extHostProtocol.ChainedCacheId): extHostProtocol.ISuggestDataDto | undefined {
|
||||
if (typeof item.label !== 'string' || item.label.length === 0) {
|
||||
console.warn('INVALID text edit -> must have at least a label');
|
||||
this._logService.warn('INVALID text edit -> must have at least a label');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -751,21 +868,46 @@ class SuggestAdapter {
|
||||
}
|
||||
|
||||
// 'overwrite[Before|After]'-logic
|
||||
let range: vscode.Range | undefined;
|
||||
let range: vscode.Range | { inserting: vscode.Range, replacing: vscode.Range; } | undefined;
|
||||
if (item.textEdit) {
|
||||
range = item.textEdit.range;
|
||||
} else if (item.range) {
|
||||
range = item.range;
|
||||
} else if (item.range2) {
|
||||
range = item.range2;
|
||||
}
|
||||
result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);
|
||||
|
||||
if (range && (!range.isSingleLine || range.start.line !== position.line)) {
|
||||
console.warn('INVALID text edit -> must be single line and on the same line');
|
||||
return undefined;
|
||||
if (range) {
|
||||
if (Range.isRange(range)) {
|
||||
if (!SuggestAdapter._isValidRangeForCompletion(range, position)) {
|
||||
this._logService.trace('INVALID range -> must be single line and on the same line');
|
||||
return undefined;
|
||||
}
|
||||
result[extHostProtocol.ISuggestDataDtoField.range] = typeConvert.Range.from(range);
|
||||
|
||||
} else {
|
||||
if (
|
||||
!SuggestAdapter._isValidRangeForCompletion(range.inserting, position)
|
||||
|| !SuggestAdapter._isValidRangeForCompletion(range.replacing, position)
|
||||
|| !range.inserting.start.isEqual(range.replacing.start)
|
||||
|| !range.replacing.contains(range.inserting)
|
||||
) {
|
||||
this._logService.trace('INVALID range -> must be single line, on the same line, insert range must be a prefix of replace range');
|
||||
return undefined;
|
||||
}
|
||||
result[extHostProtocol.ISuggestDataDtoField.range] = {
|
||||
insert: typeConvert.Range.from(range.inserting),
|
||||
replace: typeConvert.Range.from(range.replacing)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static _isValidRangeForCompletion(range: vscode.Range, position: vscode.Position): boolean {
|
||||
return range.isSingleLine || range.start.line === position.line;
|
||||
}
|
||||
}
|
||||
|
||||
class SignatureHelpAdapter {
|
||||
@@ -966,7 +1108,8 @@ class SelectionRangeAdapter {
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.SelectionRangeProvider
|
||||
private readonly _provider: vscode.SelectionRangeProvider,
|
||||
private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
provideSelectionRanges(resource: URI, pos: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]> {
|
||||
@@ -978,7 +1121,7 @@ class SelectionRangeAdapter {
|
||||
return [];
|
||||
}
|
||||
if (allProviderRanges.length !== positions.length) {
|
||||
console.warn('BAD selection ranges, provider must return ranges for each position');
|
||||
this._logService.warn('BAD selection ranges, provider must return ranges for each position');
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1009,37 +1152,95 @@ class SelectionRangeAdapter {
|
||||
|
||||
class CallHierarchyAdapter {
|
||||
|
||||
private readonly _idPool = new IdGenerator('');
|
||||
private readonly _cache = new Map<string, Map<string, vscode.CallHierarchyItem>>();
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _provider: vscode.CallHierarchyItemProvider
|
||||
private readonly _provider: vscode.CallHierarchyProvider
|
||||
) { }
|
||||
|
||||
async provideCallsTo(uri: URI, position: IPosition, token: CancellationToken): Promise<[extHostProtocol.ICallHierarchyItemDto, IRange[]][] | undefined> {
|
||||
async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto | undefined> {
|
||||
const doc = this._documents.getDocument(uri);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
const calls = await this._provider.provideCallHierarchyIncomingCalls(doc, pos, token);
|
||||
if (!calls) {
|
||||
|
||||
const item = await this._provider.prepareCallHierarchy(doc, pos, token);
|
||||
if (!item) {
|
||||
return undefined;
|
||||
}
|
||||
return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.from), call.fromRanges.map(typeConvert.Range.from)]));
|
||||
const sessionId = this._idPool.nextId();
|
||||
|
||||
this._cache.set(sessionId, new Map());
|
||||
return this._cacheAndConvertItem(sessionId, item);
|
||||
}
|
||||
|
||||
async provideCallsFrom(uri: URI, position: IPosition, token: CancellationToken): Promise<[extHostProtocol.ICallHierarchyItemDto, IRange[]][] | undefined> {
|
||||
const doc = this._documents.getDocument(uri);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
const calls = await this._provider.provideCallHierarchyOutgoingCalls(doc, pos, token);
|
||||
async provideCallsTo(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {
|
||||
const item = this._itemFromCache(sessionId, itemId);
|
||||
if (!item) {
|
||||
throw new Error('missing call hierarchy item');
|
||||
}
|
||||
const calls = await this._provider.provideCallHierarchyIncomingCalls(item, token);
|
||||
if (!calls) {
|
||||
return undefined;
|
||||
}
|
||||
return calls.map(call => (<[extHostProtocol.ICallHierarchyItemDto, IRange[]]>[typeConvert.CallHierarchyItem.from(call.to), call.fromRanges.map(typeConvert.Range.from)]));
|
||||
return calls.map(call => {
|
||||
return {
|
||||
from: this._cacheAndConvertItem(sessionId, call.from),
|
||||
fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async provideCallsFrom(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {
|
||||
const item = this._itemFromCache(sessionId, itemId);
|
||||
if (!item) {
|
||||
throw new Error('missing call hierarchy item');
|
||||
}
|
||||
const calls = await this._provider.provideCallHierarchyOutgoingCalls(item, token);
|
||||
if (!calls) {
|
||||
return undefined;
|
||||
}
|
||||
return calls.map(call => {
|
||||
return {
|
||||
to: this._cacheAndConvertItem(sessionId, call.to),
|
||||
fromRanges: call.fromRanges.map(r => typeConvert.Range.from(r))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
releaseSession(sessionId: string): void {
|
||||
this._cache.delete(sessionId.charAt(0));
|
||||
}
|
||||
|
||||
private _cacheAndConvertItem(itemOrSessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const sessionId = itemOrSessionId.charAt(0);
|
||||
const map = this._cache.get(sessionId)!;
|
||||
const dto: extHostProtocol.ICallHierarchyItemDto = {
|
||||
_sessionId: sessionId,
|
||||
_itemId: map.size.toString(36),
|
||||
name: item.name,
|
||||
detail: item.detail,
|
||||
kind: typeConvert.SymbolKind.from(item.kind),
|
||||
uri: item.uri,
|
||||
range: typeConvert.Range.from(item.range),
|
||||
selectionRange: typeConvert.Range.from(item.selectionRange),
|
||||
};
|
||||
map.set(dto._itemId, item);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private _itemFromCache(sessionId: string, itemId: string): vscode.CallHierarchyItem | undefined {
|
||||
const map = this._cache.get(sessionId);
|
||||
return map && map.get(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
|
||||
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter
|
||||
| ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter | SelectionRangeAdapter | CallHierarchyAdapter;
|
||||
| SemanticTokensAdapter | SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter
|
||||
| ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter
|
||||
| DeclarationAdapter | SelectionRangeAdapter | CallHierarchyAdapter;
|
||||
|
||||
class AdapterData {
|
||||
constructor(
|
||||
@@ -1119,7 +1320,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
return ExtHostLanguageFeatures._handlePool++;
|
||||
}
|
||||
|
||||
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A, extension: IExtensionDescription | undefined) => Promise<R>, fallbackValue: R): Promise<R> {
|
||||
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A; }, callback: (adapter: A, extension: IExtensionDescription | undefined) => Promise<R>, fallbackValue: R): Promise<R> {
|
||||
const data = this._adapter.get(handle);
|
||||
if (!data) {
|
||||
return Promise.resolve(fallbackValue);
|
||||
@@ -1330,7 +1531,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
// --- navigate types
|
||||
|
||||
registerWorkspaceSymbolProvider(extension: IExtensionDescription, provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new NavigateTypeAdapter(provider), extension);
|
||||
const handle = this._addNewAdapter(new NavigateTypeAdapter(provider, this._logService), extension);
|
||||
this._proxy.$registerNavigateTypeSupport(handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -1350,7 +1551,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
// --- rename
|
||||
|
||||
registerRenameProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider), extension);
|
||||
const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider, this._logService), extension);
|
||||
this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), RenameAdapter.supportsResolving(provider));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -1363,10 +1564,28 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token), undefined);
|
||||
}
|
||||
|
||||
//#region semantic coloring
|
||||
|
||||
registerSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SemanticTokensAdapter(this._documents, provider), extension);
|
||||
this._proxy.$registerSemanticTokensProvider(handle, this._transformDocumentSelector(selector), legend);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideSemanticTokens(handle: number, resource: UriComponents, ranges: IRange[] | null, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {
|
||||
return this._withAdapter(handle, SemanticTokensAdapter, adapter => adapter.provideSemanticTokens(URI.revive(resource), ranges, previousResultId, token), null);
|
||||
}
|
||||
|
||||
$releaseSemanticTokens(handle: number, semanticColoringResultId: number): void {
|
||||
this._withAdapter(handle, SemanticTokensAdapter, adapter => adapter.releaseSemanticColoring(semanticColoringResultId), undefined);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
// --- suggestion
|
||||
|
||||
registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider), extension);
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService), extension);
|
||||
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -1450,7 +1669,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
// --- smart select
|
||||
|
||||
registerSelectionRangeProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SelectionRangeProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SelectionRangeAdapter(this._documents, provider), extension);
|
||||
const handle = this._addNewAdapter(new SelectionRangeAdapter(this._documents, provider, this._logService), extension);
|
||||
this._proxy.$registerSelectionRangeProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -1461,18 +1680,26 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
|
||||
// --- call hierarchy
|
||||
|
||||
registerCallHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CallHierarchyItemProvider): vscode.Disposable {
|
||||
registerCallHierarchyProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CallHierarchyProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new CallHierarchyAdapter(this._documents, provider), extension);
|
||||
this._proxy.$registerCallHierarchyProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCallHierarchyIncomingCalls(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<[extHostProtocol.ICallHierarchyItemDto, IRange[]][] | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsTo(URI.revive(resource), position, token), undefined);
|
||||
$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined);
|
||||
}
|
||||
|
||||
$provideCallHierarchyOutgoingCalls(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<[extHostProtocol.ICallHierarchyItemDto, IRange[]][] | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsFrom(URI.revive(resource), position, token), undefined);
|
||||
$provideCallHierarchyIncomingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsTo(sessionId, itemId, token), undefined);
|
||||
}
|
||||
|
||||
$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IOutgoingCallDto[] | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => adapter.provideCallsFrom(sessionId, itemId, token), undefined);
|
||||
}
|
||||
|
||||
$releaseCallHierarchy(handle: number, sessionId: string): void {
|
||||
this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.releaseSession(sessionId)), undefined);
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
Reference in New Issue
Block a user