mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-20 12:00:24 -04:00
Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)
This commit is contained in:
@@ -17,11 +17,15 @@ export class MoveCaretCommand implements ICommand {
|
||||
private _cutEndIndex: number;
|
||||
private _moved: boolean;
|
||||
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
|
||||
constructor(selection: Selection, isMovingLeft: boolean) {
|
||||
this._selection = selection;
|
||||
this._isMovingLeft = isMovingLeft;
|
||||
this._cutStartIndex = -1;
|
||||
this._cutEndIndex = -1;
|
||||
this._moved = false;
|
||||
this._selectionId = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {
|
||||
@@ -64,7 +68,7 @@ export class MoveCaretCommand implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
let result = helper.getTrackedSelection(this._selectionId);
|
||||
let result = helper.getTrackedSelection(this._selectionId!);
|
||||
if (this._moved) {
|
||||
result = result.setStartPosition(result.startLineNumber, this._cutStartIndex);
|
||||
result = result.setEndPosition(result.startLineNumber, this._cutEndIndex);
|
||||
|
||||
@@ -117,8 +117,8 @@ function getCodeActionProviders(
|
||||
}
|
||||
|
||||
registerLanguageCommand('_executeCodeActionProvider', async function (accessor, args): Promise<ReadonlyArray<CodeAction>> {
|
||||
const { resource, range, kind } = args;
|
||||
if (!(resource instanceof URI) || !Range.isIRange(range)) {
|
||||
const { resource, rangeOrSelection, kind } = args;
|
||||
if (!(resource instanceof URI)) {
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
@@ -127,9 +127,19 @@ registerLanguageCommand('_executeCodeActionProvider', async function (accessor,
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const validatedRangeOrSelection = Selection.isISelection(rangeOrSelection)
|
||||
? Selection.liftSelection(rangeOrSelection)
|
||||
: Range.isIRange(rangeOrSelection)
|
||||
? model.validateRange(rangeOrSelection)
|
||||
: undefined;
|
||||
|
||||
if (!validatedRangeOrSelection) {
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const codeActionSet = await getCodeActions(
|
||||
model,
|
||||
model.validateRange(range),
|
||||
validatedRangeOrSelection,
|
||||
{ type: 'manual', filter: { includeSourceActions: true, kind: kind && kind.value ? new CodeActionKind(kind.value) : undefined } },
|
||||
CancellationToken.None);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ export class CodeActionWidget extends Disposable {
|
||||
private readonly _delegate: CodeActionWidgetDelegate,
|
||||
) {
|
||||
super();
|
||||
this._visible = false;
|
||||
}
|
||||
|
||||
public async show(codeActions: CodeActionSet, at?: IAnchor | IPosition): Promise<void> {
|
||||
|
||||
@@ -59,8 +59,8 @@ suite('CodeAction', () => {
|
||||
command: {
|
||||
abc: {
|
||||
command: new class implements modes.Command {
|
||||
id: '1';
|
||||
title: 'abc';
|
||||
id!: '1';
|
||||
title!: 'abc';
|
||||
},
|
||||
title: 'Extract to inner function in function "test"'
|
||||
}
|
||||
@@ -69,7 +69,7 @@ suite('CodeAction', () => {
|
||||
bcd: {
|
||||
diagnostics: <IMarkerData[]>[],
|
||||
edit: new class implements modes.WorkspaceEdit {
|
||||
edits: modes.ResourceTextEdit[];
|
||||
edits!: modes.ResourceTextEdit[];
|
||||
},
|
||||
title: 'abc'
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
private _currentCodeLensModel: CodeLensModel | undefined;
|
||||
private _modelChangeCounter: number = 0;
|
||||
private _currentResolveCodeLensSymbolsPromise: CancelablePromise<any> | undefined;
|
||||
private _detectVisibleLenses: RunOnceScheduler;
|
||||
private _detectVisibleLenses!: RunOnceScheduler;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: editorBrowser.ICodeEditor,
|
||||
|
||||
@@ -60,7 +60,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
||||
private readonly _editor: editorBrowser.ICodeEditor;
|
||||
private readonly _commands = new Map<string, Command>();
|
||||
|
||||
private _widgetPosition: editorBrowser.IContentWidgetPosition;
|
||||
private _widgetPosition?: editorBrowser.IContentWidgetPosition;
|
||||
|
||||
constructor(
|
||||
editor: editorBrowser.ICodeEditor,
|
||||
@@ -147,8 +147,8 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
||||
};
|
||||
}
|
||||
|
||||
getPosition(): editorBrowser.IContentWidgetPosition {
|
||||
return this._widgetPosition;
|
||||
getPosition(): editorBrowser.IContentWidgetPosition | null {
|
||||
return this._widgetPosition || null;
|
||||
}
|
||||
|
||||
isVisible(): boolean {
|
||||
@@ -192,9 +192,9 @@ export class CodeLensHelper {
|
||||
export class CodeLensWidget {
|
||||
|
||||
private readonly _editor: editorBrowser.ICodeEditor;
|
||||
private readonly _viewZone: CodeLensViewZone;
|
||||
private readonly _viewZoneId: number;
|
||||
private readonly _contentWidget: CodeLensContentWidget;
|
||||
private readonly _viewZone!: CodeLensViewZone;
|
||||
private readonly _viewZoneId!: number;
|
||||
private readonly _contentWidget!: CodeLensContentWidget;
|
||||
private _decorationIds: string[];
|
||||
private _data: CodeLensItem[];
|
||||
|
||||
|
||||
@@ -123,8 +123,8 @@ class SaturationBox extends Disposable {
|
||||
private readonly domNode: HTMLElement;
|
||||
private readonly selection: HTMLElement;
|
||||
private readonly canvas: HTMLCanvasElement;
|
||||
private width: number;
|
||||
private height: number;
|
||||
private width!: number;
|
||||
private height!: number;
|
||||
|
||||
private monitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData> | null;
|
||||
private _onDidChange = new Emitter<{ s: number, v: number }>();
|
||||
@@ -235,7 +235,7 @@ abstract class Strip extends Disposable {
|
||||
protected domNode: HTMLElement;
|
||||
protected overlay: HTMLElement;
|
||||
protected slider: HTMLElement;
|
||||
private height: number;
|
||||
private height!: number;
|
||||
|
||||
private _onDidChange = new Emitter<number>();
|
||||
readonly onDidChange: Event<number> = this._onDidChange.event;
|
||||
|
||||
@@ -49,7 +49,7 @@ export const enum Type {
|
||||
export class LineCommentCommand implements editorCommon.ICommand {
|
||||
|
||||
private readonly _selection: Selection;
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
private _deltaColumn: number;
|
||||
private _moveEndPositionDown: boolean;
|
||||
private readonly _tabSize: number;
|
||||
@@ -57,9 +57,11 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
||||
|
||||
constructor(selection: Selection, tabSize: number, type: Type) {
|
||||
this._selection = selection;
|
||||
this._selectionId = null;
|
||||
this._tabSize = tabSize;
|
||||
this._type = type;
|
||||
this._deltaColumn = 0;
|
||||
this._moveEndPositionDown = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,7 +325,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: editorCommon.ICursorStateComputerData): Selection {
|
||||
let result = helper.getTrackedSelection(this._selectionId);
|
||||
let result = helper.getTrackedSelection(this._selectionId!);
|
||||
|
||||
if (this._moveEndPositionDown) {
|
||||
result = result.setEndPosition(result.endLineNumber + 1, 1);
|
||||
|
||||
@@ -14,13 +14,14 @@ export class DragAndDropCommand implements editorCommon.ICommand {
|
||||
|
||||
private readonly selection: Selection;
|
||||
private readonly targetPosition: Position;
|
||||
private targetSelection: Selection;
|
||||
private targetSelection: Selection | null;
|
||||
private readonly copy: boolean;
|
||||
|
||||
constructor(selection: Selection, targetPosition: Position, copy: boolean) {
|
||||
this.selection = selection;
|
||||
this.targetPosition = targetPosition;
|
||||
this.copy = copy;
|
||||
this.targetSelection = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: editorCommon.IEditOperationBuilder): void {
|
||||
@@ -102,6 +103,6 @@ export class DragAndDropCommand implements editorCommon.ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: editorCommon.ICursorStateComputerData): Selection {
|
||||
return this.targetSelection;
|
||||
return this.targetSelection!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,16 +45,19 @@ export class OutlineIdentityProvider implements IIdentityProvider<OutlineItem> {
|
||||
|
||||
export class OutlineGroupTemplate {
|
||||
static id = 'OutlineGroupTemplate';
|
||||
|
||||
labelContainer: HTMLElement;
|
||||
label: HighlightedLabel;
|
||||
constructor(
|
||||
readonly labelContainer: HTMLElement,
|
||||
readonly label: HighlightedLabel,
|
||||
) { }
|
||||
}
|
||||
|
||||
export class OutlineElementTemplate {
|
||||
static id = 'OutlineElementTemplate';
|
||||
container: HTMLElement;
|
||||
iconLabel: IconLabel;
|
||||
decoration: HTMLElement;
|
||||
constructor(
|
||||
readonly container: HTMLElement,
|
||||
readonly iconLabel: IconLabel,
|
||||
readonly decoration: HTMLElement,
|
||||
) { }
|
||||
}
|
||||
|
||||
export class OutlineVirtualDelegate implements IListVirtualDelegate<OutlineItem> {
|
||||
@@ -80,7 +83,7 @@ export class OutlineGroupRenderer implements ITreeRenderer<OutlineGroup, FuzzySc
|
||||
const labelContainer = dom.$('.outline-element-label');
|
||||
dom.addClass(container, 'outline-element');
|
||||
dom.append(container, labelContainer);
|
||||
return { labelContainer, label: new HighlightedLabel(labelContainer, true) };
|
||||
return new OutlineGroupTemplate(labelContainer, new HighlightedLabel(labelContainer, true));
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<OutlineGroup, FuzzyScore>, index: number, template: OutlineGroupTemplate): void {
|
||||
@@ -109,7 +112,7 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
|
||||
const iconLabel = new IconLabel(container, { supportHighlights: true });
|
||||
const decoration = dom.$('.outline-element-decoration');
|
||||
container.appendChild(decoration);
|
||||
return { container, iconLabel, decoration };
|
||||
return new OutlineElementTemplate(container, iconLabel, decoration);
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<OutlineElement, FuzzyScore>, index: number, template: OutlineElementTemplate): void {
|
||||
|
||||
@@ -374,8 +374,8 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
||||
|
||||
export class FindController extends CommonFindController implements IFindController {
|
||||
|
||||
private _widget: FindWidget;
|
||||
private _findOptionsWidget: FindOptionsWidget;
|
||||
private _widget: FindWidget | null;
|
||||
private _findOptionsWidget: FindOptionsWidget | null;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@@ -387,6 +387,8 @@ export class FindController extends CommonFindController implements IFindControl
|
||||
@optional(IClipboardService) clipboardService: IClipboardService
|
||||
) {
|
||||
super(editor, _contextKeyService, storageService, clipboardService);
|
||||
this._widget = null;
|
||||
this._findOptionsWidget = null;
|
||||
}
|
||||
|
||||
protected _start(opts: IFindStartOptions): void {
|
||||
@@ -394,7 +396,7 @@ export class FindController extends CommonFindController implements IFindControl
|
||||
this._createFindWidget();
|
||||
}
|
||||
|
||||
if (!this._widget.getPosition() && this._editor.getConfiguration().contribInfo.find.autoFindInSelection) {
|
||||
if (!this._widget!.getPosition() && this._editor.getConfiguration().contribInfo.find.autoFindInSelection) {
|
||||
// not visible yet so we need to set search scope if `editor.find.autoFindInSelection` is `true`
|
||||
opts.updateSearchScope = true;
|
||||
}
|
||||
@@ -402,9 +404,9 @@ export class FindController extends CommonFindController implements IFindControl
|
||||
super._start(opts);
|
||||
|
||||
if (opts.shouldFocus === FindStartFocusAction.FocusReplaceInput) {
|
||||
this._widget.focusReplaceInput();
|
||||
this._widget!.focusReplaceInput();
|
||||
} else if (opts.shouldFocus === FindStartFocusAction.FocusFindInput) {
|
||||
this._widget.focusFindInput();
|
||||
this._widget!.focusFindInput();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,9 +415,9 @@ export class FindController extends CommonFindController implements IFindControl
|
||||
this._createFindWidget();
|
||||
}
|
||||
if (this._state.isRevealed) {
|
||||
this._widget.highlightFindOptions();
|
||||
this._widget!.highlightFindOptions();
|
||||
} else {
|
||||
this._findOptionsWidget.highlightFindOptions();
|
||||
this._findOptionsWidget!.highlightFindOptions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,19 +93,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
private readonly _keybindingService: IKeybindingService;
|
||||
private readonly _contextKeyService: IContextKeyService;
|
||||
|
||||
private _domNode: HTMLElement;
|
||||
private _findInput: FindInput;
|
||||
private _replaceInputBox: HistoryInputBox;
|
||||
private _domNode!: HTMLElement;
|
||||
private _findInput!: FindInput;
|
||||
private _replaceInputBox!: HistoryInputBox;
|
||||
|
||||
private _toggleReplaceBtn: SimpleButton;
|
||||
private _matchesCount: HTMLElement;
|
||||
private _prevBtn: SimpleButton;
|
||||
private _nextBtn: SimpleButton;
|
||||
private _toggleSelectionFind: SimpleCheckbox;
|
||||
private _closeBtn: SimpleButton;
|
||||
private _preserveCase: Checkbox;
|
||||
private _replaceBtn: SimpleButton;
|
||||
private _replaceAllBtn: SimpleButton;
|
||||
private _toggleReplaceBtn!: SimpleButton;
|
||||
private _matchesCount!: HTMLElement;
|
||||
private _prevBtn!: SimpleButton;
|
||||
private _nextBtn!: SimpleButton;
|
||||
private _toggleSelectionFind!: SimpleCheckbox;
|
||||
private _closeBtn!: SimpleButton;
|
||||
private _preserveCase!: Checkbox;
|
||||
private _replaceBtn!: SimpleButton;
|
||||
private _replaceAllBtn!: SimpleButton;
|
||||
|
||||
private _isVisible: boolean;
|
||||
private _isReplaceVisible: boolean;
|
||||
@@ -118,8 +118,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
private _viewZone?: FindWidgetViewZone;
|
||||
private _viewZoneId?: number;
|
||||
|
||||
private _resizeSash: Sash;
|
||||
private _resized: boolean;
|
||||
private _resizeSash!: Sash;
|
||||
private _resized!: boolean;
|
||||
private readonly _updateHistoryDelayer: Delayer<void>;
|
||||
|
||||
constructor(
|
||||
@@ -784,7 +784,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
return ` (${kb.getLabel()})`;
|
||||
}
|
||||
|
||||
private _buildFindPart(): HTMLElement {
|
||||
private _buildDomNode(): void {
|
||||
// Find input
|
||||
this._findInput = this._register(new ContextScopedFindInput(null, this._contextViewProvider, {
|
||||
width: FIND_INPUT_AREA_WIDTH,
|
||||
@@ -908,10 +908,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
|
||||
findPart.appendChild(this._closeBtn.domNode);
|
||||
|
||||
return findPart;
|
||||
}
|
||||
|
||||
private _buildReplacePart(): HTMLElement {
|
||||
// Replace input
|
||||
let replaceInput = document.createElement('div');
|
||||
replaceInput.className = 'replace-input';
|
||||
@@ -977,16 +973,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
replacePart.appendChild(this._replaceBtn.domNode);
|
||||
replacePart.appendChild(this._replaceAllBtn.domNode);
|
||||
|
||||
return replacePart;
|
||||
}
|
||||
|
||||
private _buildDomNode(): void {
|
||||
// Find part
|
||||
let findPart = this._buildFindPart();
|
||||
|
||||
// Replace part
|
||||
let replacePart = this._buildReplacePart();
|
||||
|
||||
// Toggle replace button
|
||||
this._toggleReplaceBtn = this._register(new SimpleButton({
|
||||
label: NLS_TOGGLE_REPLACE_MODE_BTN_LABEL,
|
||||
@@ -1014,10 +1000,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
this._domNode.appendChild(findPart);
|
||||
this._domNode.appendChild(replacePart);
|
||||
|
||||
this._buildSash();
|
||||
}
|
||||
|
||||
private _buildSash() {
|
||||
this._resizeSash = new Sash(this._domNode, this, { orientation: Orientation.VERTICAL });
|
||||
this._resized = false;
|
||||
let originalWidth = FIND_WIDGET_INITIAL_WIDTH;
|
||||
|
||||
@@ -16,7 +16,7 @@ interface IEditOperation {
|
||||
export class ReplaceAllCommand implements editorCommon.ICommand {
|
||||
|
||||
private readonly _editorSelection: Selection;
|
||||
private _trackedEditorSelectionId: string;
|
||||
private _trackedEditorSelectionId: string | null;
|
||||
private readonly _ranges: Range[];
|
||||
private readonly _replaceStrings: string[];
|
||||
|
||||
@@ -24,6 +24,7 @@ export class ReplaceAllCommand implements editorCommon.ICommand {
|
||||
this._editorSelection = editorSelection;
|
||||
this._ranges = ranges;
|
||||
this._replaceStrings = replaceStrings;
|
||||
this._trackedEditorSelectionId = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: editorCommon.IEditOperationBuilder): void {
|
||||
@@ -66,6 +67,6 @@ export class ReplaceAllCommand implements editorCommon.ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: editorCommon.ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this._trackedEditorSelectionId);
|
||||
return helper.getTrackedSelection(this._trackedEditorSelectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .simple-find-part-wrapper {
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 18px;
|
||||
width: 220px;
|
||||
max-width: calc(100% - 28px - 28px - 8px);
|
||||
pointer-events: none;
|
||||
padding: 0 10px 10px;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part {
|
||||
visibility: hidden; /* Use visibility to maintain flex layout while hidden otherwise interferes with transition */
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
top: -45px;
|
||||
display: flex;
|
||||
padding: 4px;
|
||||
align-items: center;
|
||||
pointer-events: all;
|
||||
transition: top 200ms linear;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part.visible-transition {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .monaco-findInput {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .button {
|
||||
min-width: 20px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
flex: initial;
|
||||
margin-left: 3px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .button.previous {
|
||||
background-image: url('images/chevron-previous-light.svg');
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .button.next {
|
||||
background-image: url('images/chevron-next-light.svg');
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .button.close-fw {
|
||||
background-image: url('images/close-light.svg');
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .simple-find-part .button.previous,
|
||||
.vs-dark .monaco-workbench .simple-find-part .button.previous {
|
||||
background-image: url('images/chevron-previous-dark.svg');
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .simple-find-part .button.next,
|
||||
.vs-dark .monaco-workbench .simple-find-part .button.next {
|
||||
background-image: url('images/chevron-next-dark.svg');
|
||||
}
|
||||
|
||||
.hc-black .monaco-workbench .simple-find-part .button.close-fw,
|
||||
.vs-dark .monaco-workbench .simple-find-part .button.close-fw {
|
||||
background-image: url('images/close-dark.svg');
|
||||
}
|
||||
|
||||
.monaco-workbench .simple-find-part .button.disabled {
|
||||
opacity: 0.3;
|
||||
cursor: default;
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./simpleFindWidget';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { FindInput, IFindInputStyles } from 'vs/base/browser/ui/findinput/findInput';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { SimpleButton } from 'vs/editor/contrib/find/findWidget';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { editorWidgetBackground, inputActiveOptionBorder, inputActiveOptionBackground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ITheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { ContextScopedFindInput } from 'vs/platform/browser/contextScopedHistoryWidget';
|
||||
|
||||
const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
|
||||
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
|
||||
const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous match");
|
||||
const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next match");
|
||||
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
|
||||
|
||||
export abstract class SimpleFindWidget extends Widget {
|
||||
private readonly _findInput: FindInput;
|
||||
private readonly _domNode: HTMLElement;
|
||||
private readonly _innerDomNode: HTMLElement;
|
||||
private _isVisible: boolean = false;
|
||||
private readonly _focusTracker: dom.IFocusTracker;
|
||||
private readonly _findInputFocusTracker: dom.IFocusTracker;
|
||||
private readonly _updateHistoryDelayer: Delayer<void>;
|
||||
private prevBtn: SimpleButton;
|
||||
private nextBtn: SimpleButton;
|
||||
private foundMatch: boolean;
|
||||
|
||||
constructor(
|
||||
@IContextViewService private readonly _contextViewService: IContextViewService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
private readonly _state: FindReplaceState = new FindReplaceState(),
|
||||
showOptionButtons?: boolean,
|
||||
private readonly _invertDefaultDirection: boolean = false
|
||||
) {
|
||||
super();
|
||||
|
||||
this._findInput = this._register(new ContextScopedFindInput(null, this._contextViewService, {
|
||||
label: NLS_FIND_INPUT_LABEL,
|
||||
placeholder: NLS_FIND_INPUT_PLACEHOLDER,
|
||||
validation: (value: string): InputBoxMessage | null => {
|
||||
if (value.length === 0 || !this._findInput.getRegex()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
/* tslint:disable-next-line:no-unused-expression */
|
||||
new RegExp(value);
|
||||
return null;
|
||||
} catch (e) {
|
||||
this.foundMatch = false;
|
||||
this._updateButtons();
|
||||
return { content: e.message };
|
||||
}
|
||||
}
|
||||
}, contextKeyService, showOptionButtons));
|
||||
|
||||
// Find History with update delayer
|
||||
this._updateHistoryDelayer = new Delayer<void>(500);
|
||||
|
||||
this.oninput(this._findInput.domNode, (e) => {
|
||||
this.foundMatch = this.onInputChanged();
|
||||
this._updateButtons();
|
||||
this._delayedUpdateHistory();
|
||||
});
|
||||
|
||||
this._findInput.setRegex(!!this._state.isRegex);
|
||||
this._findInput.setCaseSensitive(!!this._state.matchCase);
|
||||
this._findInput.setWholeWords(!!this._state.wholeWord);
|
||||
|
||||
this._register(this._findInput.onDidOptionChange(() => {
|
||||
this._state.change({
|
||||
isRegex: this._findInput.getRegex(),
|
||||
wholeWord: this._findInput.getWholeWords(),
|
||||
matchCase: this._findInput.getCaseSensitive()
|
||||
}, true);
|
||||
}));
|
||||
|
||||
this._register(this._state.onFindReplaceStateChange(() => {
|
||||
this._findInput.setRegex(this._state.isRegex);
|
||||
this._findInput.setWholeWords(this._state.wholeWord);
|
||||
this._findInput.setCaseSensitive(this._state.matchCase);
|
||||
}));
|
||||
|
||||
this._register(this._findInput.onKeyDown((e) => {
|
||||
if (e.equals(KeyCode.Enter)) {
|
||||
this.find(this._invertDefaultDirection);
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.equals(KeyMod.Shift | KeyCode.Enter)) {
|
||||
this.find(!this._invertDefaultDirection);
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
}));
|
||||
|
||||
this.prevBtn = this._register(new SimpleButton({
|
||||
label: NLS_PREVIOUS_MATCH_BTN_LABEL,
|
||||
className: 'previous',
|
||||
onTrigger: () => {
|
||||
this.find(true);
|
||||
}
|
||||
}));
|
||||
|
||||
this.nextBtn = this._register(new SimpleButton({
|
||||
label: NLS_NEXT_MATCH_BTN_LABEL,
|
||||
className: 'next',
|
||||
onTrigger: () => {
|
||||
this.find(false);
|
||||
}
|
||||
}));
|
||||
|
||||
const closeBtn = this._register(new SimpleButton({
|
||||
label: NLS_CLOSE_BTN_LABEL,
|
||||
className: 'close-fw',
|
||||
onTrigger: () => {
|
||||
this.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
this._innerDomNode = document.createElement('div');
|
||||
this._innerDomNode.classList.add('simple-find-part');
|
||||
this._innerDomNode.appendChild(this._findInput.domNode);
|
||||
this._innerDomNode.appendChild(this.prevBtn.domNode);
|
||||
this._innerDomNode.appendChild(this.nextBtn.domNode);
|
||||
this._innerDomNode.appendChild(closeBtn.domNode);
|
||||
|
||||
// _domNode wraps _innerDomNode, ensuring that
|
||||
this._domNode = document.createElement('div');
|
||||
this._domNode.classList.add('simple-find-part-wrapper');
|
||||
this._domNode.appendChild(this._innerDomNode);
|
||||
|
||||
this.onkeyup(this._innerDomNode, e => {
|
||||
if (e.equals(KeyCode.Escape)) {
|
||||
this.hide();
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
this._focusTracker = this._register(dom.trackFocus(this._innerDomNode));
|
||||
this._register(this._focusTracker.onDidFocus(this.onFocusTrackerFocus.bind(this)));
|
||||
this._register(this._focusTracker.onDidBlur(this.onFocusTrackerBlur.bind(this)));
|
||||
|
||||
this._findInputFocusTracker = this._register(dom.trackFocus(this._findInput.domNode));
|
||||
this._register(this._findInputFocusTracker.onDidFocus(this.onFindInputFocusTrackerFocus.bind(this)));
|
||||
this._register(this._findInputFocusTracker.onDidBlur(this.onFindInputFocusTrackerBlur.bind(this)));
|
||||
|
||||
this._register(dom.addDisposableListener(this._innerDomNode, 'click', (event) => {
|
||||
event.stopPropagation();
|
||||
}));
|
||||
}
|
||||
|
||||
protected abstract onInputChanged(): boolean;
|
||||
protected abstract find(previous: boolean): void;
|
||||
protected abstract onFocusTrackerFocus(): void;
|
||||
protected abstract onFocusTrackerBlur(): void;
|
||||
protected abstract onFindInputFocusTrackerFocus(): void;
|
||||
protected abstract onFindInputFocusTrackerBlur(): void;
|
||||
|
||||
protected get inputValue() {
|
||||
return this._findInput.getValue();
|
||||
}
|
||||
|
||||
public get focusTracker(): dom.IFocusTracker {
|
||||
return this._focusTracker;
|
||||
}
|
||||
|
||||
public updateTheme(theme: ITheme): void {
|
||||
const inputStyles: IFindInputStyles = {
|
||||
inputActiveOptionBorder: theme.getColor(inputActiveOptionBorder),
|
||||
inputActiveOptionBackground: theme.getColor(inputActiveOptionBackground),
|
||||
inputBackground: theme.getColor(inputBackground),
|
||||
inputForeground: theme.getColor(inputForeground),
|
||||
inputBorder: theme.getColor(inputBorder),
|
||||
inputValidationInfoBackground: theme.getColor(inputValidationInfoBackground),
|
||||
inputValidationInfoForeground: theme.getColor(inputValidationInfoForeground),
|
||||
inputValidationInfoBorder: theme.getColor(inputValidationInfoBorder),
|
||||
inputValidationWarningBackground: theme.getColor(inputValidationWarningBackground),
|
||||
inputValidationWarningForeground: theme.getColor(inputValidationWarningForeground),
|
||||
inputValidationWarningBorder: theme.getColor(inputValidationWarningBorder),
|
||||
inputValidationErrorBackground: theme.getColor(inputValidationErrorBackground),
|
||||
inputValidationErrorForeground: theme.getColor(inputValidationErrorForeground),
|
||||
inputValidationErrorBorder: theme.getColor(inputValidationErrorBorder)
|
||||
};
|
||||
this._findInput.style(inputStyles);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
|
||||
if (this._domNode && this._domNode.parentElement) {
|
||||
this._domNode.parentElement.removeChild(this._domNode);
|
||||
}
|
||||
}
|
||||
|
||||
public getDomNode() {
|
||||
return this._domNode;
|
||||
}
|
||||
|
||||
public reveal(initialInput?: string): void {
|
||||
if (initialInput) {
|
||||
this._findInput.setValue(initialInput);
|
||||
}
|
||||
|
||||
if (this._isVisible) {
|
||||
this._findInput.select();
|
||||
return;
|
||||
}
|
||||
|
||||
this._isVisible = true;
|
||||
this._updateButtons();
|
||||
|
||||
setTimeout(() => {
|
||||
dom.addClass(this._innerDomNode, 'visible');
|
||||
dom.addClass(this._innerDomNode, 'visible-transition');
|
||||
this._innerDomNode.setAttribute('aria-hidden', 'false');
|
||||
this._findInput.select();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public show(initialInput?: string): void {
|
||||
if (initialInput && !this._isVisible) {
|
||||
this._findInput.setValue(initialInput);
|
||||
}
|
||||
|
||||
this._isVisible = true;
|
||||
|
||||
setTimeout(() => {
|
||||
dom.addClass(this._innerDomNode, 'visible');
|
||||
dom.addClass(this._innerDomNode, 'visible-transition');
|
||||
this._innerDomNode.setAttribute('aria-hidden', 'false');
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public hide(): void {
|
||||
if (this._isVisible) {
|
||||
dom.removeClass(this._innerDomNode, 'visible-transition');
|
||||
this._innerDomNode.setAttribute('aria-hidden', 'true');
|
||||
// Need to delay toggling visibility until after Transition, then visibility hidden - removes from tabIndex list
|
||||
setTimeout(() => {
|
||||
this._isVisible = false;
|
||||
this._updateButtons();
|
||||
dom.removeClass(this._innerDomNode, 'visible');
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
protected _delayedUpdateHistory() {
|
||||
this._updateHistoryDelayer.trigger(this._updateHistory.bind(this));
|
||||
}
|
||||
|
||||
protected _updateHistory() {
|
||||
this._findInput.inputBox.addToHistory();
|
||||
}
|
||||
|
||||
protected _getRegexValue(): boolean {
|
||||
return this._findInput.getRegex();
|
||||
}
|
||||
|
||||
protected _getWholeWordValue(): boolean {
|
||||
return this._findInput.getWholeWords();
|
||||
}
|
||||
|
||||
protected _getCaseSensitiveValue(): boolean {
|
||||
return this._findInput.getCaseSensitive();
|
||||
}
|
||||
|
||||
private _updateButtons() {
|
||||
let hasInput = this.inputValue.length > 0;
|
||||
this.prevBtn.setEnabled(this._isVisible && hasInput && this.foundMatch);
|
||||
this.nextBtn.setEnabled(this._isVisible && hasInput && this.foundMatch);
|
||||
}
|
||||
}
|
||||
|
||||
// theming
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
const findWidgetBGColor = theme.getColor(editorWidgetBackground);
|
||||
if (findWidgetBGColor) {
|
||||
collector.addRule(`.monaco-workbench .simple-find-part { background-color: ${findWidgetBGColor} !important; }`);
|
||||
}
|
||||
|
||||
const widgetShadowColor = theme.getColor(widgetShadow);
|
||||
if (widgetShadowColor) {
|
||||
collector.addRule(`.monaco-workbench .simple-find-part { box-shadow: 0 2px 8px ${widgetShadowColor}; }`);
|
||||
}
|
||||
});
|
||||
@@ -24,7 +24,6 @@ export class TestFindController extends CommonFindController {
|
||||
|
||||
public hasFocus: boolean;
|
||||
public delayUpdateHistory: boolean = false;
|
||||
public delayedUpdateHistoryPromise: Promise<void>;
|
||||
|
||||
private _findInputFocused: IContextKey<boolean>;
|
||||
|
||||
@@ -37,6 +36,7 @@ export class TestFindController extends CommonFindController {
|
||||
super(editor, contextKeyService, storageService, clipboardService);
|
||||
this._findInputFocused = CONTEXT_FIND_INPUT_FOCUSED.bindTo(contextKeyService);
|
||||
this._updateHistoryDelayer = new Delayer<void>(50);
|
||||
this.hasFocus = false;
|
||||
}
|
||||
|
||||
protected _start(opts: IFindStartOptions): void {
|
||||
|
||||
@@ -79,6 +79,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
private cursorChangedScheduler: RunOnceScheduler | null;
|
||||
|
||||
private readonly localToDispose = this._register(new DisposableStore());
|
||||
private mouseDownInfo: { lineNumber: number, iconClicked: boolean } | null;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@@ -90,6 +91,15 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
this._autoHideFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls === 'mouseover';
|
||||
this._useFoldingProviders = this.editor.getConfiguration().contribInfo.foldingStrategy !== 'indentation';
|
||||
|
||||
this.foldingModel = null;
|
||||
this.hiddenRangeModel = null;
|
||||
this.rangeProvider = null;
|
||||
this.foldingRegionPromise = null;
|
||||
this.foldingStateMemento = null;
|
||||
this.foldingModelPromise = null;
|
||||
this.updateScheduler = null;
|
||||
this.cursorChangedScheduler = null;
|
||||
this.mouseDownInfo = null;
|
||||
|
||||
this.foldingDecorationProvider = new FoldingDecorationProvider(editor);
|
||||
this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls;
|
||||
@@ -331,8 +341,6 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
|
||||
}
|
||||
|
||||
private mouseDownInfo: { lineNumber: number, iconClicked: boolean } | null;
|
||||
|
||||
private onEditorMouseDown(e: IEditorMouseEvent): void {
|
||||
this.mouseDownInfo = null;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ export class FoldingRegions {
|
||||
this._endIndexes = endIndexes;
|
||||
this._collapseStates = new Uint32Array(Math.ceil(startIndexes.length / 32));
|
||||
this._types = types;
|
||||
this._parentsComputed = false;
|
||||
}
|
||||
|
||||
private ensureParentIndices() {
|
||||
@@ -186,4 +187,4 @@ export class FoldingRegion {
|
||||
hidesLine(lineNumber: number) {
|
||||
return this.startLineNumber < lineNumber && lineNumber <= this.endLineNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,18 +34,16 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC
|
||||
|
||||
private readonly editor: ICodeEditor;
|
||||
private readonly toUnhook = new DisposableStore();
|
||||
private decorations: string[];
|
||||
private currentWordUnderMouse: IWordAtPosition | null;
|
||||
private previousPromise: CancelablePromise<LocationLink[] | null> | null;
|
||||
private decorations: string[] = [];
|
||||
private currentWordUnderMouse: IWordAtPosition | null = null;
|
||||
private previousPromise: CancelablePromise<LocationLink[] | null> | null = null;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@ITextModelService private readonly textModelResolverService: ITextModelService,
|
||||
@IModeService private readonly modeService: IModeService
|
||||
) {
|
||||
this.decorations = [];
|
||||
this.editor = editor;
|
||||
this.previousPromise = null;
|
||||
|
||||
let linkGesture = new ClickLinkGesture(editor);
|
||||
this.toUnhook.add(linkGesture);
|
||||
|
||||
@@ -165,15 +165,15 @@ class MessageWidget {
|
||||
|
||||
export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
|
||||
private _parentContainer: HTMLElement;
|
||||
private _container: HTMLElement;
|
||||
private _icon: HTMLElement;
|
||||
private _message: MessageWidget;
|
||||
private _parentContainer!: HTMLElement;
|
||||
private _container!: HTMLElement;
|
||||
private _icon!: HTMLElement;
|
||||
private _message!: MessageWidget;
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private _severity: MarkerSeverity;
|
||||
private _backgroundColor?: Color;
|
||||
private _onDidSelectRelatedInformation = new Emitter<IRelatedInformation>();
|
||||
private _heightInPixel: number;
|
||||
private _heightInPixel!: number;
|
||||
|
||||
readonly onDidSelectRelatedInformation: Event<IRelatedInformation> = this._onDidSelectRelatedInformation.event;
|
||||
|
||||
@@ -228,7 +228,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
|
||||
protected _fillHead(container: HTMLElement): void {
|
||||
super._fillHead(container);
|
||||
this._actionbarWidget.push(this.actions, { label: false, icon: true });
|
||||
this._actionbarWidget!.push(this.actions, { label: false, icon: true });
|
||||
}
|
||||
|
||||
protected _fillTitleIcon(container: HTMLElement): void {
|
||||
|
||||
@@ -84,13 +84,14 @@
|
||||
|
||||
.monaco-editor-hover .hover-row.status-bar .actions {
|
||||
display: flex;
|
||||
padding: 0px 8px;
|
||||
}
|
||||
|
||||
.monaco-editor-hover .hover-row.status-bar .actions .action-container {
|
||||
margin: 0px 8px;
|
||||
margin-right: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-editor-hover .hover-row.status-bar .actions .action-container .action .icon {
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,27 +34,27 @@ export class ModesHoverController implements IEditorContribution {
|
||||
private readonly _toUnhook = new DisposableStore();
|
||||
private readonly _didChangeConfigurationHandler: IDisposable;
|
||||
|
||||
private _contentWidget: ModesContentHoverWidget;
|
||||
private _glyphWidget: ModesGlyphHoverWidget;
|
||||
private _contentWidget: ModesContentHoverWidget | null;
|
||||
private _glyphWidget: ModesGlyphHoverWidget | null;
|
||||
|
||||
get contentWidget(): ModesContentHoverWidget {
|
||||
if (!this._contentWidget) {
|
||||
this._createHoverWidget();
|
||||
this._createHoverWidgets();
|
||||
}
|
||||
return this._contentWidget;
|
||||
return this._contentWidget!;
|
||||
}
|
||||
|
||||
get glyphWidget(): ModesGlyphHoverWidget {
|
||||
if (!this._glyphWidget) {
|
||||
this._createHoverWidget();
|
||||
this._createHoverWidgets();
|
||||
}
|
||||
return this._glyphWidget;
|
||||
return this._glyphWidget!;
|
||||
}
|
||||
|
||||
private _isMouseDown: boolean;
|
||||
private _hoverClicked: boolean;
|
||||
private _isHoverEnabled: boolean;
|
||||
private _isHoverSticky: boolean;
|
||||
private _isHoverEnabled!: boolean;
|
||||
private _isHoverSticky!: boolean;
|
||||
|
||||
static get(editor: ICodeEditor): ModesHoverController {
|
||||
return editor.getContribution<ModesHoverController>(ModesHoverController.ID);
|
||||
@@ -69,6 +69,8 @@ export class ModesHoverController implements IEditorContribution {
|
||||
) {
|
||||
this._isMouseDown = false;
|
||||
this._hoverClicked = false;
|
||||
this._contentWidget = null;
|
||||
this._glyphWidget = null;
|
||||
|
||||
this._hookEvents();
|
||||
|
||||
@@ -196,15 +198,15 @@ export class ModesHoverController implements IEditorContribution {
|
||||
}
|
||||
|
||||
private _hideWidgets(): void {
|
||||
if (!this._contentWidget || (this._isMouseDown && this._hoverClicked && this._contentWidget.isColorPickerVisible())) {
|
||||
if (!this._glyphWidget || !this._contentWidget || (this._isMouseDown && this._hoverClicked && this._contentWidget.isColorPickerVisible())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._glyphWidget.hide();
|
||||
this._glyphWidget!.hide();
|
||||
this._contentWidget.hide();
|
||||
}
|
||||
|
||||
private _createHoverWidget() {
|
||||
private _createHoverWidgets() {
|
||||
this._contentWidget = new ModesContentHoverWidget(this._editor, this._markerDecorationsService, this._themeService, this._keybindingService, this._modeService, this._openerService);
|
||||
this._glyphWidget = new ModesGlyphHoverWidget(this._editor, this._modeService, this._openerService);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
this._id = id;
|
||||
this._editor = editor;
|
||||
this._isVisible = false;
|
||||
this._stoleFocus = false;
|
||||
|
||||
this._containerDomNode = document.createElement('div');
|
||||
this._containerDomNode.className = 'monaco-editor-hover hidden';
|
||||
@@ -72,6 +73,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
this._editor.addContentWidget(this);
|
||||
this._showAtPosition = null;
|
||||
this._showAtRange = null;
|
||||
this._stoleFocus = false;
|
||||
}
|
||||
|
||||
public getId(): string {
|
||||
|
||||
@@ -70,6 +70,7 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
|
||||
private readonly _markerDecorationsService: IMarkerDecorationsService
|
||||
) {
|
||||
this._editor = editor;
|
||||
this._result = [];
|
||||
}
|
||||
|
||||
setRange(range: Range): void {
|
||||
@@ -213,6 +214,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
this._computer = new ModesContentComputer(this._editor, markerDecorationsService);
|
||||
this._highlightDecorations = [];
|
||||
this._isChangingDecorations = false;
|
||||
this._shouldFocus = false;
|
||||
this._colorPicker = null;
|
||||
|
||||
this._hoverOperation = new HoverOperation(
|
||||
this._computer,
|
||||
|
||||
@@ -27,6 +27,7 @@ class MarginComputer implements IHoverComputer<IHoverMessage[]> {
|
||||
constructor(editor: ICodeEditor) {
|
||||
this._editor = editor;
|
||||
this._lineNumber = -1;
|
||||
this._result = [];
|
||||
}
|
||||
|
||||
public setLineNumber(lineNumber: number): void {
|
||||
@@ -100,6 +101,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
|
||||
) {
|
||||
super(ModesGlyphHoverWidget.ID, editor);
|
||||
|
||||
this._messages = [];
|
||||
this._lastLineNumber = -1;
|
||||
|
||||
this._markdownRenderer = this._register(new MarkdownRenderer(this._editor, modeService, openerService));
|
||||
|
||||
@@ -37,8 +37,8 @@ class InPlaceReplaceController implements IEditorContribution {
|
||||
private readonly editor: ICodeEditor;
|
||||
private readonly editorWorkerService: IEditorWorkerService;
|
||||
private decorationIds: string[] = [];
|
||||
private currentRequest: CancelablePromise<IInplaceReplaceSupportResult | null>;
|
||||
private decorationRemover: CancelablePromise<void>;
|
||||
private currentRequest?: CancelablePromise<IInplaceReplaceSupportResult | null>;
|
||||
private decorationRemover?: CancelablePromise<void>;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
|
||||
@@ -378,11 +378,12 @@ export class AutoIndentOnPasteCommand implements ICommand {
|
||||
private readonly _edits: { range: IRange; text: string; eol?: EndOfLineSequence; }[];
|
||||
|
||||
private readonly _initialSelection: Selection;
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
|
||||
constructor(edits: TextEdit[], initialSelection: Selection) {
|
||||
this._initialSelection = initialSelection;
|
||||
this._edits = [];
|
||||
this._selectionId = null;
|
||||
|
||||
for (let edit of edits) {
|
||||
if (edit.range && typeof edit.text === 'string') {
|
||||
@@ -415,7 +416,7 @@ export class AutoIndentOnPasteCommand implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this._selectionId);
|
||||
return helper.getTrackedSelection(this._selectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,7 +652,7 @@ function getIndentationEditOperations(model: ITextModel, builder: IEditOperation
|
||||
|
||||
export class IndentationToSpacesCommand implements ICommand {
|
||||
|
||||
private selectionId: string;
|
||||
private selectionId: string | null = null;
|
||||
|
||||
constructor(private readonly selection: Selection, private tabSize: number) { }
|
||||
|
||||
@@ -661,13 +662,13 @@ export class IndentationToSpacesCommand implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this.selectionId);
|
||||
return helper.getTrackedSelection(this.selectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
export class IndentationToTabsCommand implements ICommand {
|
||||
|
||||
private selectionId: string;
|
||||
private selectionId: string | null = null;
|
||||
|
||||
constructor(private readonly selection: Selection, private tabSize: number) { }
|
||||
|
||||
@@ -677,7 +678,7 @@ export class IndentationToTabsCommand implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this.selectionId);
|
||||
return helper.getTrackedSelection(this.selectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,4 +689,4 @@ registerEditorAction(IndentUsingTabs);
|
||||
registerEditorAction(IndentUsingSpaces);
|
||||
registerEditorAction(DetectIndentation);
|
||||
registerEditorAction(ReindentLinesAction);
|
||||
registerEditorAction(ReindentSelectedLinesAction);
|
||||
registerEditorAction(ReindentSelectedLinesAction);
|
||||
|
||||
@@ -14,13 +14,17 @@ export class CopyLinesCommand implements editorCommon.ICommand {
|
||||
private readonly _isCopyingDown: boolean;
|
||||
|
||||
private _selectionDirection: SelectionDirection;
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
private _startLineNumberDelta: number;
|
||||
private _endLineNumberDelta: number;
|
||||
|
||||
constructor(selection: Selection, isCopyingDown: boolean) {
|
||||
this._selection = selection;
|
||||
this._isCopyingDown = isCopyingDown;
|
||||
this._selectionDirection = SelectionDirection.LTR;
|
||||
this._selectionId = null;
|
||||
this._startLineNumberDelta = 0;
|
||||
this._endLineNumberDelta = 0;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: editorCommon.IEditOperationBuilder): void {
|
||||
@@ -58,7 +62,7 @@ export class CopyLinesCommand implements editorCommon.ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: editorCommon.ICursorStateComputerData): Selection {
|
||||
let result = helper.getTrackedSelection(this._selectionId);
|
||||
let result = helper.getTrackedSelection(this._selectionId!);
|
||||
|
||||
if (this._startLineNumberDelta !== 0 || this._endLineNumberDelta !== 0) {
|
||||
let startLineNumber = result.startLineNumber;
|
||||
|
||||
@@ -20,7 +20,7 @@ export class MoveLinesCommand implements ICommand {
|
||||
private readonly _isMovingDown: boolean;
|
||||
private readonly _autoIndent: boolean;
|
||||
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
private _moveEndPositionDown?: boolean;
|
||||
private _moveEndLineSelectionShrink: boolean;
|
||||
|
||||
@@ -28,6 +28,7 @@ export class MoveLinesCommand implements ICommand {
|
||||
this._selection = selection;
|
||||
this._isMovingDown = isMovingDown;
|
||||
this._autoIndent = autoIndent;
|
||||
this._selectionId = null;
|
||||
this._moveEndLineSelectionShrink = false;
|
||||
}
|
||||
|
||||
@@ -36,9 +37,11 @@ export class MoveLinesCommand implements ICommand {
|
||||
let modelLineCount = model.getLineCount();
|
||||
|
||||
if (this._isMovingDown && this._selection.endLineNumber === modelLineCount) {
|
||||
this._selectionId = builder.trackSelection(this._selection);
|
||||
return;
|
||||
}
|
||||
if (!this._isMovingDown && this._selection.startLineNumber === 1) {
|
||||
this._selectionId = builder.trackSelection(this._selection);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -328,7 +331,7 @@ export class MoveLinesCommand implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
let result = helper.getTrackedSelection(this._selectionId);
|
||||
let result = helper.getTrackedSelection(this._selectionId!);
|
||||
|
||||
if (this._moveEndPositionDown) {
|
||||
result = result.setEndPosition(result.endLineNumber + 1, 1);
|
||||
|
||||
@@ -12,12 +12,13 @@ import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/mod
|
||||
export class SortLinesCommand implements editorCommon.ICommand {
|
||||
|
||||
private readonly selection: Selection;
|
||||
private selectionId: string;
|
||||
private readonly descending: boolean;
|
||||
private selectionId: string | null;
|
||||
|
||||
constructor(selection: Selection, descending: boolean) {
|
||||
this.selection = selection;
|
||||
this.descending = descending;
|
||||
this.selectionId = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: editorCommon.IEditOperationBuilder): void {
|
||||
@@ -30,7 +31,7 @@ export class SortLinesCommand implements editorCommon.ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: editorCommon.ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this.selectionId);
|
||||
return helper.getTrackedSelection(this.selectionId!);
|
||||
}
|
||||
|
||||
public static canRun(model: ITextModel | null, selection: Selection, descending: boolean): boolean {
|
||||
|
||||
@@ -299,10 +299,12 @@ class LinkDetector implements editorCommon.IEditorContribution {
|
||||
return this.openerService.open(uri, { openToSide });
|
||||
|
||||
}, err => {
|
||||
const messageOrError =
|
||||
err instanceof Error ? (<Error>err).message : err;
|
||||
// different error cases
|
||||
if (err === 'invalid') {
|
||||
if (messageOrError === 'invalid') {
|
||||
this.notificationService.warn(nls.localize('invalid.url', 'Failed to open this link because it is not well-formed: {0}', link.url!.toString()));
|
||||
} else if (err === 'missing') {
|
||||
} else if (messageOrError === 'missing') {
|
||||
this.notificationService.warn(nls.localize('missing.url', 'Failed to open this link because its target is missing.'));
|
||||
} else {
|
||||
onUnexpectedError(err);
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .docs.empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .docs .markdown-docs {
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
@@ -206,8 +206,6 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
dom.append(this.docs, $('p', {}, documentation));
|
||||
}
|
||||
|
||||
dom.toggleClass(this.signature, 'has-docs', !!signature.documentation);
|
||||
|
||||
if (signature.documentation === undefined) { /** no op */ }
|
||||
else if (typeof signature.documentation === 'string') {
|
||||
dom.append(this.docs, $('p', {}, signature.documentation));
|
||||
@@ -218,6 +216,23 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
dom.append(this.docs, renderedContents.element);
|
||||
}
|
||||
|
||||
let hasDocs = false;
|
||||
if (activeParameter && typeof (activeParameter.documentation) === 'string' && activeParameter.documentation.length > 0) {
|
||||
hasDocs = true;
|
||||
}
|
||||
if (activeParameter && typeof (activeParameter.documentation) === 'object' && activeParameter.documentation.value.length > 0) {
|
||||
hasDocs = true;
|
||||
}
|
||||
if (typeof (signature.documentation) === 'string' && signature.documentation.length > 0) {
|
||||
hasDocs = true;
|
||||
}
|
||||
if (typeof (signature.documentation) === 'object' && signature.documentation.value.length > 0) {
|
||||
hasDocs = true;
|
||||
}
|
||||
|
||||
dom.toggleClass(this.signature, 'has-docs', hasDocs);
|
||||
dom.toggleClass(this.docs, 'empty', !hasDocs);
|
||||
|
||||
let currentOverload = String(hints.activeSignature + 1);
|
||||
|
||||
if (hints.signatures.length < 10) {
|
||||
|
||||
@@ -84,12 +84,12 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
|
||||
private _onDidClose = new Emitter<PeekViewWidget>();
|
||||
|
||||
protected _headElement: HTMLDivElement;
|
||||
protected _primaryHeading: HTMLElement;
|
||||
protected _secondaryHeading: HTMLElement;
|
||||
protected _metaHeading: HTMLElement;
|
||||
protected _actionbarWidget: ActionBar;
|
||||
protected _bodyElement: HTMLDivElement;
|
||||
protected _headElement?: HTMLDivElement;
|
||||
protected _primaryHeading?: HTMLElement;
|
||||
protected _secondaryHeading?: HTMLElement;
|
||||
protected _metaHeading?: HTMLElement;
|
||||
protected _actionbarWidget?: ActionBar;
|
||||
protected _bodyElement?: HTMLDivElement;
|
||||
|
||||
constructor(editor: ICodeEditor, options: IPeekViewOptions = {}) {
|
||||
super(editor, options);
|
||||
@@ -139,8 +139,8 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
protected _fillContainer(container: HTMLElement): void {
|
||||
this.setCssClass('peekview-widget');
|
||||
|
||||
this._headElement = dom.$('.head');
|
||||
this._bodyElement = dom.$('.body');
|
||||
this._headElement = dom.$<HTMLDivElement>('.head');
|
||||
this._bodyElement = dom.$<HTMLDivElement>('.body');
|
||||
|
||||
this._fillHead(this._headElement);
|
||||
this._fillBody(this._bodyElement);
|
||||
@@ -151,7 +151,7 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
|
||||
protected _fillHead(container: HTMLElement): void {
|
||||
const titleElement = dom.$('.peekview-title');
|
||||
dom.append(this._headElement, titleElement);
|
||||
dom.append(this._headElement!, titleElement);
|
||||
dom.addStandardDisposableListener(titleElement, 'click', event => this._onTitleClick(event));
|
||||
|
||||
this._fillTitleIcon(titleElement);
|
||||
@@ -161,7 +161,7 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
dom.append(titleElement, this._primaryHeading, this._secondaryHeading, this._metaHeading);
|
||||
|
||||
const actionsContainer = dom.$('.peekview-actions');
|
||||
dom.append(this._headElement, actionsContainer);
|
||||
dom.append(this._headElement!, actionsContainer);
|
||||
|
||||
const actionBarOptions = this._getActionBarOptions();
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, actionBarOptions);
|
||||
@@ -185,20 +185,24 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
}
|
||||
|
||||
public setTitle(primaryHeading: string, secondaryHeading?: string): void {
|
||||
this._primaryHeading.innerHTML = strings.escape(primaryHeading);
|
||||
this._primaryHeading.setAttribute('aria-label', primaryHeading);
|
||||
if (secondaryHeading) {
|
||||
this._secondaryHeading.innerHTML = strings.escape(secondaryHeading);
|
||||
} else {
|
||||
dom.clearNode(this._secondaryHeading);
|
||||
if (this._primaryHeading && this._secondaryHeading) {
|
||||
this._primaryHeading.innerHTML = strings.escape(primaryHeading);
|
||||
this._primaryHeading.setAttribute('aria-label', primaryHeading);
|
||||
if (secondaryHeading) {
|
||||
this._secondaryHeading.innerHTML = strings.escape(secondaryHeading);
|
||||
} else {
|
||||
dom.clearNode(this._secondaryHeading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setMetaTitle(value: string): void {
|
||||
if (value) {
|
||||
this._metaHeading.innerHTML = strings.escape(value);
|
||||
} else {
|
||||
dom.clearNode(this._metaHeading);
|
||||
if (this._metaHeading) {
|
||||
if (value) {
|
||||
this._metaHeading.innerHTML = strings.escape(value);
|
||||
} else {
|
||||
dom.clearNode(this._metaHeading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,11 +224,15 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
}
|
||||
|
||||
protected _doLayoutHead(heightInPixel: number, widthInPixel: number): void {
|
||||
this._headElement.style.height = `${heightInPixel}px`;
|
||||
this._headElement.style.lineHeight = this._headElement.style.height;
|
||||
if (this._headElement) {
|
||||
this._headElement.style.height = `${heightInPixel}px`;
|
||||
this._headElement.style.lineHeight = this._headElement.style.height;
|
||||
}
|
||||
}
|
||||
|
||||
protected _doLayoutBody(heightInPixel: number, widthInPixel: number): void {
|
||||
this._bodyElement.style.height = `${heightInPixel}px`;
|
||||
if (this._bodyElement) {
|
||||
this._bodyElement.style.height = `${heightInPixel}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
private readonly _editor: ICodeEditor;
|
||||
private _widget: ReferenceWidget | null;
|
||||
private _model: ReferencesModel | null;
|
||||
private _widget?: ReferenceWidget;
|
||||
private _model?: ReferencesModel;
|
||||
private _requestIdPool = 0;
|
||||
private _ignoreModelChangeEvent = false;
|
||||
|
||||
@@ -68,11 +68,11 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
dispose(this._disposables);
|
||||
if (this._widget) {
|
||||
dispose(this._widget);
|
||||
this._widget = null;
|
||||
this._widget = undefined;
|
||||
}
|
||||
if (this._model) {
|
||||
dispose(this._model);
|
||||
this._model = null;
|
||||
this._model = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
modelPromise.cancel();
|
||||
if (this._widget) {
|
||||
this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData), StorageScope.GLOBAL);
|
||||
this._widget = null;
|
||||
this._widget = undefined;
|
||||
}
|
||||
this.closeWidget();
|
||||
}));
|
||||
@@ -202,13 +202,13 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
public closeWidget(): void {
|
||||
if (this._widget) {
|
||||
dispose(this._widget);
|
||||
this._widget = null;
|
||||
this._widget = undefined;
|
||||
}
|
||||
this._referenceSearchVisible.reset();
|
||||
this._disposables.clear();
|
||||
if (this._model) {
|
||||
dispose(this._model);
|
||||
this._model = null;
|
||||
this._model = undefined;
|
||||
}
|
||||
this._editor.focus();
|
||||
this._requestIdPool += 1; // Cancel pending requests
|
||||
|
||||
@@ -89,7 +89,7 @@ export class FileReferences implements IDisposable {
|
||||
|
||||
private _children: OneReference[];
|
||||
private _preview?: FilePreview;
|
||||
private _resolved: boolean;
|
||||
private _resolved?: boolean;
|
||||
private _loadFailure: any;
|
||||
|
||||
constructor(private readonly _parent: ReferencesModel, private readonly _uri: URI) {
|
||||
|
||||
@@ -158,8 +158,8 @@ class DecorationsManager implements IDisposable {
|
||||
}
|
||||
|
||||
export class LayoutData {
|
||||
ratio: number;
|
||||
heightInLines: number;
|
||||
ratio: number = 0.7;
|
||||
heightInLines: number = 18;
|
||||
|
||||
static fromJSON(raw: string): LayoutData {
|
||||
let ratio: number | undefined;
|
||||
@@ -191,22 +191,21 @@ export const ctxReferenceWidgetSearchTreeFocused = new RawContextKey<boolean>('r
|
||||
*/
|
||||
export class ReferenceWidget extends PeekViewWidget {
|
||||
|
||||
private _model: ReferencesModel | undefined;
|
||||
private _decorationsManager: DecorationsManager;
|
||||
private _model?: ReferencesModel;
|
||||
private _decorationsManager?: DecorationsManager;
|
||||
|
||||
private readonly _disposeOnNewModel = new DisposableStore();
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private _onDidSelectReference = new Emitter<SelectionEvent>();
|
||||
|
||||
private _tree: WorkbenchAsyncDataTree<ReferencesModel | FileReferences, TreeElement, FuzzyScore>;
|
||||
private _treeContainer: HTMLElement;
|
||||
// private _sash: VSash;
|
||||
private _splitView: SplitView;
|
||||
private _preview: ICodeEditor;
|
||||
private _previewModelReference: IReference<ITextEditorModel>;
|
||||
private _previewNotAvailableMessage: TextModel;
|
||||
private _previewContainer: HTMLElement;
|
||||
private _messageContainer: HTMLElement;
|
||||
private _tree!: WorkbenchAsyncDataTree<ReferencesModel | FileReferences, TreeElement, FuzzyScore>;
|
||||
private _treeContainer!: HTMLElement;
|
||||
private _splitView!: SplitView;
|
||||
private _preview!: ICodeEditor;
|
||||
private _previewModelReference!: IReference<ITextEditorModel>;
|
||||
private _previewNotAvailableMessage!: TextModel;
|
||||
private _previewContainer!: HTMLElement;
|
||||
private _messageContainer!: HTMLElement;
|
||||
private _dim: dom.Dimension = { height: 0, width: 0 };
|
||||
|
||||
constructor(
|
||||
@@ -470,7 +469,7 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
}));
|
||||
|
||||
// make sure things are rendered
|
||||
dom.addClass(this.container, 'results-loaded');
|
||||
dom.addClass(this.container!, 'results-loaded');
|
||||
dom.show(this._treeContainer);
|
||||
dom.show(this._previewContainer);
|
||||
this._splitView.layout(this._dim.width);
|
||||
|
||||
@@ -19,10 +19,10 @@ export const CONTEXT_RENAME_INPUT_VISIBLE = new RawContextKey<boolean>('renameIn
|
||||
export class RenameInputField implements IContentWidget, IDisposable {
|
||||
|
||||
private _editor: ICodeEditor;
|
||||
private _position: Position;
|
||||
private _domNode: HTMLElement;
|
||||
private _inputField: HTMLInputElement;
|
||||
private _visible: boolean;
|
||||
private _position?: Position;
|
||||
private _domNode?: HTMLElement;
|
||||
private _inputField?: HTMLInputElement;
|
||||
private _visible?: boolean;
|
||||
private readonly _visibleContextKey: IContextKey<boolean>;
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
@@ -95,7 +95,7 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
this._inputField.style.borderStyle = border ? 'solid' : 'none';
|
||||
this._inputField.style.borderColor = border ? border.toString() : 'none';
|
||||
|
||||
this._domNode.style.boxShadow = widgetShadowColor ? ` 0 2px 8px ${widgetShadowColor}` : null;
|
||||
this._domNode!.style.boxShadow = widgetShadowColor ? ` 0 2px 8px ${widgetShadowColor}` : null;
|
||||
}
|
||||
|
||||
private updateFont(): void {
|
||||
@@ -111,7 +111,7 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
|
||||
public getPosition(): IContentWidgetPosition | null {
|
||||
return this._visible
|
||||
? { position: this._position, preference: [ContentWidgetPositionPreference.BELOW, ContentWidgetPositionPreference.ABOVE] }
|
||||
? { position: this._position!, preference: [ContentWidgetPositionPreference.BELOW, ContentWidgetPositionPreference.ABOVE] }
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -133,10 +133,10 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
public getInput(where: IRange, value: string, selectionStart: number, selectionEnd: number): Promise<string | boolean> {
|
||||
|
||||
this._position = new Position(where.startLineNumber, where.startColumn);
|
||||
this._inputField.value = value;
|
||||
this._inputField.setAttribute('selectionStart', selectionStart.toString());
|
||||
this._inputField.setAttribute('selectionEnd', selectionEnd.toString());
|
||||
this._inputField.size = Math.max((where.endColumn - where.startColumn) * 1.1, 20);
|
||||
this._inputField!.value = value;
|
||||
this._inputField!.setAttribute('selectionStart', selectionStart.toString());
|
||||
this._inputField!.setAttribute('selectionEnd', selectionEnd.toString());
|
||||
this._inputField!.size = Math.max((where.endColumn - where.startColumn) * 1.1, 20);
|
||||
|
||||
const disposeOnDone = new DisposableStore();
|
||||
const always = () => {
|
||||
@@ -154,7 +154,7 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
};
|
||||
|
||||
this._currentAcceptInput = () => {
|
||||
if (this._inputField.value.trim().length === 0 || this._inputField.value === value) {
|
||||
if (this._inputField!.value.trim().length === 0 || this._inputField!.value === value) {
|
||||
// empty or whitespace only or not changed
|
||||
this.cancelInput(true);
|
||||
return;
|
||||
@@ -162,7 +162,7 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
|
||||
this._currentAcceptInput = null;
|
||||
this._currentCancelInput = null;
|
||||
resolve(this._inputField.value);
|
||||
resolve(this._inputField!.value);
|
||||
};
|
||||
|
||||
let onCursorChanged = () => {
|
||||
@@ -187,16 +187,16 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
}
|
||||
|
||||
private _show(): void {
|
||||
this._editor.revealLineInCenterIfOutsideViewport(this._position.lineNumber, ScrollType.Smooth);
|
||||
this._editor.revealLineInCenterIfOutsideViewport(this._position!.lineNumber, ScrollType.Smooth);
|
||||
this._visible = true;
|
||||
this._visibleContextKey.set(true);
|
||||
this._editor.layoutContentWidget(this);
|
||||
|
||||
setTimeout(() => {
|
||||
this._inputField.focus();
|
||||
this._inputField.setSelectionRange(
|
||||
parseInt(this._inputField.getAttribute('selectionStart')!),
|
||||
parseInt(this._inputField.getAttribute('selectionEnd')!));
|
||||
this._inputField!.focus();
|
||||
this._inputField!.setSelectionRange(
|
||||
parseInt(this._inputField!.getAttribute('selectionStart')!),
|
||||
parseInt(this._inputField!.getAttribute('selectionEnd')!));
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ export class SnippetController2 implements IEditorContribution {
|
||||
|
||||
private _session?: SnippetSession;
|
||||
private _snippetListener = new DisposableStore();
|
||||
private _modelVersionId: number;
|
||||
private _modelVersionId: number = -1;
|
||||
private _currentChoice?: Choice;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -56,12 +56,8 @@ export class Scanner {
|
||||
|| (ch >= CharCode.A && ch <= CharCode.Z);
|
||||
}
|
||||
|
||||
value: string;
|
||||
pos: number;
|
||||
|
||||
constructor() {
|
||||
this.text('');
|
||||
}
|
||||
value: string = '';
|
||||
pos: number = 0;
|
||||
|
||||
text(value: string) {
|
||||
this.value = value;
|
||||
@@ -135,7 +131,7 @@ export abstract class Marker {
|
||||
|
||||
readonly _markerBrand: any;
|
||||
|
||||
public parent: Marker;
|
||||
public parent!: Marker;
|
||||
protected _children: Marker[] = [];
|
||||
|
||||
appendChild(child: Marker): this {
|
||||
@@ -219,7 +215,7 @@ export class Text extends Marker {
|
||||
}
|
||||
|
||||
export abstract class TransformableMarker extends Marker {
|
||||
public transform: Transform;
|
||||
public transform?: Transform;
|
||||
}
|
||||
|
||||
export class Placeholder extends TransformableMarker {
|
||||
@@ -314,7 +310,7 @@ export class Choice extends Marker {
|
||||
|
||||
export class Transform extends Marker {
|
||||
|
||||
regexp: RegExp;
|
||||
regexp: RegExp = new RegExp('');
|
||||
|
||||
resolve(value: string): string {
|
||||
const _this = this;
|
||||
@@ -590,8 +586,8 @@ export class SnippetParser {
|
||||
return value.replace(/\$|}|\\/g, '\\$&');
|
||||
}
|
||||
|
||||
private _scanner = new Scanner();
|
||||
private _token: Token;
|
||||
private _scanner: Scanner = new Scanner();
|
||||
private _token: Token = { type: TokenType.EOF, pos: 0, len: 0 };
|
||||
|
||||
text(value: string): string {
|
||||
return this.parse(value).toString();
|
||||
@@ -671,16 +667,24 @@ export class SnippetParser {
|
||||
if (this._token.type === TokenType.EOF) {
|
||||
return false;
|
||||
}
|
||||
let start = this._token;
|
||||
while (this._token.type !== type) {
|
||||
let res = '';
|
||||
let pos = this._token.pos;
|
||||
let prevToken = <Token>{ type: TokenType.EOF, pos: 0, len: 0 };
|
||||
|
||||
while (this._token.type !== type || prevToken.type === TokenType.Backslash) {
|
||||
if (this._token.type === type) {
|
||||
res += this._scanner.value.substring(pos, prevToken.pos);
|
||||
pos = this._token.pos;
|
||||
}
|
||||
prevToken = this._token;
|
||||
this._token = this._scanner.next();
|
||||
if (this._token.type === TokenType.EOF) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let value = this._scanner.value.substring(start.pos, this._token.pos);
|
||||
res += this._scanner.value.substring(pos, this._token.pos);
|
||||
this._token = this._scanner.next();
|
||||
return value;
|
||||
return res;
|
||||
}
|
||||
|
||||
private _parse(marker: Marker): boolean {
|
||||
|
||||
@@ -41,7 +41,7 @@ export class OneSnippet {
|
||||
private readonly _snippet: TextmateSnippet;
|
||||
private readonly _offset: number;
|
||||
|
||||
private _placeholderDecorations: Map<Placeholder, string>;
|
||||
private _placeholderDecorations?: Map<Placeholder, string>;
|
||||
private _placeholderGroups: Placeholder[][];
|
||||
_placeholderGroupsIdx: number;
|
||||
_nestingLevel: number = 1;
|
||||
@@ -92,7 +92,7 @@ export class OneSnippet {
|
||||
);
|
||||
const options = placeholder.isFinalTabstop ? OneSnippet._decor.inactiveFinal : OneSnippet._decor.inactive;
|
||||
const handle = accessor.addDecoration(range, options);
|
||||
this._placeholderDecorations.set(placeholder, handle);
|
||||
this._placeholderDecorations!.set(placeholder, handle);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -111,7 +111,7 @@ export class OneSnippet {
|
||||
for (const placeholder of this._placeholderGroups[this._placeholderGroupsIdx]) {
|
||||
// Check if the placeholder has a transformation
|
||||
if (placeholder.transform) {
|
||||
const id = this._placeholderDecorations.get(placeholder)!;
|
||||
const id = this._placeholderDecorations!.get(placeholder)!;
|
||||
const range = this._editor.getModel().getDecorationRange(id)!;
|
||||
const currentValue = this._editor.getModel().getValueInRange(range);
|
||||
|
||||
@@ -148,7 +148,7 @@ export class OneSnippet {
|
||||
// Special case #2: placeholders enclosing active placeholders
|
||||
const selections: Selection[] = [];
|
||||
for (const placeholder of this._placeholderGroups[this._placeholderGroupsIdx]) {
|
||||
const id = this._placeholderDecorations.get(placeholder)!;
|
||||
const id = this._placeholderDecorations!.get(placeholder)!;
|
||||
const range = this._editor.getModel().getDecorationRange(id)!;
|
||||
selections.push(new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn));
|
||||
|
||||
@@ -161,7 +161,7 @@ export class OneSnippet {
|
||||
activePlaceholders.add(placeholder);
|
||||
|
||||
for (const enclosingPlaceholder of this._snippet.enclosingPlaceholders(placeholder)) {
|
||||
const id = this._placeholderDecorations.get(enclosingPlaceholder)!;
|
||||
const id = this._placeholderDecorations!.get(enclosingPlaceholder)!;
|
||||
accessor.changeDecorationOptions(id, enclosingPlaceholder.isFinalTabstop ? OneSnippet._decor.activeFinal : OneSnippet._decor.active);
|
||||
activePlaceholders.add(enclosingPlaceholder);
|
||||
}
|
||||
@@ -169,7 +169,7 @@ export class OneSnippet {
|
||||
|
||||
// change stickness to never grow when typing at its edges
|
||||
// so that in-active tabstops never grow
|
||||
this._placeholderDecorations.forEach((id, placeholder) => {
|
||||
this._placeholderDecorations!.forEach((id, placeholder) => {
|
||||
if (!activePlaceholders.has(placeholder)) {
|
||||
accessor.changeDecorationOptions(id, placeholder.isFinalTabstop ? OneSnippet._decor.inactiveFinal : OneSnippet._decor.inactive);
|
||||
}
|
||||
@@ -188,7 +188,7 @@ export class OneSnippet {
|
||||
let marker: Marker | undefined = placeholder;
|
||||
while (marker) {
|
||||
if (marker instanceof Placeholder) {
|
||||
const id = this._placeholderDecorations.get(marker)!;
|
||||
const id = this._placeholderDecorations!.get(marker)!;
|
||||
const range = this._editor.getModel().getDecorationRange(id)!;
|
||||
if (range.isEmpty() && marker.toString().length > 0) {
|
||||
return true;
|
||||
@@ -227,7 +227,7 @@ export class OneSnippet {
|
||||
result.set(placeholder.index, ranges);
|
||||
}
|
||||
|
||||
const id = this._placeholderDecorations.get(placeholder)!;
|
||||
const id = this._placeholderDecorations!.get(placeholder)!;
|
||||
const range = this._editor.getModel().getDecorationRange(id);
|
||||
if (!range) {
|
||||
// one of the placeholder lost its decoration and
|
||||
@@ -278,9 +278,9 @@ export class OneSnippet {
|
||||
|
||||
// Remove the placeholder at which position are inserting
|
||||
// the snippet and also remove its decoration.
|
||||
const id = this._placeholderDecorations.get(placeholder)!;
|
||||
const id = this._placeholderDecorations!.get(placeholder)!;
|
||||
accessor.removeDecoration(id);
|
||||
this._placeholderDecorations.delete(placeholder);
|
||||
this._placeholderDecorations!.delete(placeholder);
|
||||
|
||||
// For each *new* placeholder we create decoration to monitor
|
||||
// how and if it grows/shrinks.
|
||||
@@ -292,7 +292,7 @@ export class OneSnippet {
|
||||
model.getPositionAt(nested._offset + placeholderOffset + placeholderLen)
|
||||
);
|
||||
const handle = accessor.addDecoration(range, OneSnippet._decor.inactive);
|
||||
this._placeholderDecorations.set(placeholder, handle);
|
||||
this._placeholderDecorations!.set(placeholder, handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ export class OneSnippet {
|
||||
public getEnclosingRange(): Range | undefined {
|
||||
let result: Range | undefined;
|
||||
const model = this._editor.getModel();
|
||||
this._placeholderDecorations.forEach((decorationId) => {
|
||||
this._placeholderDecorations!.forEach((decorationId) => {
|
||||
const placeholderRange = withNullAsUndefined(model.getDecorationRange(decorationId));
|
||||
if (!result) {
|
||||
result = placeholderRange;
|
||||
|
||||
@@ -418,7 +418,7 @@ suite('SnippetParser', () => {
|
||||
assert.ok(children[3] instanceof Placeholder);
|
||||
assert.equal(children[3].children.length, 0);
|
||||
assert.notEqual((<Placeholder>children[3]).transform, undefined);
|
||||
let transform = (<Placeholder>children[3]).transform;
|
||||
let transform = (<Placeholder>children[3]).transform!;
|
||||
assert.equal(transform.regexp, '/\\s:=(.*)/');
|
||||
assert.equal(transform.children.length, 2);
|
||||
assert.ok(transform.children[0] instanceof FormatString);
|
||||
@@ -754,4 +754,17 @@ suite('SnippetParser', () => {
|
||||
let snippet = new SnippetParser().parse('namespace ${TM_DIRECTORY/[\\/]/\\\\/g};');
|
||||
assertMarker(snippet, Text, Variable, Text);
|
||||
});
|
||||
|
||||
test('Snippet cannot escape closing bracket inside conditional insertion variable replacement #78883', function () {
|
||||
|
||||
let snippet = new SnippetParser().parse('${TM_DIRECTORY/(.+)/${1:+import { hello \\} from world}/}');
|
||||
let variable = <Variable>snippet.children[0];
|
||||
assert.equal(snippet.children.length, 1);
|
||||
assert.ok(variable instanceof Variable);
|
||||
assert.ok(variable.transform);
|
||||
assert.equal(variable.transform!.children.length, 1);
|
||||
assert.ok(variable.transform!.children[0] instanceof FormatString);
|
||||
assert.equal((<FormatString>variable.transform!.children[0]).ifValue, 'import { hello } from world');
|
||||
assert.equal((<FormatString>variable.transform!.children[0]).elseValue, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,8 +29,10 @@ export interface ICompletionStats {
|
||||
}
|
||||
|
||||
export class LineContext {
|
||||
leadingLineContent: string;
|
||||
characterCountDelta: number;
|
||||
constructor(
|
||||
readonly leadingLineContent: string,
|
||||
readonly characterCountDelta: number,
|
||||
) { }
|
||||
}
|
||||
|
||||
const enum Refilter {
|
||||
@@ -49,9 +51,9 @@ export class CompletionModel {
|
||||
|
||||
private _lineContext: LineContext;
|
||||
private _refilterKind: Refilter;
|
||||
private _filteredItems: StrictCompletionItem[];
|
||||
private _isIncomplete: Set<CompletionItemProvider>;
|
||||
private _stats: ICompletionStats;
|
||||
private _filteredItems?: StrictCompletionItem[];
|
||||
private _isIncomplete?: Set<CompletionItemProvider>;
|
||||
private _stats?: ICompletionStats;
|
||||
|
||||
constructor(
|
||||
items: CompletionItem[],
|
||||
@@ -89,12 +91,12 @@ export class CompletionModel {
|
||||
|
||||
get items(): CompletionItem[] {
|
||||
this._ensureCachedState();
|
||||
return this._filteredItems;
|
||||
return this._filteredItems!;
|
||||
}
|
||||
|
||||
get incomplete(): Set<CompletionItemProvider> {
|
||||
this._ensureCachedState();
|
||||
return this._isIncomplete;
|
||||
return this._isIncomplete!;
|
||||
}
|
||||
|
||||
adopt(except: Set<CompletionItemProvider>): CompletionItem[] {
|
||||
@@ -117,7 +119,7 @@ export class CompletionModel {
|
||||
|
||||
get stats(): ICompletionStats {
|
||||
this._ensureCachedState();
|
||||
return this._stats;
|
||||
return this._stats!;
|
||||
}
|
||||
|
||||
private _ensureCachedState(): void {
|
||||
@@ -136,7 +138,7 @@ export class CompletionModel {
|
||||
let wordLow = '';
|
||||
|
||||
// incrementally filter less
|
||||
const source = this._refilterKind === Refilter.All ? this._items : this._filteredItems;
|
||||
const source = this._refilterKind === Refilter.All ? this._items : this._filteredItems!;
|
||||
const target: StrictCompletionItem[] = [];
|
||||
|
||||
// picks a score function based on the number of
|
||||
|
||||
@@ -110,7 +110,9 @@
|
||||
|
||||
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .close {
|
||||
background-image: url('./close-light.svg');
|
||||
float: right;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@@ -251,7 +253,7 @@
|
||||
text-overflow: ellipsis;
|
||||
opacity: 0.7;
|
||||
word-break: break-all;
|
||||
margin: 0;
|
||||
margin: 0px 24px 0 0;
|
||||
padding: 4px 0 12px 5px;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ export const Context = {
|
||||
|
||||
export class CompletionItem {
|
||||
|
||||
_brand: 'ISuggestionItem';
|
||||
_brand!: 'ISuggestionItem';
|
||||
|
||||
readonly resolve: (token: CancellationToken) => Promise<void>;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export class SuggestAlternatives {
|
||||
|
||||
private readonly _ckOtherSuggestions: IContextKey<boolean>;
|
||||
|
||||
private _index: number;
|
||||
private _index: number = 0;
|
||||
private _model: CompletionModel | undefined;
|
||||
private _acceptNext: ((selected: ISelectedSuggestion) => any) | undefined;
|
||||
private _listener: IDisposable | undefined;
|
||||
|
||||
@@ -370,6 +370,10 @@ export class SuggestController implements IEditorContribution {
|
||||
this._widget.getValue().toggleDetails();
|
||||
}
|
||||
|
||||
toggleExplainMode(): void {
|
||||
this._widget.getValue().toggleExplainMode();
|
||||
}
|
||||
|
||||
toggleSuggestionFocus(): void {
|
||||
this._widget.getValue().toggleDetailsFocus();
|
||||
}
|
||||
@@ -521,6 +525,16 @@ registerEditorCommand(new SuggestCommand({
|
||||
}
|
||||
}));
|
||||
|
||||
registerEditorCommand(new SuggestCommand({
|
||||
id: 'toggleExplainMode',
|
||||
precondition: SuggestContext.Visible,
|
||||
handler: x => x.toggleExplainMode(),
|
||||
kbOpts: {
|
||||
weight: KeybindingWeight.EditorContrib,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_SLASH,
|
||||
}
|
||||
}));
|
||||
|
||||
registerEditorCommand(new SuggestCommand({
|
||||
id: 'toggleSuggestionFocus',
|
||||
precondition: SuggestContext.Visible,
|
||||
|
||||
@@ -22,10 +22,10 @@ export abstract class Memory {
|
||||
if (items.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
let topScore = items[0].score;
|
||||
let topScore = items[0].score[0];
|
||||
for (let i = 1; i < items.length; i++) {
|
||||
const { score, completion: suggestion } = items[i];
|
||||
if (score !== topScore) {
|
||||
if (score[0] !== topScore) {
|
||||
// stop when leaving the group of top matches
|
||||
break;
|
||||
}
|
||||
@@ -81,33 +81,42 @@ export class LRUMemory extends Memory {
|
||||
}
|
||||
|
||||
select(model: ITextModel, pos: IPosition, items: CompletionItem[]): number {
|
||||
// in order of completions, select the first
|
||||
// that has been used in the past
|
||||
let { word } = model.getWordUntilPosition(pos);
|
||||
if (word.length !== 0) {
|
||||
return super.select(model, pos, items);
|
||||
|
||||
if (items.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1);
|
||||
const lineSuffix = model.getLineContent(pos.lineNumber).substr(pos.column - 10, pos.column - 1);
|
||||
if (/\s$/.test(lineSuffix)) {
|
||||
return super.select(model, pos, items);
|
||||
}
|
||||
|
||||
let res = -1;
|
||||
let topScore = items[0].score[0];
|
||||
let indexPreselect = -1;
|
||||
let indexRecency = -1;
|
||||
let seq = -1;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const { completion: suggestion } = items[i];
|
||||
const key = `${model.getLanguageIdentifier().language}/${suggestion.label}`;
|
||||
const item = this._cache.get(key);
|
||||
if (item && item.touch > seq && item.type === suggestion.kind && item.insertText === suggestion.insertText) {
|
||||
if (items[i].score[0] !== topScore) {
|
||||
// consider only top items
|
||||
break;
|
||||
}
|
||||
const key = `${model.getLanguageIdentifier().language}/${items[i].completion.label}`;
|
||||
const item = this._cache.peek(key);
|
||||
if (item && item.touch > seq && item.type === items[i].completion.kind && item.insertText === items[i].completion.insertText) {
|
||||
seq = item.touch;
|
||||
res = i;
|
||||
indexRecency = i;
|
||||
}
|
||||
if (items[i].completion.preselect && indexPreselect === -1) {
|
||||
// stop when seeing an auto-select-item
|
||||
return indexPreselect = i;
|
||||
}
|
||||
}
|
||||
if (res === -1) {
|
||||
return super.select(model, pos, items);
|
||||
if (indexRecency !== -1) {
|
||||
return indexRecency;
|
||||
} else if (indexPreselect !== -1) {
|
||||
return indexPreselect;
|
||||
} else {
|
||||
return res;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,9 +213,9 @@ export class SuggestMemoryService extends Disposable implements ISuggestMemorySe
|
||||
private readonly _storagePrefix = 'suggest/memories';
|
||||
|
||||
private readonly _persistSoon: RunOnceScheduler;
|
||||
private _mode: MemMode;
|
||||
private _shareMem: boolean;
|
||||
private _strategy: Memory;
|
||||
private _mode!: MemMode;
|
||||
private _shareMem!: boolean;
|
||||
private _strategy!: Memory;
|
||||
|
||||
constructor(
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
|
||||
@@ -92,8 +92,8 @@ export const enum State {
|
||||
export class SuggestModel implements IDisposable {
|
||||
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private _quickSuggestDelay: number;
|
||||
private _triggerCharacterListener: IDisposable;
|
||||
private _quickSuggestDelay: number = 10;
|
||||
private _triggerCharacterListener?: IDisposable;
|
||||
private readonly _triggerQuickSuggest = new TimeoutTimer();
|
||||
private _state: State = State.Idle;
|
||||
|
||||
@@ -161,7 +161,8 @@ export class SuggestModel implements IDisposable {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger, this._triggerCharacterListener, this._triggerQuickSuggest]);
|
||||
dispose(this._triggerCharacterListener);
|
||||
dispose([this._onDidCancel, this._onDidSuggest, this._onDidTrigger, this._triggerQuickSuggest]);
|
||||
this._toDispose.dispose();
|
||||
this._completionDisposables.dispose();
|
||||
this.cancel();
|
||||
|
||||
@@ -38,8 +38,6 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { FileKind } from 'vs/platform/files/common/files';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
|
||||
const expandSuggestionDocsByDefault = false;
|
||||
|
||||
@@ -117,7 +115,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
|
||||
const text = append(container, $('.contents'));
|
||||
const main = append(text, $('.main'));
|
||||
|
||||
data.iconLabel = new IconLabel(main, { supportHighlights: true });
|
||||
data.iconLabel = new IconLabel(main, { supportHighlights: true, supportOcticons: true });
|
||||
data.disposables.add(data.iconLabel);
|
||||
|
||||
data.typeLabel = append(main, $('span.type-label'));
|
||||
@@ -231,17 +229,6 @@ const enum State {
|
||||
}
|
||||
|
||||
|
||||
let _explainMode = false;
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'suggest.toggleExplainMode',
|
||||
handler() {
|
||||
_explainMode = !_explainMode;
|
||||
},
|
||||
when: SuggestContext.Visible,
|
||||
weight: KeybindingWeight.EditorContrib,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.US_SLASH,
|
||||
});
|
||||
|
||||
class SuggestionDetails {
|
||||
|
||||
private el: HTMLElement;
|
||||
@@ -253,7 +240,7 @@ class SuggestionDetails {
|
||||
private docs: HTMLElement;
|
||||
private ariaLabel: string | null;
|
||||
private readonly disposables: DisposableStore;
|
||||
private renderDisposeable: IDisposable;
|
||||
private renderDisposeable?: IDisposable;
|
||||
private borderWidth: number = 1;
|
||||
|
||||
constructor(
|
||||
@@ -300,13 +287,13 @@ class SuggestionDetails {
|
||||
this.docs.textContent = '';
|
||||
}
|
||||
|
||||
renderItem(item: CompletionItem): void {
|
||||
renderItem(item: CompletionItem, explainMode: boolean): void {
|
||||
this.renderDisposeable = dispose(this.renderDisposeable);
|
||||
|
||||
let { documentation, detail } = item.completion;
|
||||
// --- documentation
|
||||
|
||||
if (_explainMode) {
|
||||
if (explainMode) {
|
||||
let md = '';
|
||||
md += `score: ${item.score[0]}${item.word ? `, compared '${item.completion.filterText && (item.completion.filterText + ' (filterText)') || item.completion.label}' with '${item.word}'` : ' (no prefix)'}\n`;
|
||||
md += `distance: ${item.distance}, see localityBonus-setting\n`;
|
||||
@@ -315,7 +302,7 @@ class SuggestionDetails {
|
||||
detail = `Provider: ${item.provider._debugDisplayName}`;
|
||||
}
|
||||
|
||||
if (!_explainMode && !canExpandCompletionItem(item)) {
|
||||
if (!explainMode && !canExpandCompletionItem(item)) {
|
||||
this.type.textContent = '';
|
||||
this.docs.textContent = '';
|
||||
addClass(this.el, 'no-docs');
|
||||
@@ -435,25 +422,24 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
readonly allowEditorOverflow = true;
|
||||
readonly suppressMouseDown = true;
|
||||
|
||||
private state: State | null;
|
||||
private isAuto: boolean;
|
||||
private state: State | null = null;
|
||||
private isAuto: boolean = false;
|
||||
private loadingTimeout: IDisposable = Disposable.None;
|
||||
private currentSuggestionDetails: CancelablePromise<void> | null;
|
||||
private currentSuggestionDetails: CancelablePromise<void> | null = null;
|
||||
private focusedItem: CompletionItem | null;
|
||||
private ignoreFocusEvents = false;
|
||||
private completionModel: CompletionModel | null;
|
||||
private ignoreFocusEvents: boolean = false;
|
||||
private completionModel: CompletionModel | null = null;
|
||||
|
||||
private element: HTMLElement;
|
||||
private messageElement: HTMLElement;
|
||||
private listElement: HTMLElement;
|
||||
private details: SuggestionDetails;
|
||||
private list: List<CompletionItem>;
|
||||
private listHeight: number;
|
||||
private listHeight?: number;
|
||||
|
||||
private readonly suggestWidgetVisible: IContextKey<boolean>;
|
||||
private readonly suggestWidgetMultipleSuggestions: IContextKey<boolean>;
|
||||
|
||||
private readonly editorBlurTimeout = new TimeoutTimer();
|
||||
private readonly showTimeout = new TimeoutTimer();
|
||||
private readonly toDispose = new DisposableStore();
|
||||
|
||||
@@ -470,13 +456,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
private readonly maxWidgetWidth = 660;
|
||||
private readonly listWidth = 330;
|
||||
private readonly storageService: IStorageService;
|
||||
private detailsFocusBorderColor: string;
|
||||
private detailsBorderColor: string;
|
||||
private detailsFocusBorderColor?: string;
|
||||
private detailsBorderColor?: string;
|
||||
|
||||
private firstFocusInCurrentList: boolean = false;
|
||||
|
||||
private preferDocPositionTop: boolean = false;
|
||||
private docsPositionPreviousWidgetY: number | null;
|
||||
private docsPositionPreviousWidgetY: number | null = null;
|
||||
private explainMode: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly editor: ICodeEditor,
|
||||
@@ -594,7 +581,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
}
|
||||
}
|
||||
|
||||
private _lastAriaAlertLabel: string | null;
|
||||
private _lastAriaAlertLabel: string | null = null;
|
||||
private _ariaAlert(newAriaAlertLabel: string | null): void {
|
||||
if (this._lastAriaAlertLabel === newAriaAlertLabel) {
|
||||
return;
|
||||
@@ -974,12 +961,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.expandSideOrBelow();
|
||||
|
||||
show(this.details.element);
|
||||
|
||||
this.details.element.style.maxHeight = this.maxWidgetHeight + 'px';
|
||||
|
||||
if (loading) {
|
||||
this.details.renderLoading();
|
||||
} else {
|
||||
this.details.renderItem(this.list.getFocusedElements()[0]);
|
||||
this.details.renderItem(this.list.getFocusedElements()[0], this.explainMode);
|
||||
}
|
||||
this.details.element.style.maxHeight = this.maxWidgetHeight + 'px';
|
||||
|
||||
// Reset margin-top that was set as Fix for #26416
|
||||
this.listElement.style.marginTop = '0px';
|
||||
@@ -992,6 +981,13 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.editor.focus();
|
||||
}
|
||||
|
||||
toggleExplainMode(): void {
|
||||
if (this.list.getFocusedElements()[0] && this.expandDocsSettingFromStorage()) {
|
||||
this.explainMode = !this.explainMode;
|
||||
this.showDetails(false);
|
||||
}
|
||||
}
|
||||
|
||||
private show(): void {
|
||||
const newHeight = this.updateListHeight();
|
||||
if (newHeight !== this.listHeight) {
|
||||
@@ -1162,7 +1158,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.list.dispose();
|
||||
this.toDispose.dispose();
|
||||
this.loadingTimeout.dispose();
|
||||
this.editorBlurTimeout.dispose();
|
||||
this.showTimeout.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,29 @@ suite('SuggestMemories', function () {
|
||||
]), 0);
|
||||
});
|
||||
|
||||
test('`"editor.suggestSelection": "recentlyUsed"` should be a little more sticky #78571', function () {
|
||||
|
||||
let item1 = createSuggestItem('gamma', 0);
|
||||
let item2 = createSuggestItem('game', 0);
|
||||
items = [item1, item2];
|
||||
|
||||
let mem = new LRUMemory();
|
||||
buffer.setValue(' foo.');
|
||||
mem.memorize(buffer, { lineNumber: 1, column: 1 }, item2);
|
||||
|
||||
assert.equal(mem.select(buffer, { lineNumber: 1, column: 2 }, items), 0); // leading whitespace -> ignore recent items
|
||||
|
||||
mem.memorize(buffer, { lineNumber: 1, column: 9 }, item2);
|
||||
assert.equal(mem.select(buffer, { lineNumber: 1, column: 9 }, items), 1); // foo.
|
||||
|
||||
buffer.setValue(' foo.g');
|
||||
assert.equal(mem.select(buffer, { lineNumber: 1, column: 10 }, items), 1); // foo.g, 'gamma' and 'game' have the same score
|
||||
|
||||
item1.score = [10, 0, 0];
|
||||
assert.equal(mem.select(buffer, { lineNumber: 1, column: 10 }, items), 0); // foo.g, 'gamma' has higher score
|
||||
|
||||
});
|
||||
|
||||
test('intellisense is not showing top options first #43429', function () {
|
||||
// ensure we don't memorize for whitespace prefixes
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export class WordContextKey extends Disposable {
|
||||
|
||||
private readonly _ckAtEnd: IContextKey<boolean>;
|
||||
|
||||
private _enabled: boolean;
|
||||
private _enabled: boolean = false;
|
||||
private _selectionListener?: IDisposable;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -469,6 +469,7 @@ class WordHighlighterContribution extends Disposable implements editorCommon.IEd
|
||||
|
||||
constructor(editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
|
||||
super();
|
||||
this.wordHighligher = null;
|
||||
const createWordHighlighterIfPossible = () => {
|
||||
if (editor.hasModel()) {
|
||||
this.wordHighligher = new WordHighlighter(editor, contextKeyService);
|
||||
|
||||
@@ -51,7 +51,7 @@ const WIDGET_ID = 'vs.editor.contrib.zoneWidget';
|
||||
export class ViewZoneDelegate implements IViewZone {
|
||||
|
||||
public domNode: HTMLElement;
|
||||
public id: number;
|
||||
public id: number = 0; // A valid zone id should be greater than 0
|
||||
public afterLineNumber: number;
|
||||
public afterColumn: number;
|
||||
public heightInLines: number;
|
||||
@@ -109,8 +109,8 @@ class Arrow {
|
||||
|
||||
private readonly _ruleName = Arrow._IdGenerator.nextId();
|
||||
private _decorations: string[] = [];
|
||||
private _color: string;
|
||||
private _height: number;
|
||||
private _color: string | null = null;
|
||||
private _height: number = -1;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor
|
||||
@@ -159,15 +159,15 @@ class Arrow {
|
||||
|
||||
export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
|
||||
private _arrow: Arrow;
|
||||
private _overlayWidget: OverlayWidgetDelegate | null;
|
||||
private _resizeSash: Sash;
|
||||
private _arrow: Arrow | null = null;
|
||||
private _overlayWidget: OverlayWidgetDelegate | null = null;
|
||||
private _resizeSash: Sash | null = null;
|
||||
private _positionMarkerId: string[] = [];
|
||||
|
||||
protected _viewZone: ViewZoneDelegate | null;
|
||||
protected _viewZone: ViewZoneDelegate | null = null;
|
||||
protected readonly _disposables = new DisposableStore();
|
||||
|
||||
public container: HTMLElement;
|
||||
public container: HTMLElement | null = null;
|
||||
public domNode: HTMLElement;
|
||||
public editor: ICodeEditor;
|
||||
public options: IOptions;
|
||||
@@ -273,12 +273,16 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
private _onViewZoneHeight(height: number): void {
|
||||
this.domNode.style.height = `${height}px`;
|
||||
|
||||
let containerHeight = height - this._decoratingElementsHeight();
|
||||
this.container.style.height = `${containerHeight}px`;
|
||||
const layoutInfo = this.editor.getLayoutInfo();
|
||||
this._doLayout(containerHeight, this._getWidth(layoutInfo));
|
||||
if (this.container) {
|
||||
let containerHeight = height - this._decoratingElementsHeight();
|
||||
this.container.style.height = `${containerHeight}px`;
|
||||
const layoutInfo = this.editor.getLayoutInfo();
|
||||
this._doLayout(containerHeight, this._getWidth(layoutInfo));
|
||||
}
|
||||
|
||||
this._resizeSash.layout();
|
||||
if (this._resizeSash) {
|
||||
this._resizeSash.layout();
|
||||
}
|
||||
}
|
||||
|
||||
public get position(): Position | undefined {
|
||||
@@ -373,7 +377,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
let frameThickness = 0;
|
||||
|
||||
// Render the arrow one 1/3 of an editor line height
|
||||
if (this.options.showArrow) {
|
||||
if (this._arrow && this.options.showArrow) {
|
||||
arrowHeight = Math.round(lineHeight / 3);
|
||||
this._arrow.height = arrowHeight;
|
||||
this._arrow.show(position);
|
||||
@@ -407,17 +411,19 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
this.editor.addOverlayWidget(this._overlayWidget);
|
||||
});
|
||||
|
||||
if (this.options.showFrame) {
|
||||
if (this.container && this.options.showFrame) {
|
||||
const width = this.options.frameWidth ? this.options.frameWidth : frameThickness;
|
||||
this.container.style.borderTopWidth = width + 'px';
|
||||
this.container.style.borderBottomWidth = width + 'px';
|
||||
}
|
||||
|
||||
let containerHeight = heightInLines * lineHeight - this._decoratingElementsHeight();
|
||||
this.container.style.top = arrowHeight + 'px';
|
||||
this.container.style.height = containerHeight + 'px';
|
||||
this.container.style.overflow = 'hidden';
|
||||
|
||||
if (this.container) {
|
||||
this.container.style.top = arrowHeight + 'px';
|
||||
this.container.style.height = containerHeight + 'px';
|
||||
this.container.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
this._doLayout(containerHeight, width);
|
||||
|
||||
@@ -438,6 +444,10 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
}
|
||||
|
||||
protected setCssClass(className: string, classToReplace?: string): void {
|
||||
if (!this.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (classToReplace) {
|
||||
this.container.classList.remove(classToReplace);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user