提交 3ba44a03 编写于 作者: J Johannes Rieken

minimize suggest dto, #71060

上级 83d8f282
...@@ -460,6 +460,11 @@ export interface CompletionItem { ...@@ -460,6 +460,11 @@ export interface CompletionItem {
* A command that should be run upon acceptance of this item. * A command that should be run upon acceptance of this item.
*/ */
command?: Command; command?: Command;
/**
* @internal
*/
[key: string]: any;
} }
export interface CompletionList { export interface CompletionList {
......
...@@ -10,8 +10,8 @@ import * as modes from 'vs/editor/common/modes'; ...@@ -10,8 +10,8 @@ import * as modes from 'vs/editor/common/modes';
import * as search from 'vs/workbench/contrib/search/common/search'; import * as search from 'vs/workbench/contrib/search/common/search';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { Position as EditorPosition } from 'vs/editor/common/core/position'; import { Position as EditorPosition } from 'vs/editor/common/core/position';
import { Range as EditorRange } from 'vs/editor/common/core/range'; import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, DefinitionLinkDto, ISerializedSignatureHelpProviderMetadata, CodeInsetDto, LinkDto, CallHierarchyDto } from '../common/extHost.protocol'; import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, WorkspaceSymbolDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, DefinitionLinkDto, ISerializedSignatureHelpProviderMetadata, CodeInsetDto, LinkDto, CallHierarchyDto, SuggestDataDto } from '../common/extHost.protocol';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
import { IModeService } from 'vs/editor/common/services/modeService'; import { IModeService } from 'vs/editor/common/services/modeService';
...@@ -22,6 +22,7 @@ import * as codeInset from 'vs/workbench/contrib/codeinset/common/codeInset'; ...@@ -22,6 +22,7 @@ import * as codeInset from 'vs/workbench/contrib/codeinset/common/codeInset';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'; import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { IHeapService } from 'vs/workbench/services/heap/common/heap'; import { IHeapService } from 'vs/workbench/services/heap/common/heap';
import { mixin } from 'vs/base/common/objects';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures) @extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape { export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape {
...@@ -359,8 +360,29 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha ...@@ -359,8 +360,29 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- suggest // --- suggest
private static _inflateSuggestDto(defaultRange: IRange, data: SuggestDataDto): modes.CompletionItem {
return {
label: data.a,
kind: data.b,
detail: data.c,
documentation: data.d,
sortText: data.e,
filterText: data.f,
preselect: data.g,
insertText: data.h || data.a,
insertTextRules: data.i,
range: data.j || defaultRange,
commitCharacters: data.k,
additionalTextEdits: data.l,
command: data.m,
// not-standard
_id: data.x,
_pid: data.y
};
}
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void { $registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void {
this._registrations[handle] = modes.CompletionProviderRegistry.register(selector, <modes.CompletionItemProvider>{ const provider: modes.CompletionItemProvider = {
triggerCharacters, triggerCharacters,
provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.CompletionContext, token: CancellationToken): Promise<modes.CompletionList | undefined> => { provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.CompletionContext, token: CancellationToken): Promise<modes.CompletionList | undefined> => {
return this._proxy.$provideCompletionItems(handle, model.uri, position, context, token).then(result => { return this._proxy.$provideCompletionItems(handle, model.uri, position, context, token).then(result => {
...@@ -368,20 +390,25 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha ...@@ -368,20 +390,25 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return result; return result;
} }
return { return {
suggestions: result.suggestions, suggestions: result.b.map(d => MainThreadLanguageFeatures._inflateSuggestDto(result.a, d)),
incomplete: result.incomplete, incomplete: result.c,
dispose: () => { dispose: () => this._proxy.$releaseCompletionItems(handle, result.x)
if (typeof result._id === 'number') {
this._proxy.$releaseCompletionItems(handle, result._id);
}
}
}; };
}); });
}, }
resolveCompletionItem: supportsResolveDetails };
? (model, position, suggestion, token) => this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion, token) if (supportsResolveDetails) {
: undefined provider.resolveCompletionItem = (model, position, suggestion, token) => {
}); return this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion._id, suggestion._pid, token).then(result => {
if (!result) {
return suggestion;
}
let newSuggestion = MainThreadLanguageFeatures._inflateSuggestDto(suggestion.range, result);
return mixin(suggestion, newSuggestion, true);
});
};
}
this._registrations[handle] = modes.CompletionProviderRegistry.register(selector, provider);
} }
// --- parameter hints // --- parameter hints
......
...@@ -854,14 +854,30 @@ export class IdObject { ...@@ -854,14 +854,30 @@ export class IdObject {
} }
} }
export interface SuggestionDto extends modes.CompletionItem { export interface SuggestDataDto {
_id: number; a/* label */: string;
_parentId: number; b/* kind */: modes.CompletionItemKind;
} c/* detail */?: string;
d/* documentation */?: string | IMarkdownString;
export interface SuggestResultDto extends IdObject { e/* sortText */?: string;
suggestions: SuggestionDto[]; f/* filterText */?: string;
incomplete?: boolean; g/* preselect */?: boolean;
h/* insertText */?: string;
i/* insertTextRules */?: modes.CompletionItemInsertTextRule;
j/* range */?: IRange;
k/* commitCharacters */?: string[];
l/* additionalTextEdits */?: ISingleEditOperation[];
m/* command */?: modes.Command;
// not-standard
x: number;
y: number;
}
export interface SuggestResultDto {
x: number;
a: IRange;
b: SuggestDataDto[];
c?: boolean;
} }
export interface LocationDto { export interface LocationDto {
...@@ -982,7 +998,7 @@ export interface ExtHostLanguageFeaturesShape { ...@@ -982,7 +998,7 @@ export interface ExtHostLanguageFeaturesShape {
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined>; $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation | undefined>; $resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation | undefined>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto | undefined>; $provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto | undefined>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem>; $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: number, pid: number, token: CancellationToken): Promise<SuggestDataDto | undefined>;
$releaseCompletionItems(handle: number, id: number): void; $releaseCompletionItems(handle: number, id: number): void;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined>; $provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinkDto[] | undefined>; $provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinkDto[] | undefined>;
......
...@@ -15,7 +15,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments'; ...@@ -15,7 +15,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands'; import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics'; import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { asPromise } from 'vs/base/common/async'; import { asPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto } from '../common/extHost.protocol'; import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata, LinkDto, CodeLensDto, MainThreadWebviewsShape, CodeInsetDto, SuggestDataDto } from '../common/extHost.protocol';
import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings'; import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position'; import { IPosition } from 'vs/editor/common/core/position';
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range'; import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
...@@ -637,15 +637,18 @@ class SuggestAdapter { ...@@ -637,15 +637,18 @@ class SuggestAdapter {
const doc = this._documents.getDocument(resource); const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position); const pos = typeConvert.Position.to(position);
return asPromise<vscode.CompletionItem[] | vscode.CompletionList | null | undefined>( return asPromise(() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))).then(value => {
() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))
).then(value => {
const _id = this._idPool++; const _id = this._idPool++;
// the default text edit range
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
.with({ end: pos });
const result: SuggestResultDto = { const result: SuggestResultDto = {
_id, x: _id,
suggestions: [], b: [],
a: typeConvert.Range.from(wordRangeBeforePos),
}; };
let list: CompletionList; let list: CompletionList;
...@@ -658,54 +661,45 @@ class SuggestAdapter { ...@@ -658,54 +661,45 @@ class SuggestAdapter {
} else { } else {
list = value; list = value;
result.incomplete = list.isIncomplete; result.c = list.isIncomplete;
} }
// the default text edit range
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
.with({ end: pos });
for (let i = 0; i < list.items.length; i++) { for (let i = 0; i < list.items.length; i++) {
const suggestion = this._convertCompletionItem(list.items[i], pos, wordRangeBeforePos, i, _id); const suggestion = this._convertCompletionItem2(list.items[i], pos, i, _id);
// check for bad completion item // check for bad completion item
// for the converter did warn // for the converter did warn
if (suggestion) { if (suggestion) {
result.suggestions.push(suggestion); result.b.push(suggestion);
} }
} }
this._cache.set(_id, list.items);
if (SuggestAdapter.supportsResolving(this._provider)) {
this._cache.set(_id, list.items);
}
return result; return result;
}); });
} }
resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> { resolveCompletionItem(_resource: URI, position: IPosition, id: number, pid: number, token: CancellationToken): Promise<SuggestDataDto | undefined> {
if (typeof this._provider.resolveCompletionItem !== 'function') { if (typeof this._provider.resolveCompletionItem !== 'function') {
return Promise.resolve(suggestion); return Promise.resolve(undefined);
} }
const { _parentId, _id } = (<SuggestionDto>suggestion); const item = this._cache.has(pid) ? this._cache.get(pid)![id] : undefined;
const item = this._cache.has(_parentId) ? this._cache.get(_parentId)![_id] : undefined;
if (!item) { if (!item) {
return Promise.resolve(suggestion); return Promise.resolve(undefined);
} }
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => { return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
if (!resolvedItem) { if (!resolvedItem) {
return suggestion; return undefined;
} }
const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position); const pos = typeConvert.Position.to(position);
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)).with({ end: pos }); return this._convertCompletionItem2(resolvedItem, pos, id, pid);
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
if (newSuggestion) {
mixin(suggestion, newSuggestion, true);
}
return suggestion;
}); });
} }
...@@ -713,60 +707,52 @@ class SuggestAdapter { ...@@ -713,60 +707,52 @@ class SuggestAdapter {
this._cache.delete(id); this._cache.delete(id);
} }
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto | undefined { private _convertCompletionItem2(item: vscode.CompletionItem, position: vscode.Position, id: number, pid: number): SuggestDataDto | undefined {
if (typeof item.label !== 'string' || item.label.length === 0) { if (typeof item.label !== 'string' || item.label.length === 0) {
console.warn('INVALID text edit -> must have at least a label'); console.warn('INVALID text edit -> must have at least a label');
return undefined; return undefined;
} }
const result: SuggestionDto = { const result: SuggestDataDto = {
//
_id,
_parentId,
// //
label: item.label, x: id,
kind: typeConvert.CompletionItemKind.from(item.kind), y: pid,
detail: item.detail,
documentation: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
filterText: item.filterText,
sortText: item.sortText,
preselect: item.preselect,
// //
range: undefined!, // populated below a: item.label,
insertText: undefined!, // populated below b: typeConvert.CompletionItemKind.from(item.kind),
insertTextRules: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0, c: item.detail,
additionalTextEdits: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from), d: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
command: this._commands.toInternal(item.command), e: item.sortText,
commitCharacters: item.commitCharacters f: item.filterText,
g: item.preselect,
i: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
k: item.commitCharacters,
l: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),
m: this._commands.toInternal(item.command),
}; };
// 'insertText'-logic // 'insertText'-logic
if (item.textEdit) { if (item.textEdit) {
result.insertText = item.textEdit.newText; result.h = item.textEdit.newText;
} else if (typeof item.insertText === 'string') { } else if (typeof item.insertText === 'string') {
result.insertText = item.insertText; result.h = item.insertText;
} else if (item.insertText instanceof SnippetString) { } else if (item.insertText instanceof SnippetString) {
result.insertText = item.insertText.value; result.h = item.insertText.value;
result.insertTextRules! |= modes.CompletionItemInsertTextRule.InsertAsSnippet; result.i! |= modes.CompletionItemInsertTextRule.InsertAsSnippet;
} else {
result.insertText = item.label;
} }
// 'overwrite[Before|After]'-logic // 'overwrite[Before|After]'-logic
let range: vscode.Range; let range: vscode.Range | undefined;
if (item.textEdit) { if (item.textEdit) {
range = item.textEdit.range; range = item.textEdit.range;
} else if (item.range) { } else if (item.range) {
range = item.range; range = item.range;
} else {
range = defaultRange;
} }
result.range = typeConvert.Range.from(range); result.j = typeConvert.Range.from(range);
if (!range.isSingleLine || range.start.line !== position.line) { if (range && (!range.isSingleLine || range.start.line !== position.line)) {
console.warn('INVALID text edit -> must be single line and on the same line'); console.warn('INVALID text edit -> must be single line and on the same line');
return undefined; return undefined;
} }
...@@ -1387,8 +1373,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { ...@@ -1387,8 +1373,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined); return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined);
} }
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> { $resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: number, pid: number, token: CancellationToken): Promise<SuggestDataDto | undefined> {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, suggestion, token), suggestion); return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, pid, token), undefined);
} }
$releaseCompletionItems(handle: number, id: number): void { $releaseCompletionItems(handle: number, id: number): void {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册