Merge from vscode 718331d6f3ebd1b571530ab499edb266ddd493d5

This commit is contained in:
ADS Merger
2020-02-08 04:50:58 +00:00
parent 8c61538a27
commit 2af13c18d2
752 changed files with 16458 additions and 10063 deletions

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/suggest';
import 'vs/css!./media/suggestStatusBar';
import 'vs/base/browser/ui/codiconLabel/codiconLabel'; // The codicon symbol styles are defined here and must be loaded
import 'vs/editor/contrib/documentSymbols/outlineTree'; // The codicon symbol colors are defined here and must be loaded
import * as nls from 'vs/nls';
@@ -20,7 +21,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition, IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { Context as SuggestContext, CompletionItem } from './suggest';
import { Context as SuggestContext, CompletionItem, suggestWidgetStatusbarMenu } from './suggest';
import { CompletionModel } from './completionModel';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { attachListStyler } from 'vs/platform/theme/common/styler';
@@ -39,8 +40,11 @@ import { URI } from 'vs/base/common/uri';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { FileKind } from 'vs/platform/files/common/files';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { flatten } from 'vs/base/common/arrays';
import { flatten, isFalsyOrEmpty } from 'vs/base/common/arrays';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMenuService } from 'vs/platform/actions/common/actions';
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction } from 'vs/base/common/actions';
const expandSuggestionDocsByDefault = false;
@@ -49,8 +53,8 @@ interface ISuggestionTemplateData {
/**
* Flexbox
* < ------- left ------- > < -------- right -------- >
* <icon><label><signature> <qualifier><type><readmore>
* < ------------- left ------------ > < --- right -- >
* <icon><label><signature><qualifier> <type><readmore>
*/
left: HTMLElement;
right: HTMLElement;
@@ -301,7 +305,7 @@ class SuggestionDetails {
private readonly widget: SuggestWidget,
private readonly editor: ICodeEditor,
private readonly markdownRenderer: MarkdownRenderer,
private readonly triggerKeybindingLabel: string,
private readonly kbToggleDetails: string,
) {
this.disposables = new DisposableStore();
@@ -316,7 +320,7 @@ class SuggestionDetails {
this.header = append(this.body, $('.header'));
this.close = append(this.header, $('span.codicon.codicon-close'));
this.close.title = nls.localize('readLess', "Read less...{0}", this.triggerKeybindingLabel);
this.close.title = nls.localize('readLess', "Read less...{0}", this.kbToggleDetails);
this.type = append(this.header, $('p.type'));
this.docs = append(this.body, $('p.docs'));
@@ -340,7 +344,8 @@ class SuggestionDetails {
}
renderItem(item: CompletionItem, explainMode: boolean): void {
this.renderDisposeable = dispose(this.renderDisposeable);
dispose(this.renderDisposeable);
this.renderDisposeable = undefined;
let { documentation, detail } = item.completion;
// --- documentation
@@ -447,7 +452,8 @@ class SuggestionDetails {
dispose(): void {
this.disposables.dispose();
this.renderDisposeable = dispose(this.renderDisposeable);
dispose(this.renderDisposeable);
this.renderDisposeable = undefined;
}
}
@@ -479,12 +485,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private element: HTMLElement;
private messageElement: HTMLElement;
private listElement: HTMLElement;
private statusBarElement: HTMLElement;
private details: SuggestionDetails;
private list: List<CompletionItem>;
private listHeight?: number;
private readonly suggestWidgetVisible: IContextKey<boolean>;
private readonly suggestWidgetMultipleSuggestions: IContextKey<boolean>;
private readonly ctxSuggestWidgetVisible: IContextKey<boolean>;
private readonly ctxSuggestWidgetDetailsVisible: IContextKey<boolean>;
private readonly ctxSuggestWidgetMultipleSuggestions: IContextKey<boolean>;
private readonly showTimeout = new TimeoutTimer();
private readonly toDispose = new DisposableStore();
@@ -517,18 +525,19 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
constructor(
private readonly editor: ICodeEditor,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService,
@IKeybindingService keybindingService: IKeybindingService,
@IModeService modeService: IModeService,
@IOpenerService openerService: IOpenerService,
@IMenuService menuService: IMenuService,
@IInstantiationService instantiationService: IInstantiationService,
) {
const kb = keybindingService.lookupKeybinding('editor.action.triggerSuggest');
const triggerKeybindingLabel = !kb ? '' : ` (${kb.getLabel()})`;
const markdownRenderer = this.toDispose.add(new MarkdownRenderer(editor, modeService, openerService));
const kbToggleDetails = keybindingService.lookupKeybinding('toggleSuggestionDetails')?.getLabel() ?? '';
this.isAuto = false;
this.focusedItem = null;
this.storageService = storageService;
@@ -542,12 +551,55 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement = append(this.element, $('.message'));
this.listElement = append(this.element, $('.tree'));
this.details = instantiationService.createInstance(SuggestionDetails, this.element, this, this.editor, markdownRenderer, triggerKeybindingLabel);
const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', !this.editor.getOption(EditorOption.suggest).hideStatusBar);
applyStatusBarStyle();
this.statusBarElement = append(this.element, $('.suggest-status-bar'));
const actionViewItemProvider = <IActionViewItemProvider>(action => {
const kb = keybindingService.lookupKeybindings(action.id);
return new class extends ActionViewItem {
constructor() {
super(undefined, action, { label: true, icon: false });
}
updateLabel() {
if (isFalsyOrEmpty(kb) || !this.label) {
return super.updateLabel();
}
const { label } = this.getAction();
this.label.textContent = /{\d}/.test(label)
? strings.format(this.getAction().label, kb[0].getLabel())
: `${this.getAction().label} (${kb[0].getLabel()})`;
}
};
});
const leftActions = new ActionBar(this.statusBarElement, { actionViewItemProvider });
const rightActions = new ActionBar(this.statusBarElement, { actionViewItemProvider });
const menu = menuService.createMenu(suggestWidgetStatusbarMenu, contextKeyService);
const renderMenu = () => {
const left: IAction[] = [];
const right: IAction[] = [];
for (let [group, actions] of menu.getActions()) {
if (group === 'left') {
left.push(...actions);
} else {
right.push(...actions);
}
}
leftActions.clear();
leftActions.push(left);
rightActions.clear();
rightActions.push(right);
};
this.toDispose.add(menu.onDidChange(() => renderMenu()));
this.toDispose.add(menu);
this.details = instantiationService.createInstance(SuggestionDetails, this.element, this, this.editor, markdownRenderer, kbToggleDetails);
const applyIconStyle = () => toggleClass(this.element, 'no-icons', !this.editor.getOption(EditorOption.suggest).showIcons);
applyIconStyle();
let renderer = instantiationService.createInstance(ItemRenderer, this, this.editor, triggerKeybindingLabel);
let renderer = instantiationService.createInstance(ItemRenderer, this, this.editor, kbToggleDetails);
this.list = new List('SuggestWidget', this.listElement, this, [renderer], {
useShadows: false,
@@ -582,10 +634,16 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.toDispose.add(this.list.onSelectionChange(e => this.onListSelection(e)));
this.toDispose.add(this.list.onFocusChange(e => this.onListFocus(e)));
this.toDispose.add(this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged()));
this.toDispose.add(this.editor.onDidChangeConfiguration(e => { if (e.hasChanged(EditorOption.suggest)) { applyIconStyle(); } }));
this.toDispose.add(this.editor.onDidChangeConfiguration(e => {
if (e.hasChanged(EditorOption.suggest)) {
applyStatusBarStyle();
applyIconStyle();
}
}));
this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
this.suggestWidgetMultipleSuggestions = SuggestContext.MultipleSuggestions.bindTo(contextKeyService);
this.ctxSuggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
this.ctxSuggestWidgetDetailsVisible = SuggestContext.DetailsVisible.bindTo(contextKeyService);
this.ctxSuggestWidgetMultipleSuggestions = SuggestContext.MultipleSuggestions.bindTo(contextKeyService);
this.editor.addContentWidget(this);
this.setState(State.Hidden);
@@ -661,12 +719,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
const backgroundColor = theme.getColor(editorSuggestWidgetBackground);
if (backgroundColor) {
this.listElement.style.backgroundColor = backgroundColor.toString();
this.statusBarElement.style.backgroundColor = backgroundColor.toString();
this.details.element.style.backgroundColor = backgroundColor.toString();
this.messageElement.style.backgroundColor = backgroundColor.toString();
}
const borderColor = theme.getColor(editorSuggestWidgetBorder);
if (borderColor) {
this.listElement.style.borderColor = borderColor.toString();
this.statusBarElement.style.borderColor = borderColor.toString();
this.details.element.style.borderColor = borderColor.toString();
this.messageElement.style.borderColor = borderColor.toString();
this.detailsBorderColor = borderColor.toString();
@@ -704,7 +764,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.firstFocusInCurrentList = !this.focusedItem;
if (item !== this.focusedItem) {
if (this.currentSuggestionDetails) {
this.currentSuggestionDetails.cancel();
this.currentSuggestionDetails = null;
@@ -759,7 +818,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
switch (state) {
case State.Hidden:
hide(this.messageElement, this.details.element, this.listElement);
hide(this.messageElement, this.details.element, this.listElement, this.statusBarElement);
this.hide();
this.listHeight = 0;
if (stateChanged) {
@@ -769,7 +828,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
break;
case State.Loading:
this.messageElement.textContent = SuggestWidget.LOADING_MESSAGE;
hide(this.listElement, this.details.element);
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.show();
@@ -777,7 +836,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
break;
case State.Empty:
this.messageElement.textContent = SuggestWidget.NO_SUGGESTIONS_MESSAGE;
hide(this.listElement, this.details.element);
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.show();
@@ -785,7 +844,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
break;
case State.Open:
hide(this.messageElement);
show(this.listElement);
show(this.listElement, this.statusBarElement);
this.show();
break;
case State.Frozen:
@@ -795,7 +854,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
break;
case State.Details:
hide(this.messageElement);
show(this.details.element, this.listElement);
show(this.details.element, this.listElement, this.statusBarElement);
this.show();
break;
}
@@ -836,7 +895,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
let visibleCount = this.completionModel.items.length;
const isEmpty = visibleCount === 0;
this.suggestWidgetMultipleSuggestions.set(visibleCount > 1);
this.ctxSuggestWidgetMultipleSuggestions.set(visibleCount > 1);
if (isEmpty) {
if (isAuto) {
@@ -1003,6 +1062,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
if (this.expandDocsSettingFromStorage()) {
this.ctxSuggestWidgetDetailsVisible.set(false);
this.updateExpandDocsSetting(false);
hide(this.details.element);
removeClass(this.element, 'docs-side');
@@ -1014,6 +1074,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
return;
}
this.ctxSuggestWidgetDetailsVisible.set(true);
this.updateExpandDocsSetting(true);
this.showDetails(false);
this.telemetryService.publicLog2('suggestWidget:expandDetails');
@@ -1021,7 +1082,10 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
showDetails(loading: boolean): void {
this.expandSideOrBelow();
if (!loading) {
// When loading, don't re-layout docs, as item is not resolved yet #88731
this.expandSideOrBelow();
}
show(this.details.element);
@@ -1058,7 +1122,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.listHeight = newHeight;
}
this.suggestWidgetVisible.set(true);
this.ctxSuggestWidgetVisible.set(true);
this.showTimeout.cancelAndSet(() => {
addClass(this.element, 'visible');
@@ -1067,8 +1131,8 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
private hide(): void {
this.suggestWidgetVisible.reset();
this.suggestWidgetMultipleSuggestions.reset();
this.ctxSuggestWidgetVisible.reset();
this.ctxSuggestWidgetMultipleSuggestions.reset();
removeClass(this.element, 'visible');
}
@@ -1119,6 +1183,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.element.style.lineHeight = `${this.unfocusedHeight}px`;
this.listElement.style.height = `${height}px`;
this.statusBarElement.style.top = `${height}px`;
this.list.layout(height);
return height;
}
@@ -1172,7 +1237,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
}
/**
* Adds the proper classes for positioning the docs to the side or below
* Adds the proper classes for positioning the docs to the side or below depending on item
*/
private expandSideOrBelow() {
if (!canExpandCompletionItem(this.focusedItem) && this.firstFocusInCurrentList) {