提交 79a01a0f 编写于 作者: P Pine Wu

Revert isDetailsResolved and implement CompletionItemLabel

上级 fecfa6ec
......@@ -60,12 +60,17 @@ export function activate(context: ExtensionContext) {
(Array.isArray(r) ? r : r.items).forEach(updateRanges);
if (!Array.isArray(r)) {
r.isDetailsResolved = true;
r.items.forEach(i => {
if (i.kind === CompletionItemKind.Color) {
i.detail = i.documentation?.toString();
i.label = {
label: i.label as string,
details: i.documentation?.toString()
};
} else {
i.detail = i.label;
i.label = {
label: i.label as string,
details: i.label as string
};
}
});
}
......
......@@ -369,6 +369,28 @@ export let completionKindFromString: {
};
})();
export interface CompletionItemLabel {
/**
* The label of this completion item. By default
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
/**
* A description of the completion item which is rendered
* less prominent.
*/
// description?: string;
/**
* Details of the completion item that is rendered less
* prominent to the right.
*/
details?: string;
}
export const enum CompletionItemTag {
Deprecated = 1
}
......@@ -396,7 +418,7 @@ export interface CompletionItem {
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
label: string | CompletionItemLabel;
/**
* The kind of this completion item. Based on the kind
* an icon is chosen by the editor.
......@@ -481,7 +503,6 @@ export interface CompletionItem {
export interface CompletionList {
suggestions: CompletionItem[];
incomplete?: boolean;
isDetailsResolved?: boolean;
dispose?(): void;
}
......
......@@ -192,6 +192,7 @@ export class CompletionModel {
}
}
const label = typeof item.completion.label === 'string' ? item.completion.label : item.completion.label.label;
if (wordPos >= wordLen) {
// the wordPos at which scoring starts is the whole word
// and therefore the same rules as not having a word apply
......@@ -206,19 +207,19 @@ export class CompletionModel {
if (!match) {
continue; // NO match
}
if (compareIgnoreCase(item.completion.filterText, item.completion.label) === 0) {
if (compareIgnoreCase(item.completion.filterText, label) === 0) {
// filterText and label are actually the same -> use good highlights
item.score = match;
} else {
// re-run the scorer on the label in the hope of a result BUT use the rank
// of the filterText-match
item.score = anyScore(word, wordLow, wordPos, item.completion.label, item.labelLow, 0);
item.score = anyScore(word, wordLow, wordPos, label, item.labelLow, 0);
item.score[0] = match[0]; // use score from filterText
}
} else {
// by default match `word` against the `label`
let match = scoreFn(word, wordLow, wordPos, item.completion.label, item.labelLow, 0, false);
let match = scoreFn(word, wordLow, wordPos, label, item.labelLow, 0, false);
if (!match) {
continue; // NO match
}
......
......@@ -36,6 +36,9 @@ export class CompletionItem {
readonly editInsertEnd: IPosition;
readonly editReplaceEnd: IPosition;
//
readonly textLabel: string;
// perf
readonly labelLow: string;
readonly sortTextLow?: string;
......@@ -47,9 +50,6 @@ export class CompletionItem {
idx?: number;
word?: string;
// all details resolved, we can show them all
readonly isDetailsResolved: boolean;
constructor(
readonly position: IPosition,
readonly completion: modes.CompletionItem,
......@@ -57,8 +57,13 @@ export class CompletionItem {
readonly provider: modes.CompletionItemProvider,
model: ITextModel
) {
this.textLabel = typeof completion.label === 'string'
? completion.label
: completion.label.label;
// ensure lower-variants (perf)
this.labelLow = completion.label.toLowerCase();
this.labelLow = this.textLabel.toLowerCase();
this.sortTextLow = completion.sortText && completion.sortText.toLowerCase();
this.filterTextLow = completion.filterText && completion.filterText.toLowerCase();
......@@ -73,8 +78,6 @@ export class CompletionItem {
this.editReplaceEnd = new Position(completion.range.replace.endLineNumber, completion.range.replace.endColumn);
}
this.isDetailsResolved = container.isDetailsResolved || typeof provider.resolveCompletionItem === 'undefined';
// create the suggestion resolver
const { resolveCompletionItem } = provider;
if (typeof resolveCompletionItem !== 'function') {
......@@ -188,7 +191,7 @@ export function provideSuggestionItems(
}
// fill in default sortText when missing
if (!suggestion.sortText) {
suggestion.sortText = suggestion.label;
suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.label;
}
allSuggestions.push(new CompletionItem(position, suggestion, container, provider, model));
......
......@@ -343,8 +343,9 @@ export class SuggestController implements IEditorContribution {
}
private _alertCompletionItem({ completion: suggestion }: CompletionItem): void {
const textLabel = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.label;
if (isNonEmptyArray(suggestion.additionalTextEdits)) {
let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' made {1} additional edits", suggestion.label, suggestion.additionalTextEdits.length);
let msg = nls.localize('arai.alert.snippet', "Accepting '{0}' made {1} additional edits", textLabel, suggestion.additionalTextEdits.length);
alert(msg);
}
}
......
......@@ -67,8 +67,12 @@ export const editorSuggestWidgetHighlightForeground = registerColor('editorSugge
const colorRegExp = /^(#([\da-f]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))$/i;
function extractColor(item: CompletionItem, out: string[]): boolean {
if (item.completion.label.match(colorRegExp)) {
out[0] = item.completion.label;
const label = typeof item.completion.label === 'string'
? item.completion.label
: item.completion.label.label;
if (label.match(colorRegExp)) {
out[0] = label;
return true;
}
if (typeof item.completion.documentation === 'string' && item.completion.documentation.match(colorRegExp)) {
......@@ -163,6 +167,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
renderElement(element: CompletionItem, _index: number, templateData: ISuggestionTemplateData): void {
const data = <ISuggestionTemplateData>templateData;
const suggestion = (<CompletionItem>element).completion;
const textLabel = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.label;
data.icon.className = 'icon ' + completionKindToCssClass(suggestion.kind);
data.colorspan.style.backgroundColor = '';
......@@ -183,7 +188,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
// special logic for 'file' completion items
data.icon.className = 'icon hide';
data.iconContainer.className = 'icon hide';
const labelClasses = getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.label }), FileKind.FILE);
const labelClasses = getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: textLabel }), FileKind.FILE);
const detailClasses = getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.detail }), FileKind.FILE);
labelOptions.extraClasses = labelClasses.length > detailClasses.length ? labelClasses : detailClasses;
......@@ -192,7 +197,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
data.icon.className = 'icon hide';
data.iconContainer.className = 'icon hide';
labelOptions.extraClasses = flatten([
getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.label }), FileKind.FOLDER),
getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: textLabel }), FileKind.FOLDER),
getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.detail }), FileKind.FOLDER)
]);
} else {
......@@ -207,8 +212,12 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
labelOptions.matches = [];
}
data.iconLabel.setLabel(suggestion.label, undefined, labelOptions);
data.typeLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');
data.iconLabel.setLabel(textLabel, undefined, labelOptions);
if (typeof suggestion.label === 'string') {
data.typeLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');
} else {
data.typeLabel.textContent = (suggestion.label.details || '').replace(/\n.*$/m, '');
}
if (canExpandCompletionItem(element)) {
show(data.readMore);
......@@ -621,10 +630,11 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
private _getSuggestionAriaAlertLabel(item: CompletionItem): string {
const textLabel = typeof item.completion.label === 'string' ? item.completion.label : item.completion.label.label;
if (this.expandDocsSettingFromStorage()) {
return nls.localize('ariaCurrenttSuggestionReadDetails', "Item {0}, docs: {1}", item.completion.label, this.details.getAriaLabel());
return nls.localize('ariaCurrenttSuggestionReadDetails', "Item {0}, docs: {1}", textLabel, this.details.getAriaLabel());
} else {
return item.completion.label;
return textLabel;
}
}
......
......@@ -48,7 +48,10 @@ export abstract class WordDistance {
if (suggestion.kind === CompletionItemKind.Keyword) {
return 2 << 20;
}
let word = suggestion.label;
let word = typeof suggestion.label === 'string'
? suggestion.label
: suggestion.label.label;
let wordLines = wordRanges[word];
if (isFalsyOrEmpty(wordLines)) {
return 2 << 20;
......
......@@ -4744,6 +4744,24 @@ declare namespace monaco.languages {
Snippet = 25
}
export interface CompletionItemLabel {
/**
* The label of this completion item. By default
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
/**
* A description of the completion item which is rendered
* less prominent.
*/
/**
* Details of the completion item that is rendered less
* prominent to the right.
*/
details?: string;
}
export enum CompletionItemTag {
Deprecated = 1
}
......@@ -4770,7 +4788,7 @@ declare namespace monaco.languages {
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
label: string | CompletionItemLabel;
/**
* The kind of this completion item. Based on the kind
* an icon is chosen by the editor.
......@@ -4853,7 +4871,6 @@ declare namespace monaco.languages {
export interface CompletionList {
suggestions: CompletionItem[];
incomplete?: boolean;
isDetailsResolved?: boolean;
dispose?(): void;
}
......
......@@ -3360,7 +3360,7 @@ declare module 'vscode' {
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
label: string | CompletionItemLabel;
/**
* The kind of this completion item. Based on the kind
......
......@@ -1509,8 +1509,26 @@ declare module 'vscode' {
//#region https://github.com/microsoft/vscode/issues/39441
export interface CompletionList {
isDetailsResolved?: boolean;
export interface CompletionItemLabel {
/**
* The label of this completion item. By default
* this is also the text that is inserted when selecting
* this completion.
*/
label: string;
/**
* A description of the completion item which is rendered
* less prominent.
*/
// description?: string;
/**
* Details of the completion item that is rendered less
* prominent to the right.
*/
details?: string;
}
//#endregion
......
......@@ -334,6 +334,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- suggest
private static _inflateSuggestDto(defaultRange: IRange | { insert: IRange, replace: IRange }, data: ISuggestDataDto): modes.CompletionItem {
const label = data[ISuggestDataDtoField.label];
const labelText = typeof label === 'string'
? label
: label.label;
return {
label: data[ISuggestDataDtoField.label],
......@@ -344,7 +348,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
sortText: data[ISuggestDataDtoField.sortText],
filterText: data[ISuggestDataDtoField.filterText],
preselect: data[ISuggestDataDtoField.preselect],
insertText: typeof data.h === 'undefined' ? data[ISuggestDataDtoField.label] : data.h,
insertText: typeof data.h === 'undefined' ? labelText : data.h,
range: data[ISuggestDataDtoField.range] || defaultRange,
insertTextRules: data[ISuggestDataDtoField.insertTextRules],
commitCharacters: data[ISuggestDataDtoField.commitCharacters],
......@@ -367,7 +371,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return {
suggestions: result.b.map(d => MainThreadLanguageFeatures._inflateSuggestDto(result.a, d)),
incomplete: result.c,
isDetailsResolved: result.d,
dispose: () => typeof result.x === 'number' && this._proxy.$releaseCompletionItems(handle, result.x)
};
});
......
......@@ -989,7 +989,7 @@ export const enum ISuggestDataDtoField {
}
export interface ISuggestDataDto {
[ISuggestDataDtoField.label]: string;
[ISuggestDataDtoField.label]: string | modes.CompletionItemLabel;
[ISuggestDataDtoField.kind]: modes.CompletionItemKind;
[ISuggestDataDtoField.detail]?: string;
[ISuggestDataDtoField.documentation]?: string | IMarkdownString;
......@@ -1012,7 +1012,6 @@ export interface ISuggestResultDto {
a: { insert: IRange, replace: IRange; };
b: ISuggestDataDto[];
c?: boolean;
d?: boolean;
}
export interface ISignatureHelpDto {
......
......@@ -787,8 +787,7 @@ class SuggestAdapter {
x: pid,
b: [],
a: { replace: typeConvert.Range.from(replaceRange), insert: typeConvert.Range.from(insertRange) },
c: list.isIncomplete || undefined,
d: list.isDetailsResolved || undefined
c: list.isIncomplete || undefined
};
for (let i = 0; i < list.items.length; i++) {
......@@ -858,7 +857,11 @@ 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) {
const label = typeof item.label === 'string'
? item.label
: item.label.label;
if (typeof label !== 'string' || label.length === 0) {
this._logService.warn('INVALID text edit -> must have at least a label');
return undefined;
}
......
......@@ -1351,10 +1351,17 @@ export enum CompletionItemTag {
Deprecated = 1,
}
export interface CompletionItemLabel {
label: string;
// description?: string;
details?: string;
}
@es5ClassCompat
export class CompletionItem implements vscode.CompletionItem {
label: string;
label: string | CompletionItemLabel;
kind?: CompletionItemKind;
tags?: CompletionItemTag[];
detail?: string;
......@@ -1371,7 +1378,7 @@ export class CompletionItem implements vscode.CompletionItem {
additionalTextEdits?: TextEdit[];
command?: vscode.Command;
constructor(label: string, kind?: CompletionItemKind) {
constructor(label: string | CompletionItemLabel, kind?: CompletionItemKind) {
this.label = label;
this.kind = kind;
}
......@@ -1395,7 +1402,6 @@ export class CompletionItem implements vscode.CompletionItem {
export class CompletionList {
isIncomplete?: boolean;
isDetailsResolved?: boolean;
items: vscode.CompletionItem[];
constructor(items: vscode.CompletionItem[] = [], isIncomplete: boolean = false) {
......
......@@ -146,7 +146,7 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
i = to;
}
}
return { suggestions, isDetailsResolved: true };
return { suggestions };
});
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册