Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)

This commit is contained in:
Anthony Dresser
2019-08-12 21:31:51 -07:00
committed by GitHub
parent 00250839fc
commit 7eba8c4c03
616 changed files with 9472 additions and 7087 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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> {

View File

@@ -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'
}

View File

@@ -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,

View File

@@ -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[];

View File

@@ -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;

View File

@@ -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);

View File

@@ -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!;
}
}

View File

@@ -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 {

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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!);
}
}

View File

@@ -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;
}

View File

@@ -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}; }`);
}
});

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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));

View File

@@ -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,

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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`;
}
}
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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);
});
});

View File

@@ -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

View File

@@ -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;
}

View File

@@ -27,7 +27,7 @@ export const Context = {
export class CompletionItem {
_brand: 'ISuggestionItem';
_brand!: 'ISuggestionItem';
readonly resolve: (token: CancellationToken) => Promise<void>;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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(

View File

@@ -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);

View File

@@ -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);
}