Merge from vscode bd0efff9e3f36d6b3e1045cee9887003af8034d7

This commit is contained in:
ADS Merger
2020-05-06 02:35:49 +00:00
parent 9a7810cbee
commit 8420d9f04e
243 changed files with 4276 additions and 2478 deletions

View File

@@ -156,12 +156,13 @@ export class StableEditorScrollState {
visiblePositionScrollDelta = editor.getScrollTop() - visiblePositionScrollTop;
}
}
return new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta);
return new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta, editor.getPosition());
}
constructor(
private readonly _visiblePosition: Position | null,
private readonly _visiblePositionScrollDelta: number
private readonly _visiblePositionScrollDelta: number,
private readonly _cursorPosition: Position | null
) {
}
@@ -171,4 +172,15 @@ export class StableEditorScrollState {
editor.setScrollTop(visiblePositionScrollTop + this._visiblePositionScrollDelta);
}
}
public restoreRelativeVerticalPositionOfCursor(editor: ICodeEditor): void {
const currentCursorPosition = editor.getPosition();
if (!this._cursorPosition || !currentCursorPosition) {
return;
}
const offset = editor.getTopForLineNumber(currentCursorPosition.lineNumber) - editor.getTopForLineNumber(this._cursorPosition.lineNumber);
editor.setScrollTop(editor.getScrollTop() + offset);
}
}

View File

@@ -21,6 +21,8 @@ import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { withNullAsUndefined, assertType } from 'vs/base/common/types';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
export type ServicesAccessor = InstantiationServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
@@ -48,6 +50,7 @@ export interface ICommandMenuOptions {
order: number;
when?: ContextKeyExpression;
title: string;
icon?: ThemeIcon
}
export interface ICommandOptions {
id: string;
@@ -118,6 +121,7 @@ export abstract class Command {
command: {
id: this.id,
title: item.title,
icon: item.icon
// precondition: this.precondition
},
when: item.when,

View File

@@ -1804,7 +1804,7 @@ export class EditorModeContext extends Disposable {
this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);
this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInEmbeddedEditor.bindTo(_contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInWalkThroughSnippet.bindTo(_contextKeyService);
const update = () => this._update();

View File

@@ -32,10 +32,17 @@ export namespace EditorContextKeys {
export const hasSingleSelection = hasMultipleSelections.toNegated();
export const tabMovesFocus = new RawContextKey<boolean>('editorTabMovesFocus', false);
export const tabDoesNotMoveFocus = tabMovesFocus.toNegated();
export const isInEmbeddedEditor = new RawContextKey<boolean>('isInEmbeddedEditor', false);
export const isInWalkThroughSnippet = new RawContextKey<boolean>('isInEmbeddedEditor', false);
export const canUndo = new RawContextKey<boolean>('canUndo', false);
export const canRedo = new RawContextKey<boolean>('canRedo', false);
/**
* A context key that is set when an editor is part of a larger editor, like notebooks or
* (future) a diff editor
*/
export const inCompositeEditor = new RawContextKey<boolean>('inCompositeEditor', undefined);
export const notInCompositeEditor = inCompositeEditor.toNegated();
// -- mode context keys
export const languageId = new RawContextKey<string>('editorLangId', '');
export const hasCompletionItemProvider = new RawContextKey<boolean>('editorHasCompletionItemProvider', false);

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
@@ -1276,7 +1277,8 @@ export class ValidAnnotatedEditOperation implements IIdentifiedSingleEditOperati
/**
* @internal
*/
export interface ITextBuffer {
export interface IReadonlyTextBuffer {
onDidChangeContent: Event<void>;
equals(other: ITextBuffer): boolean;
mightContainRTL(): boolean;
mightContainNonBasicASCII(): boolean;
@@ -1299,10 +1301,15 @@ export interface ITextBuffer {
getLineLength(lineNumber: number): number;
getLineFirstNonWhitespaceColumn(lineNumber: number): number;
getLineLastNonWhitespaceColumn(lineNumber: number): number;
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
}
/**
* @internal
*/
export interface ITextBuffer extends IReadonlyTextBuffer {
setEOL(newEOL: '\r\n' | '\n'): void;
applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult;
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
}
/**

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import * as strings from 'vs/base/common/strings';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -11,6 +12,7 @@ import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTex
import { SearchData } from 'vs/editor/common/model/textModelSearch';
import { countEOL, StringEOL } from 'vs/editor/common/model/tokensStore';
import { TextChange } from 'vs/editor/common/model/textChange';
import { IDisposable } from 'vs/base/common/lifecycle';
export interface IValidatedEditOperation {
sortIndex: number;
@@ -30,18 +32,24 @@ export interface IReverseSingleEditOperation extends IValidEditOperation {
sortIndex: number;
}
export class PieceTreeTextBuffer implements ITextBuffer {
export class PieceTreeTextBuffer implements ITextBuffer, IDisposable {
private readonly _pieceTree: PieceTreeBase;
private readonly _BOM: string;
private _mightContainRTL: boolean;
private _mightContainNonBasicASCII: boolean;
private readonly _onDidChangeContent: Emitter<void> = new Emitter<void>();
public readonly onDidChangeContent: Event<void> = this._onDidChangeContent.event;
constructor(chunks: StringBuffer[], BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, isBasicASCII: boolean, eolNormalized: boolean) {
this._BOM = BOM;
this._mightContainNonBasicASCII = !isBasicASCII;
this._mightContainRTL = containsRTL;
this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized);
}
dispose(): void {
this._onDidChangeContent.dispose();
}
// #region TextBuffer
public equals(other: ITextBuffer): boolean {
@@ -360,6 +368,8 @@ export class PieceTreeTextBuffer implements ITextBuffer {
}
}
this._onDidChangeContent.fire();
return new ApplyEditsResult(
reverseOperations,
contentChanges,

View File

@@ -608,7 +608,7 @@ export interface CompletionItemProvider {
*
* The editor will only resolve a completion item once.
*/
resolveCompletionItem?(model: model.ITextModel, position: Position, item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
resolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
}
export interface CodeAction {

View File

@@ -18,6 +18,7 @@ import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { withUndefinedAsNull } from 'vs/base/common/types';
import { minimapWarning, minimapError } from 'vs/platform/theme/common/colorRegistry';
import { Delayer } from 'vs/base/common/async';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -41,13 +42,14 @@ class MarkerDecorations extends Disposable {
return super._register(t);
}
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): void {
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): boolean {
const oldIds = keys(this._markersData);
this._markersData.clear();
const ids = this.model.deltaDecorations(oldIds, newDecorations);
for (let index = 0; index < ids.length; index++) {
this._markersData.set(ids[index], markers[index]);
}
return oldIds.length !== 0 || ids.length !== 0;
}
getMarker(decoration: IModelDecoration): IMarker | undefined {
@@ -114,7 +116,8 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
private _onModelAdded(model: ITextModel): void {
const markerDecorations = new MarkerDecorations(model);
this._markerDecorations.set(MODEL_ID(model.uri), markerDecorations);
markerDecorations.register(model.onDidChangeContent(() => this._updateDecorations(markerDecorations)));
const delayer = markerDecorations.register(new Delayer(100));
markerDecorations.register(model.onDidChangeContent(() => delayer.trigger(() => this._updateDecorations(markerDecorations))));
this._updateDecorations(markerDecorations);
}
@@ -144,8 +147,9 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
options: this._createDecorationOption(marker)
};
});
markerDecorations.update(markers, newModelDecorations);
this._onDidChangeMarker.fire(markerDecorations.model);
if (markerDecorations.update(markers, newModelDecorations)) {
this._onDidChangeMarker.fire(markerDecorations.model);
}
}
private _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range {

View File

@@ -29,50 +29,65 @@ export class SemanticTokensProviderStyling {
let metadata: number;
if (entry) {
metadata = entry.metadata;
} else {
const tokenType = this._legend.tokenTypes[tokenTypeIndex];
const tokenModifiers: string[] = [];
let modifierSet = tokenModifierSet;
for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
if (modifierSet & 1) {
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
}
modifierSet = modifierSet >> 1;
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling [CACHED] ${tokenTypeIndex} / ${tokenModifierSet}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
} else {
let tokenType = this._legend.tokenTypes[tokenTypeIndex];
const tokenModifiers: string[] = [];
if (tokenType) {
let modifierSet = tokenModifierSet;
for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
if (modifierSet & 1) {
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
}
modifierSet = modifierSet >> 1;
}
if (modifierSet > 0 && this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling: unknown token modifier index: ${tokenModifierSet.toString(2)} for legend: ${JSON.stringify(this._legend.tokenModifiers)}`);
tokenModifiers.push('not-in-legend');
}
const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId.language);
if (typeof tokenStyle === 'undefined') {
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
} else {
metadata = 0;
if (typeof tokenStyle.italic !== 'undefined') {
const italicBit = (tokenStyle.italic ? FontStyle.Italic : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= italicBit | MetadataConsts.SEMANTIC_USE_ITALIC;
}
if (typeof tokenStyle.bold !== 'undefined') {
const boldBit = (tokenStyle.bold ? FontStyle.Bold : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= boldBit | MetadataConsts.SEMANTIC_USE_BOLD;
}
if (typeof tokenStyle.underline !== 'undefined') {
const underlineBit = (tokenStyle.underline ? FontStyle.Underline : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= underlineBit | MetadataConsts.SEMANTIC_USE_UNDERLINE;
}
if (tokenStyle.foreground) {
const foregroundBits = (tokenStyle.foreground) << MetadataConsts.FOREGROUND_OFFSET;
metadata |= foregroundBits | MetadataConsts.SEMANTIC_USE_FOREGROUND;
}
if (metadata === 0) {
// Nothing!
const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId.language);
if (typeof tokenStyle === 'undefined') {
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
} else {
metadata = 0;
if (typeof tokenStyle.italic !== 'undefined') {
const italicBit = (tokenStyle.italic ? FontStyle.Italic : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= italicBit | MetadataConsts.SEMANTIC_USE_ITALIC;
}
if (typeof tokenStyle.bold !== 'undefined') {
const boldBit = (tokenStyle.bold ? FontStyle.Bold : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= boldBit | MetadataConsts.SEMANTIC_USE_BOLD;
}
if (typeof tokenStyle.underline !== 'undefined') {
const underlineBit = (tokenStyle.underline ? FontStyle.Underline : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= underlineBit | MetadataConsts.SEMANTIC_USE_UNDERLINE;
}
if (tokenStyle.foreground) {
const foregroundBits = (tokenStyle.foreground) << MetadataConsts.FOREGROUND_OFFSET;
metadata |= foregroundBits | MetadataConsts.SEMANTIC_USE_FOREGROUND;
}
if (metadata === 0) {
// Nothing!
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
}
}
} else {
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling: unknown token type index: ${tokenTypeIndex} for legend: ${JSON.stringify(this._legend.tokenTypes)}`);
}
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
tokenType = 'not-in-legend';
}
this._hashTable.add(tokenTypeIndex, tokenModifierSet, languageId.id, metadata);
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling ${tokenTypeIndex} (${tokenType}) / ${tokenModifierSet} (${tokenModifiers.join(' ')}): foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
}
if (this._logService.getLevel() === LogLevel.Trace) {
const type = this._legend.tokenTypes[tokenTypeIndex];
const modifiers = tokenModifierSet ? ' ' + this._legend.tokenModifiers.filter((_, i) => tokenModifierSet & (1 << i)).join(' ') : '';
this._logService.trace(`tokenStyleMetadata ${entry ? '[CACHED] ' : ''}${type}${modifiers}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
return metadata;
}
}

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./codelensWidget';
import * as dom from 'vs/base/browser/dom';
import { renderCodicons } from 'vs/base/common/codicons';
import { escape } from 'vs/base/common/strings';
import { IViewZone, IContentWidget, IActiveCodeEditor, IContentWidgetPosition, ContentWidgetPositionPreference, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
@@ -113,7 +112,7 @@ class CodeLensContentWidget implements IContentWidget {
}
this._domNode.innerHTML = innerHtml;
if (this._isEmpty && animate) {
dom.addClass(this._domNode, 'fadein');
this._domNode.classList.add('fadein');
}
this._isEmpty = false;
}

View File

@@ -102,7 +102,7 @@ export class OutlineGroupRenderer implements ITreeRenderer<OutlineGroup, FuzzySc
renderTemplate(container: HTMLElement): OutlineGroupTemplate {
const labelContainer = dom.$('.outline-element-label');
dom.addClass(container, 'outline-element');
container.classList.add('outline-element');
dom.append(container, labelContainer);
return new OutlineGroupTemplate(labelContainer, new HighlightedLabel(labelContainer, true));
}
@@ -129,7 +129,7 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
) { }
renderTemplate(container: HTMLElement): OutlineElementTemplate {
dom.addClass(container, 'outline-element');
container.classList.add('outline-element');
const iconLabel = new IconLabel(container, { supportHighlights: true });
const iconClass = dom.$('.outline-element-icon');
const decoration = dom.$('.outline-element-decoration');
@@ -184,14 +184,14 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
} else if (count > 0) {
dom.show(template.decoration);
dom.removeClass(template.decoration, 'bubble');
template.decoration.classList.remove('bubble');
template.decoration.innerText = count < 10 ? count.toString() : '+9';
template.decoration.title = count === 1 ? localize('1.problem', "1 problem in this element") : localize('N.problem', "{0} problems in this element", count);
template.decoration.style.setProperty('--outline-element-color', cssColor);
} else {
dom.show(template.decoration);
dom.addClass(template.decoration, 'bubble');
template.decoration.classList.add('bubble');
template.decoration.innerText = '\uea71';
template.decoration.title = localize('deep.problem', "Contains elements with problems");
template.decoration.style.setProperty('--outline-element-color', cssColor);

View File

@@ -213,7 +213,7 @@ class FormatDocumentAction extends EditorAction {
id: 'editor.action.formatDocument',
label: nls.localize('formatDocument.label', "Format Document"),
alias: 'Format Document',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider),
precondition: ContextKeyExpr.and(EditorContextKeys.notInCompositeEditor, EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider),
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentFormattingProvider),
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F,

View File

@@ -15,7 +15,6 @@ import { Range } from 'vs/editor/common/core/range';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { registerEditorAction, registerEditorContribution, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { MarkerNavigationWidget } from './gotoErrorWidget';
@@ -24,12 +23,10 @@ import { binarySearch, find } from 'vs/base/common/arrays';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { onUnexpectedError } from 'vs/base/common/errors';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Action } from 'vs/base/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { isEqual } from 'vs/base/common/resources';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
class MarkerModel {
@@ -192,9 +189,6 @@ class MarkerModel {
}
}
const markerNavigationNextIcon = registerIcon('marker-navigation-next', Codicon.chevronDown);
const markerNavigationPreviousIcon = registerIcon('marker-navigation-previous', Codicon.chevronUp);
export class MarkerController implements IEditorContribution {
public static readonly ID = 'editor.contrib.markerController';
@@ -213,10 +207,8 @@ export class MarkerController implements IEditorContribution {
editor: ICodeEditor,
@IMarkerService private readonly _markerService: IMarkerService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IThemeService private readonly _themeService: IThemeService,
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IOpenerService private readonly _openerService: IOpenerService
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this._editor = editor;
this._widgetVisible = CONTEXT_MARKERS_NAVIGATION_VISIBLE.bindTo(this._contextKeyService);
@@ -244,21 +236,13 @@ export class MarkerController implements IEditorContribution {
this._model = new MarkerModel(this._editor, markers);
this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._disposeOnClose);
const prevMarkerKeybinding = this._keybindingService.lookupKeybinding(PrevMarkerAction.ID);
const nextMarkerKeybinding = this._keybindingService.lookupKeybinding(NextMarkerAction.ID);
const actions = [
new Action(NextMarkerAction.ID, NextMarkerAction.LABEL + (nextMarkerKeybinding ? ` (${nextMarkerKeybinding.getLabel()})` : ''), 'show-next-problem ' + markerNavigationNextIcon.classNames, this._model.canNavigate(), async () => { if (this._model) { this._model.move(true, true); } }),
new Action(PrevMarkerAction.ID, PrevMarkerAction.LABEL + (prevMarkerKeybinding ? ` (${prevMarkerKeybinding.getLabel()})` : ''), 'show-previous-problem ' + markerNavigationPreviousIcon.classNames, this._model.canNavigate(), async () => { if (this._model) { this._model.move(false, true); } })
];
this._widget = new MarkerNavigationWidget(this._editor, actions, this._themeService, this._openerService);
this._widget = this._instantiationService.createInstance(MarkerNavigationWidget, this._editor);
this._widgetVisible.set(true);
this._widget.onDidClose(() => this.closeMarkersNavigation(), this, this._disposeOnClose);
this._disposeOnClose.add(this._model);
this._disposeOnClose.add(this._widget);
for (const action of actions) {
this._disposeOnClose.add(action);
}
this._disposeOnClose.add(this._widget.onDidSelectRelatedInformation(related => {
this._editorService.openCodeEditor({
resource: related.resource,
@@ -431,7 +415,18 @@ export class NextMarkerAction extends MarkerNavigationAction {
label: NextMarkerAction.LABEL,
alias: 'Go to Next Problem (Error, Warning, Info)',
precondition: undefined,
kbOpts: { kbExpr: EditorContextKeys.focus, primary: KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Alt | KeyCode.F8,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MarkerNavigationWidget.TitleMenu,
title: NextMarkerAction.LABEL,
icon: registerIcon('marker-navigation-next', Codicon.chevronDown),
group: 'navigation',
order: 1
}
});
}
}
@@ -445,7 +440,18 @@ class PrevMarkerAction extends MarkerNavigationAction {
label: PrevMarkerAction.LABEL,
alias: 'Go to Previous Problem (Error, Warning, Info)',
precondition: undefined,
kbOpts: { kbExpr: EditorContextKeys.focus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F8,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MarkerNavigationWidget.TitleMenu,
title: NextMarkerAction.LABEL,
icon: registerIcon('marker-navigation-previous', Codicon.chevronUp),
group: 'navigation',
order: 2
}
});
}
}

View File

@@ -27,6 +27,10 @@ import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/action
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
class MessageWidget {
@@ -224,6 +228,8 @@ class MessageWidget {
export class MarkerNavigationWidget extends PeekViewWidget {
static readonly TitleMenu = new MenuId('gotoErrorTitleMenu');
private _parentContainer!: HTMLElement;
private _container!: HTMLElement;
private _icon!: HTMLElement;
@@ -238,9 +244,11 @@ export class MarkerNavigationWidget extends PeekViewWidget {
constructor(
editor: ICodeEditor,
private readonly actions: ReadonlyArray<IAction>,
private readonly _themeService: IThemeService,
private readonly _openerService: IOpenerService
@IThemeService private readonly _themeService: IThemeService,
@IOpenerService private readonly _openerService: IOpenerService,
@IMenuService private readonly _menuService: IMenuService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
super(editor, { showArrow: true, showFrame: true, isAccessible: true });
this._severity = MarkerSeverity.Warning;
@@ -288,7 +296,11 @@ export class MarkerNavigationWidget extends PeekViewWidget {
protected _fillHead(container: HTMLElement): void {
super._fillHead(container);
this._actionbarWidget!.push(this.actions, { label: false, icon: true, index: 0 });
const actions: IAction[] = [];
const menu = this._menuService.createMenu(MarkerNavigationWidget.TitleMenu, this._contextKeyService);
createAndFillInActionBarActions(menu, undefined, actions);
this._actionbarWidget!.push(actions, { label: false, icon: true, index: 0 });
menu.dispose();
}
protected _fillTitleIcon(container: HTMLElement): void {
@@ -297,7 +309,8 @@ export class MarkerNavigationWidget extends PeekViewWidget {
protected _getActionBarOptions(): IActionBarOptions {
return {
orientation: ActionsOrientation.HORIZONTAL
orientation: ActionsOrientation.HORIZONTAL,
actionViewItemProvider: action => action instanceof MenuItemAction ? this._instantiationService.createInstance(MenuEntryActionViewItem, action) : undefined
};
}

View File

@@ -240,7 +240,7 @@ registerEditorAction(class GoToDefinitionAction extends DefinitionAction {
alias: 'Go to Definition',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: goToDefinitionKb,
@@ -276,7 +276,7 @@ registerEditorAction(class OpenDefinitionToSideAction extends DefinitionAction {
alias: 'Open Definition to the Side',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, goToDefinitionKb),
@@ -303,7 +303,7 @@ registerEditorAction(class PeekDefinitionAction extends DefinitionAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -361,7 +361,7 @@ registerEditorAction(class GoToDeclarationAction extends DeclarationAction {
alias: 'Go to Declaration',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDeclarationProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
group: 'navigation',
@@ -396,7 +396,7 @@ registerEditorAction(class PeekDeclarationAction extends DeclarationAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDeclarationProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -447,7 +447,7 @@ registerEditorAction(class GoToTypeDefinitionAction extends TypeDefinitionAction
alias: 'Go to Type Definition',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasTypeDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 0,
@@ -483,7 +483,7 @@ registerEditorAction(class PeekTypeDefinitionAction extends TypeDefinitionAction
precondition: ContextKeyExpr.and(
EditorContextKeys.hasTypeDefinitionProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -534,7 +534,7 @@ registerEditorAction(class GoToImplementationAction extends ImplementationAction
alias: 'Go to Implementations',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasImplementationProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.CtrlCmd | KeyCode.F12,
@@ -570,7 +570,7 @@ registerEditorAction(class PeekImplementationAction extends ImplementationAction
precondition: ContextKeyExpr.and(
EditorContextKeys.hasImplementationProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -621,7 +621,7 @@ registerEditorAction(class GoToReferencesAction extends ReferencesAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasReferenceProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -660,7 +660,7 @@ registerEditorAction(class PeekReferencesAction extends ReferencesAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasReferenceProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -693,7 +693,7 @@ class GenericGoToLocationAction extends SymbolNavigationAction {
alias: 'Go To Any Symbol',
precondition: ContextKeyExpr.and(
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
});
}

View File

@@ -119,7 +119,7 @@ class FileReferencesTemplate extends Disposable {
) {
super();
const parent = document.createElement('div');
dom.addClass(parent, 'reference-file');
parent.classList.add('reference-file');
this.file = this._register(new IconLabel(parent, { supportHighlights: true }));
this.badge = new CountBadge(dom.append(parent, dom.$('.count')));
@@ -184,10 +184,10 @@ class OneReferenceTemplate {
// we have score, then render the score
const { value, highlight } = preview;
if (score && !FuzzyScore.isDefault(score)) {
dom.toggleClass(this.label.element, 'referenceMatch', false);
this.label.element.classList.toggle('referenceMatch', false);
this.label.set(value, createMatches(score));
} else {
dom.toggleClass(this.label.element, 'referenceMatch', true);
this.label.element.classList.toggle('referenceMatch', true);
this.label.set(value, [highlight]);
}
}

View File

@@ -465,7 +465,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
}));
// make sure things are rendered
dom.addClass(this.container!, 'results-loaded');
this.container!.classList.add('results-loaded');
dom.show(this._treeContainer);
dom.show(this._previewContainer);
this._splitView.layout(this._dim.width);

View File

@@ -30,7 +30,8 @@
}
.monaco-editor-hover .markdown-hover > .hover-contents:not(.code-hover-contents) hr {
min-width: 100%;
/* This is a strange rule but it avoids https://github.com/microsoft/vscode/issues/96795, just 100vw on its own caused the actual hover width to increase */
min-width: calc(100% + 100vw);
}
.monaco-editor-hover p,

View File

@@ -15,7 +15,6 @@ import { inputBackground, inputBorder, inputForeground, widgetShadow, editorWidg
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { toggleClass } from 'vs/base/browser/dom';
import { CancellationToken } from 'vs/base/common/cancellation';
export const CONTEXT_RENAME_INPUT_VISIBLE = new RawContextKey<boolean>('renameInputVisible', false);
@@ -152,7 +151,7 @@ export class RenameInputField implements IContentWidget {
getInput(where: IRange, value: string, selectionStart: number, selectionEnd: number, supportPreview: boolean, token: CancellationToken): Promise<RenameInputFieldResult | boolean> {
toggleClass(this._domNode!, 'preview', supportPreview);
this._domNode!.classList.toggle('preview', supportPreview);
this._position = new Position(where.startLineNumber, where.startColumn);
this._input!.value = value;

View File

@@ -5,7 +5,6 @@
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { repeat } from 'vs/base/common/strings';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorCommand, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { Range } from 'vs/editor/common/core/range';
@@ -191,7 +190,7 @@ export class SnippetController2 implements IEditorContribution {
insertText: option.value,
// insertText: `\${1|${after.concat(before).join(',')}|}$0`,
// snippetType: 'textmate',
sortText: repeat('a', i + 1),
sortText: 'a'.repeat(i + 1),
range: Range.fromPositions(this._editor.getPosition()!, this._editor.getPosition()!.delta(0, first.value.length))
};
}));

View File

@@ -101,7 +101,7 @@ export class CompletionModel {
}
adopt(except: Set<CompletionItemProvider>): CompletionItem[] {
let res = new Array<CompletionItem>();
let res: CompletionItem[] = [];
for (let i = 0; i < this._items.length;) {
if (!except.has(this._items[i].provider)) {
res.push(this._items[i]);
@@ -151,6 +151,10 @@ export class CompletionModel {
const item = source[i];
if (item.isInvalid) {
continue; // SKIP invalid items
}
// collect those supports that signaled having
// an incomplete result
if (item.container.incomplete) {

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { first } from 'vs/base/common/async';
import { onUnexpectedExternalError, canceled, isPromiseCanceledError } from 'vs/base/common/errors';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
@@ -34,12 +33,6 @@ export class CompletionItem {
_brand!: 'ISuggestionItem';
private static readonly _defaultResolve = () => Promise.resolve();
readonly resolve: (token: CancellationToken) => Promise<void>;
isResolved: boolean = false;
//
readonly editStart: IPosition;
readonly editInsertEnd: IPosition;
@@ -53,6 +46,9 @@ export class CompletionItem {
readonly sortTextLow?: string;
readonly filterTextLow?: string;
// validation
readonly isInvalid: boolean = false;
// sorting, filtering
score: FuzzyScore = FuzzyScore.Default;
distance: number = 0;
@@ -73,6 +69,9 @@ export class CompletionItem {
// ensure lower-variants (perf)
this.labelLow = this.textLabel.toLowerCase();
// validate label
this.isInvalid = !this.textLabel;
this.sortTextLow = completion.sortText && completion.sortText.toLowerCase();
this.filterTextLow = completion.filterText && completion.filterText.toLowerCase();
@@ -81,43 +80,54 @@ export class CompletionItem {
this.editStart = new Position(completion.range.startLineNumber, completion.range.startColumn);
this.editInsertEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
this.editReplaceEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
// validate range
this.isInvalid = this.isInvalid
|| Range.spansMultipleLines(completion.range) || completion.range.startLineNumber !== position.lineNumber;
} else {
this.editStart = new Position(completion.range.insert.startLineNumber, completion.range.insert.startColumn);
this.editInsertEnd = new Position(completion.range.insert.endLineNumber, completion.range.insert.endColumn);
this.editReplaceEnd = new Position(completion.range.replace.endLineNumber, completion.range.replace.endColumn);
// validate ranges
this.isInvalid = this.isInvalid
|| Range.spansMultipleLines(completion.range.insert) || Range.spansMultipleLines(completion.range.replace)
|| completion.range.insert.startLineNumber !== position.lineNumber || completion.range.replace.startLineNumber !== position.lineNumber
|| Range.compareRangesUsingStarts(completion.range.insert, completion.range.replace) !== 0;
}
// create the suggestion resolver
const { resolveCompletionItem } = provider;
if (typeof resolveCompletionItem !== 'function') {
this.resolve = CompletionItem._defaultResolve;
this.isResolved = true;
} else {
let cached: Promise<void> | undefined;
this.resolve = (token) => {
if (!cached) {
cached = Promise.resolve(resolveCompletionItem.call(provider, model, Position.lift(position), completion, token)).then(value => {
Object.assign(completion, value);
this.isResolved = true;
}, err => {
if (isPromiseCanceledError(err)) {
// the IPC queue will reject the request with the
// cancellation error -> reset cached
cached = undefined;
}
});
token.onCancellationRequested(() => {
if (!this.isResolved) {
// cancellation after the request has been
// dispatched -> reset cache
cached = undefined;
}
});
}
return cached;
};
if (typeof provider.resolveCompletionItem !== 'function') {
this._resolveCache = Promise.resolve();
}
}
// resolving
get isResolved() {
return Boolean(this._resolveCache);
}
private _resolveCache?: Promise<void>;
async resolve(token: CancellationToken) {
if (!this._resolveCache) {
const sub = token.onCancellationRequested(() => {
this._resolveCache = undefined;
});
this._resolveCache = Promise.resolve(this.provider.resolveCompletionItem!(this.completion, token)).then(value => {
Object.assign(this.completion, value);
sub.dispose();
}, err => {
if (isPromiseCanceledError(err)) {
// the IPC queue will reject the request with the
// cancellation error -> reset cached
this._resolveCache = undefined;
}
});
}
return this._resolveCache;
}
}
export const enum SnippetSortOrder {
@@ -147,7 +157,7 @@ export function setSnippetSuggestSupport(support: modes.CompletionItemProvider):
return old;
}
export function provideSuggestionItems(
export async function provideSuggestionItems(
model: ITextModel,
position: Position,
options: CompletionOptions = CompletionOptions.default,
@@ -155,89 +165,86 @@ export function provideSuggestionItems(
token: CancellationToken = CancellationToken.None
): Promise<CompletionItem[]> {
const word = model.getWordAtPosition(position);
const defaultReplaceRange = word ? new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : Range.fromPositions(position);
const defaultInsertRange = defaultReplaceRange.setEndPosition(position.lineNumber, position.column);
// const wordUntil = model.getWordUntilPosition(position);
// const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
// const t1 = Date.now();
position = position.clone();
// get provider groups, always add snippet suggestion provider
const supports = modes.CompletionProviderRegistry.orderedGroups(model);
const word = model.getWordAtPosition(position);
const defaultReplaceRange = word ? new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : Range.fromPositions(position);
const defaultRange = { replace: defaultReplaceRange, insert: defaultReplaceRange.setEndPosition(position.lineNumber, position.column) };
// add snippets provider unless turned off
if (!options.kindFilter.has(modes.CompletionItemKind.Snippet) && _snippetSuggestSupport) {
supports.unshift([_snippetSuggestSupport]);
}
const allSuggestions: CompletionItem[] = [];
const result: CompletionItem[] = [];
const disposables = new DisposableStore();
let hasResult = false;
const onCompletionList = (provider: modes.CompletionItemProvider, container: modes.CompletionList | null | undefined) => {
if (!container) {
return;
}
for (let suggestion of container.suggestions || []) {
if (!options.kindFilter.has(suggestion.kind)) {
// fill in default range when missing
if (!suggestion.range) {
suggestion.range = defaultRange;
}
// fill in default sortText when missing
if (!suggestion.sortText) {
suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
}
result.push(new CompletionItem(position, suggestion, container, provider, model));
}
}
if (isDisposable(container)) {
disposables.add(container);
}
};
// ask for snippets in parallel to asking "real" providers. Only do something if configured to
// do so - no snippet filter, no special-providers-only request
const snippetCompletions = new Promise<void>((resolve, reject) => {
if (!_snippetSuggestSupport || options.kindFilter.has(modes.CompletionItemKind.Snippet)) {
resolve();
}
if (options.providerFilter.size > 0 && !options.providerFilter.has(_snippetSuggestSupport)) {
resolve();
}
Promise.resolve(_snippetSuggestSupport.provideCompletionItems(model, position, context, token)).then(list => {
onCompletionList(_snippetSuggestSupport, list);
resolve();
}, reject);
});
// add suggestions from contributed providers - providers are ordered in groups of
// equal score and once a group produces a result the process stops
const factory = supports.map(supports => () => {
// get provider groups, always add snippet suggestion provider
for (let providerGroup of modes.CompletionProviderRegistry.orderedGroups(model)) {
// for each support in the group ask for suggestions
return Promise.all(supports.map(provider => {
let lenBefore = result.length;
await Promise.all(providerGroup.map(async provider => {
if (options.providerFilter.size > 0 && !options.providerFilter.has(provider)) {
return undefined;
return;
}
try {
const list = await provider.provideCompletionItems(model, position, context, token);
onCompletionList(provider, list);
} catch (err) {
onUnexpectedExternalError(err);
}
return Promise.resolve(provider.provideCompletionItems(model, position, context, token)).then(container => {
const len = allSuggestions.length;
if (container) {
for (let suggestion of container.suggestions || []) {
if (!options.kindFilter.has(suggestion.kind)) {
// fill in default range when missing
if (!suggestion.range) {
suggestion.range = { insert: defaultInsertRange, replace: defaultReplaceRange };
}
// fill in default sortText when missing
if (!suggestion.sortText) {
suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
}
allSuggestions.push(new CompletionItem(position, suggestion, container, provider, model));
}
}
if (isDisposable(container)) {
disposables.add(container);
}
}
if (len !== allSuggestions.length && provider !== _snippetSuggestSupport) {
hasResult = true;
}
}, onUnexpectedExternalError);
}));
});
const result = first(factory, () => {
// stop on result or cancellation
return hasResult || token.isCancellationRequested;
}).then(() => {
if (token.isCancellationRequested) {
disposables.dispose();
return Promise.reject<any>(canceled());
if (lenBefore !== result.length || token.isCancellationRequested) {
break;
}
return allSuggestions.sort(getSuggestionComparator(options.snippetSortOrder));
});
}
// result.then(items => {
// console.log(model.getWordUntilPosition(position), items.map(item => `${item.suggestion.label}, type=${item.suggestion.type}, incomplete?${item.container.incomplete}, overwriteBefore=${item.suggestion.overwriteBefore}`));
// return items;
// }, err => {
// console.warn(model.getWordUntilPosition(position), err);
// });
await snippetCompletions;
return result;
if (token.isCancellationRequested) {
disposables.dispose();
return Promise.reject<any>(canceled());
}
// console.log(`${result.length} items AFTER ${Date.now() - t1}ms`);
return result.sort(getSuggestionComparator(options.snippetSortOrder));
}

View File

@@ -8,6 +8,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
import { onUnexpectedError } from 'vs/base/common/errors';
import { KeyCode, KeyMod, SimpleKeybinding } from 'vs/base/common/keyCodes';
import { dispose, IDisposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { StableEditorScrollState } from 'vs/editor/browser/core/editorState';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
@@ -273,6 +274,8 @@ export class SuggestController implements IEditorContribution {
// keep item in memory
this._memoryService.memorize(model, this.editor.getPosition(), item);
const scrollState = StableEditorScrollState.capture(this.editor);
if (Array.isArray(suggestion.additionalTextEdits)) {
this.editor.executeEdits('suggestController.additionalTextEdits', suggestion.additionalTextEdits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));
}
@@ -290,6 +293,8 @@ export class SuggestController implements IEditorContribution {
adjustWhitespace: !(suggestion.insertTextRules! & CompletionItemInsertTextRule.KeepWhitespace)
});
scrollState.restoreRelativeVerticalPositionOfCursor(this.editor);
if (!(flags & InsertFlags.NoAfterUndoStop)) {
this.editor.pushUndoStop();
}

View File

@@ -13,7 +13,7 @@ import * as strings from 'vs/base/common/strings';
import { Event, Emitter } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { addClass, append, $, hide, removeClass, show, toggleClass, getDomNodePagePosition, hasClass, addDisposableListener, addStandardDisposableListener, addClasses } from 'vs/base/browser/dom';
import { append, $, hide, show, getDomNodePagePosition, addDisposableListener, addStandardDisposableListener, addClasses } from 'vs/base/browser/dom';
import { IListVirtualDelegate, IListEvent, IListRenderer, IListMouseEvent, IListGestureEvent } from 'vs/base/browser/ui/list/list';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -139,7 +139,7 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
data.disposables = new DisposableStore();
data.root = container;
addClass(data.root, 'show-file-icons');
data.root.classList.add('show-file-icons');
data.icon = append(container, $('.icon'));
data.colorspan = append(data.icon, $('span.colorspan'));
@@ -245,16 +245,16 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
data.parametersLabel.textContent = '';
data.qualifierLabel.textContent = '';
data.detailsLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');
addClass(data.root, 'string-label');
data.root.classList.add('string-label');
} else {
data.parametersLabel.textContent = (suggestion.label.parameters || '').replace(/\n.*$/m, '');
data.qualifierLabel.textContent = (suggestion.label.qualifier || '').replace(/\n.*$/m, '');
data.detailsLabel.textContent = (suggestion.label.type || '').replace(/\n.*$/m, '');
removeClass(data.root, 'string-label');
data.root.classList.remove('string-label');
}
if (canExpandCompletionItem(element)) {
addClass(data.right, 'can-expand-details');
data.right.classList.add('can-expand-details');
show(data.readMore);
data.readMore.onmousedown = e => {
e.stopPropagation();
@@ -266,7 +266,7 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
this.widget.toggleDetails();
};
} else {
removeClass(data.right, 'can-expand-details');
data.right.classList.remove('can-expand-details');
hide(data.readMore);
data.readMore.onmousedown = null;
data.readMore.onclick = null;
@@ -363,15 +363,15 @@ class SuggestionDetails {
if (!explainMode && !canExpandCompletionItem(item)) {
this.type.textContent = '';
this.docs.textContent = '';
addClass(this.el, 'no-docs');
this.el.classList.add('no-docs');
return;
}
removeClass(this.el, 'no-docs');
this.el.classList.remove('no-docs');
if (typeof documentation === 'string') {
removeClass(this.docs, 'markdown-docs');
this.docs.classList.remove('markdown-docs');
this.docs.textContent = documentation;
} else {
addClass(this.docs, 'markdown-docs');
this.docs.classList.add('markdown-docs');
this.docs.innerHTML = '';
const renderedContents = this.markdownRenderer.render(documentation);
this.renderDisposeable = renderedContents;
@@ -554,7 +554,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement = append(this.element, $('.message'));
this.listElement = append(this.element, $('.tree'));
const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible);
const applyStatusBarStyle = () => this.element.classList.toggle('with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible);
applyStatusBarStyle();
this.statusBarElement = append(this.element, $('.suggest-status-bar'));
@@ -598,7 +598,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
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);
const applyIconStyle = () => this.element.classList.toggle('no-icons', !this.editor.getOption(EditorOption.suggest).showIcons);
applyIconStyle();
let renderer = instantiationService.createInstance(ItemRenderer, this, this.editor, kbToggleDetails);
@@ -797,7 +797,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
if (this.expandDocsSettingFromStorage()) {
this.showDetails(false);
} else {
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
}
this.editor.setAriaOptions({ activeDescendant: getAriaId(index) });
@@ -821,7 +821,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
const stateChanged = this.state !== state;
this.state = state;
toggleClass(this.element, 'frozen', state === State.Frozen);
this.element.classList.toggle('frozen', state === State.Frozen);
switch (state) {
case State.Hidden:
@@ -837,7 +837,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement.textContent = SuggestWidget.LOADING_MESSAGE;
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
this.show();
this.focusedItem = null;
break;
@@ -845,7 +845,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement.textContent = SuggestWidget.NO_SUGGESTIONS_MESSAGE;
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
this.show();
this.focusedItem = null;
break;
@@ -1072,8 +1072,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.ctxSuggestWidgetDetailsVisible.set(false);
this.updateExpandDocsSetting(false);
hide(this.details.element);
removeClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.remove('docs-side', 'doc-below');
this.editor.layoutContentWidget(this);
this.telemetryService.publicLog2('suggestWidget:collapseDetails');
} else {
@@ -1132,7 +1131,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.ctxSuggestWidgetVisible.set(true);
this.showTimeout.cancelAndSet(() => {
addClass(this.element, 'visible');
this.element.classList.add('visible');
this.onDidShowEmitter.fire(this);
}, 100);
}
@@ -1140,7 +1139,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private hide(): void {
this.ctxSuggestWidgetVisible.reset();
this.ctxSuggestWidgetMultipleSuggestions.reset();
removeClass(this.element, 'visible');
this.element.classList.remove('visible');
}
hideWidget(): void {
@@ -1225,15 +1224,15 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
if (widgetX < cursorX - this.listWidth) {
// Widget is too far to the left of cursor, swap list and docs
addClass(this.element, 'list-right');
this.element.classList.add('list-right');
} else {
removeClass(this.element, 'list-right');
this.element.classList.remove('list-right');
}
// Compare top of the cursor (cursorY - lineheight) with widgetTop to determine if
// margin-top needs to be applied on list to make it appear right above the cursor
// Cannot compare cursorY directly as it may be a few decimals off due to zoooming
if (hasClass(this.element, 'docs-side')
if (this.element.classList.contains('docs-side')
&& cursorY - lineHeight > widgetY
&& this.details.element.offsetHeight > this.listElement.offsetHeight) {
@@ -1248,18 +1247,17 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
*/
private expandSideOrBelow() {
if (!canExpandCompletionItem(this.focusedItem) && this.firstFocusInCurrentList) {
removeClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.remove('docs-side', 'docs-below');
return;
}
let matches = this.element.style.maxWidth!.match(/(\d+)px/);
if (!matches || Number(matches[1]) < this.maxWidgetWidth) {
addClass(this.element, 'docs-below');
removeClass(this.element, 'docs-side');
this.element.classList.add('docs-below');
this.element.classList.remove('docs-side');
} else if (canExpandCompletionItem(this.focusedItem)) {
addClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.add('docs-side');
this.element.classList.remove('docs-below');
}
}

View File

@@ -757,7 +757,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
dispose() { disposeB += 1; }
};
},
resolveCompletionItem(doc, pos, item) {
resolveCompletionItem(item) {
return item;
},
}));

View File

@@ -214,13 +214,13 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
create(): void {
dom.addClass(this.domNode, 'zone-widget');
this.domNode.classList.add('zone-widget');
if (this.options.className) {
dom.addClass(this.domNode, this.options.className);
this.domNode.classList.add(this.options.className);
}
this.container = document.createElement('div');
dom.addClass(this.container, 'zone-widget-container');
this.container.classList.add('zone-widget-container');
this.domNode.appendChild(this.container);
if (this.options.showArrow) {
this._arrow = new Arrow(this.editor);