mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode bd0efff9e3f36d6b3e1045cee9887003af8034d7
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
};
|
||||
}));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -757,7 +757,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
|
||||
dispose() { disposeB += 1; }
|
||||
};
|
||||
},
|
||||
resolveCompletionItem(doc, pos, item) {
|
||||
resolveCompletionItem(item) {
|
||||
return item;
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user