mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-15 10:58:31 -05:00
This reverts commit d15a3fcc98.
This commit is contained in:
@@ -79,7 +79,7 @@ export class EditorState {
|
||||
* A cancellation token source that cancels when the editor changes as expressed
|
||||
* by the provided flags
|
||||
*/
|
||||
export class EditorStateCancellationTokenSource extends EditorKeybindingCancellationTokenSource implements IDisposable {
|
||||
export class EditorStateCancellationTokenSource extends EditorKeybindingCancellationTokenSource {
|
||||
|
||||
private readonly _listener: IDisposable[] = [];
|
||||
|
||||
@@ -110,7 +110,7 @@ export class EditorStateCancellationTokenSource extends EditorKeybindingCancella
|
||||
/**
|
||||
* A cancellation token source that cancels when the provided model changes
|
||||
*/
|
||||
export class TextModelCancellationTokenSource extends CancellationTokenSource implements IDisposable {
|
||||
export class TextModelCancellationTokenSource extends CancellationTokenSource {
|
||||
|
||||
private _listener: IDisposable;
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ export class View extends ViewEventHandler {
|
||||
this._setLayout();
|
||||
|
||||
// Pointer handler
|
||||
this.pointerHandler = this._register(new PointerHandler(this._context, viewController, this.createPointerHandlerHelper()));
|
||||
this.pointerHandler = new PointerHandler(this._context, viewController, this.createPointerHandlerHelper());
|
||||
|
||||
this._register(model.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
this.eventDispatcher.emitMany(events);
|
||||
@@ -342,6 +342,8 @@ export class View extends ViewEventHandler {
|
||||
this.eventDispatcher.removeEventHandler(this);
|
||||
this.outgoingEvents.dispose();
|
||||
|
||||
this.pointerHandler.dispose();
|
||||
|
||||
this.viewLines.dispose();
|
||||
|
||||
// Destroy view parts
|
||||
|
||||
@@ -257,12 +257,7 @@ class MinimapLayout {
|
||||
const computedSliderRatio = (maxMinimapSliderTop) / (scrollHeight - viewportHeight);
|
||||
const sliderTop = (scrollTop * computedSliderRatio);
|
||||
|
||||
let extraLinesAtTheBottom = 0;
|
||||
if (options.scrollBeyondLastLine) {
|
||||
const expectedViewportLineCount = viewportHeight / lineHeight;
|
||||
extraLinesAtTheBottom = expectedViewportLineCount;
|
||||
}
|
||||
if (minimapLinesFitting >= lineCount + extraLinesAtTheBottom) {
|
||||
if (minimapLinesFitting >= lineCount) {
|
||||
// All lines fit in the minimap
|
||||
const startLineNumber = 1;
|
||||
const endLineNumber = lineCount;
|
||||
|
||||
@@ -38,8 +38,7 @@ import { ClassName } from 'vs/editor/common/model/intervalTree';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity, editorWarningBorder, editorWarningForeground } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as assert from 'vs/base/common/assert';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
@@ -33,11 +33,12 @@ const defaultOptions: Options = {
|
||||
/**
|
||||
* Create a new diff navigator for the provided diff editor.
|
||||
*/
|
||||
export class DiffNavigator extends Disposable {
|
||||
export class DiffNavigator {
|
||||
|
||||
private readonly _editor: IDiffEditor;
|
||||
private readonly _options: Options;
|
||||
private readonly _onDidUpdate = this._register(new Emitter<this>());
|
||||
private readonly _disposables: IDisposable[];
|
||||
private readonly _onDidUpdate = new Emitter<this>();
|
||||
|
||||
readonly onDidUpdate: Event<this> = this._onDidUpdate.event;
|
||||
|
||||
@@ -48,11 +49,11 @@ export class DiffNavigator extends Disposable {
|
||||
private ignoreSelectionChange: boolean;
|
||||
|
||||
constructor(editor: IDiffEditor, options: Options = {}) {
|
||||
super();
|
||||
this._editor = editor;
|
||||
this._options = objects.mixin(options, defaultOptions, false);
|
||||
|
||||
this.disposed = false;
|
||||
this._disposables = [];
|
||||
|
||||
this.nextIdx = -1;
|
||||
this.ranges = [];
|
||||
@@ -60,11 +61,11 @@ export class DiffNavigator extends Disposable {
|
||||
this.revealFirst = Boolean(this._options.alwaysRevealFirst);
|
||||
|
||||
// hook up to diff editor for diff, disposal, and caret move
|
||||
this._register(this._editor.onDidDispose(() => this.dispose()));
|
||||
this._register(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));
|
||||
this._disposables.push(this._editor.onDidDispose(() => this.dispose()));
|
||||
this._disposables.push(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));
|
||||
|
||||
if (this._options.followsCaret) {
|
||||
this._register(this._editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
|
||||
this._disposables.push(this._editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
|
||||
if (this.ignoreSelectionChange) {
|
||||
return;
|
||||
}
|
||||
@@ -72,7 +73,7 @@ export class DiffNavigator extends Disposable {
|
||||
}));
|
||||
}
|
||||
if (this._options.alwaysRevealFirst) {
|
||||
this._register(this._editor.getModifiedEditor().onDidChangeModel((e) => {
|
||||
this._disposables.push(this._editor.getModifiedEditor().onDidChangeModel((e) => {
|
||||
this.revealFirst = true;
|
||||
}));
|
||||
}
|
||||
@@ -215,7 +216,9 @@ export class DiffNavigator extends Disposable {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
dispose(this._disposables);
|
||||
this._disposables.length = 0;
|
||||
this._onDidUpdate.dispose();
|
||||
this.ranges = [];
|
||||
this.disposed = true;
|
||||
}
|
||||
|
||||
@@ -839,7 +839,7 @@ const editorConfiguration: IConfigurationNode = {
|
||||
enumDescriptions: [
|
||||
nls.localize('editor.gotoLocation.multiple.peek', 'Show peek view of the results (default)'),
|
||||
nls.localize('editor.gotoLocation.multiple.gotoAndPeek', 'Go to the primary result and show a peek view'),
|
||||
nls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and enable peek-less navigation to others')
|
||||
nls.localize('editor.gotoLocation.multiple.goto', 'Go to the primary result and ignore others')
|
||||
]
|
||||
},
|
||||
'editor.selectionHighlight': {
|
||||
|
||||
@@ -10,7 +10,7 @@ export class Uint8Matrix {
|
||||
public readonly cols: number;
|
||||
|
||||
constructor(rows: number, cols: number, defaultValue: number) {
|
||||
const data = new Uint8Array(rows * cols);
|
||||
let data = new Uint8Array(rows * cols);
|
||||
for (let i = 0, len = rows * cols; i < len; i++) {
|
||||
data[i] = defaultValue;
|
||||
}
|
||||
@@ -85,8 +85,8 @@ export function toUint32(v: number): number {
|
||||
}
|
||||
|
||||
export function toUint32Array(arr: number[]): Uint32Array {
|
||||
const len = arr.length;
|
||||
const r = new Uint32Array(len);
|
||||
let len = arr.length;
|
||||
let r = new Uint32Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
r[i] = toUint32(arr[i]);
|
||||
}
|
||||
|
||||
@@ -177,26 +177,22 @@ export function guessIndentation(source: ITextBuffer, defaultTabSize: number, de
|
||||
}
|
||||
|
||||
let tabSize = defaultTabSize;
|
||||
let tabSizeScore = (insertSpaces ? 0 : 0.1 * linesCount);
|
||||
|
||||
// Guess tabSize only if inserting spaces...
|
||||
if (insertSpaces) {
|
||||
let tabSizeScore = (insertSpaces ? 0 : 0.1 * linesCount);
|
||||
// console.log("score threshold: " + tabSizeScore);
|
||||
|
||||
// console.log("score threshold: " + tabSizeScore);
|
||||
|
||||
ALLOWED_TAB_SIZE_GUESSES.forEach((possibleTabSize) => {
|
||||
let possibleTabSizeScore = spacesDiffCount[possibleTabSize];
|
||||
if (possibleTabSizeScore > tabSizeScore) {
|
||||
tabSizeScore = possibleTabSizeScore;
|
||||
tabSize = possibleTabSize;
|
||||
}
|
||||
});
|
||||
|
||||
// Let a tabSize of 2 win even if it is not the maximum
|
||||
// (only in case 4 was guessed)
|
||||
if (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {
|
||||
tabSize = 2;
|
||||
ALLOWED_TAB_SIZE_GUESSES.forEach((possibleTabSize) => {
|
||||
let possibleTabSizeScore = spacesDiffCount[possibleTabSize];
|
||||
if (possibleTabSizeScore > tabSizeScore) {
|
||||
tabSizeScore = possibleTabSizeScore;
|
||||
tabSize = possibleTabSize;
|
||||
}
|
||||
});
|
||||
|
||||
// Let a tabSize of 2 win even if it is not the maximum
|
||||
// (only in case 4 was guessed)
|
||||
if (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {
|
||||
tabSize = 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -550,10 +550,6 @@ export interface CodeActionContext {
|
||||
trigger: CodeActionTrigger;
|
||||
}
|
||||
|
||||
export interface CodeActionList extends IDisposable {
|
||||
readonly actions: ReadonlyArray<CodeAction>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The code action interface defines the contract between extensions and
|
||||
* the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature.
|
||||
@@ -563,7 +559,7 @@ export interface CodeActionProvider {
|
||||
/**
|
||||
* Provide commands for the given document and range.
|
||||
*/
|
||||
provideCodeActions(model: model.ITextModel, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<CodeActionList>;
|
||||
provideCodeActions(model: model.ITextModel, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<CodeAction[]>;
|
||||
|
||||
/**
|
||||
* Optional list of CodeActionKinds that this provider returns.
|
||||
@@ -1004,7 +1000,6 @@ export interface IInplaceReplaceSupportResult {
|
||||
export interface ILink {
|
||||
range: IRange;
|
||||
url?: URI | string;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export interface ILinksList {
|
||||
@@ -1098,6 +1093,7 @@ export interface DocumentColorProvider {
|
||||
}
|
||||
|
||||
export interface SelectionRange {
|
||||
kind: string;
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
@@ -1465,21 +1461,15 @@ export interface IWebviewPanelOptions {
|
||||
readonly retainContextWhenHidden?: boolean;
|
||||
}
|
||||
|
||||
export interface CodeLens {
|
||||
export interface ICodeLensSymbol {
|
||||
range: IRange;
|
||||
id?: string;
|
||||
command?: Command;
|
||||
}
|
||||
|
||||
export interface CodeLensList {
|
||||
lenses: CodeLens[];
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface CodeLensProvider {
|
||||
onDidChange?: Event<this>;
|
||||
provideCodeLenses(model: model.ITextModel, token: CancellationToken): ProviderResult<CodeLensList>;
|
||||
resolveCodeLens?(model: model.ITextModel, codeLens: CodeLens, token: CancellationToken): ProviderResult<CodeLens>;
|
||||
provideCodeLenses(model: model.ITextModel, token: CancellationToken): ProviderResult<ICodeLensSymbol[]>;
|
||||
resolveCodeLens?(model: model.ITextModel, codeLens: ICodeLensSymbol, token: CancellationToken): ProviderResult<ICodeLensSymbol>;
|
||||
}
|
||||
|
||||
// --- feature registries ------
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { activeContrastBorder, editorBackground, editorForeground, registerColor } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
/**
|
||||
@@ -37,14 +37,26 @@ export const editorOverviewRulerBorder = registerColor('editorOverviewRuler.bord
|
||||
|
||||
export const editorGutter = registerColor('editorGutter.background', { dark: editorBackground, light: editorBackground, hc: editorBackground }, nls.localize('editorGutter', 'Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.'));
|
||||
|
||||
export const editorErrorForeground = registerColor('editorError.foreground', { dark: '#ea4646', light: '#d60a0a', hc: null }, nls.localize('errorForeground', 'Foreground color of error squigglies in the editor.'));
|
||||
export const editorErrorBorder = registerColor('editorError.border', { dark: null, light: null, hc: Color.fromHex('#E47777').transparent(0.8) }, nls.localize('errorBorder', 'Border color of error squigglies in the editor.'));
|
||||
|
||||
export const editorWarningForeground = registerColor('editorWarning.foreground', { dark: '#4d9e4d', light: '#117711', hc: null }, nls.localize('warningForeground', 'Foreground color of warning squigglies in the editor.'));
|
||||
export const editorWarningBorder = registerColor('editorWarning.border', { dark: null, light: null, hc: Color.fromHex('#71B771').transparent(0.8) }, nls.localize('warningBorder', 'Border color of warning squigglies in the editor.'));
|
||||
|
||||
export const editorInfoForeground = registerColor('editorInfo.foreground', { dark: '#008000', light: '#008000', hc: null }, nls.localize('infoForeground', 'Foreground color of info squigglies in the editor.'));
|
||||
export const editorInfoBorder = registerColor('editorInfo.border', { dark: null, light: null, hc: Color.fromHex('#71B771').transparent(0.8) }, nls.localize('infoBorder', 'Border color of info squigglies in the editor.'));
|
||||
|
||||
export const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('hintForeground', 'Foreground color of hint squigglies in the editor.'));
|
||||
export const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint squigglies in the editor.'));
|
||||
|
||||
export const editorUnnecessaryCodeBorder = registerColor('editorUnnecessaryCode.border', { dark: null, light: null, hc: Color.fromHex('#fff').transparent(0.8) }, nls.localize('unnecessaryCodeBorder', 'Border color of unnecessary (unused) source code in the editor.'));
|
||||
export const editorUnnecessaryCodeOpacity = registerColor('editorUnnecessaryCode.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hc: null }, nls.localize('unnecessaryCodeOpacity', 'Opacity of unnecessary (unused) source code in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the \'editorUnnecessaryCode.border\' theme color to underline unnecessary code instead of fading it out.'));
|
||||
|
||||
const rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6));
|
||||
export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const overviewRulerError = registerColor('editorOverviewRuler.errorForeground', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hc: new Color(new RGBA(255, 50, 50, 1)) }, nls.localize('overviewRuleError', 'Overview ruler marker color for errors.'));
|
||||
export const overviewRulerWarning = registerColor('editorOverviewRuler.warningForeground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Overview ruler marker color for warnings.'));
|
||||
export const overviewRulerInfo = registerColor('editorOverviewRuler.infoForeground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoBorder }, nls.localize('overviewRuleInfo', 'Overview ruler marker color for infos.'));
|
||||
export const overviewRulerWarning = registerColor('editorOverviewRuler.warningForeground', { dark: new Color(new RGBA(18, 136, 18, 0.7)), light: new Color(new RGBA(18, 136, 18, 0.7)), hc: new Color(new RGBA(50, 255, 50, 1)) }, nls.localize('overviewRuleWarning', 'Overview ruler marker color for warnings.'));
|
||||
export const overviewRulerInfo = registerColor('editorOverviewRuler.infoForeground', { dark: new Color(new RGBA(18, 18, 136, 0.7)), light: new Color(new RGBA(18, 18, 136, 0.7)), hc: new Color(new RGBA(50, 50, 255, 1)) }, nls.localize('overviewRuleInfo', 'Overview ruler marker color for infos.'));
|
||||
|
||||
// contains all color rules that used to defined in editor/browser/widget/editor.css
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
|
||||
@@ -13,7 +13,6 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { PrefixSumComputerWithCache } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { ICoordinatesConverter, IOverviewRulerDecorations, ViewLineData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class OutputPosition {
|
||||
_outputPositionBrand: void;
|
||||
@@ -63,9 +62,11 @@ export interface ISplitLine {
|
||||
getViewLineNumberOfModelPosition(deltaLineNumber: number, inputColumn: number): number;
|
||||
}
|
||||
|
||||
export interface IViewModelLinesCollection extends IDisposable {
|
||||
export interface IViewModelLinesCollection {
|
||||
createCoordinatesConverter(): ICoordinatesConverter;
|
||||
|
||||
dispose(): void;
|
||||
|
||||
setWrappingSettings(wrappingIndent: WrappingIndent, wrappingColumn: number, columnsForFullWidthChar: number): boolean;
|
||||
setTabSize(newTabSize: number): boolean;
|
||||
getHiddenAreas(): Range[];
|
||||
|
||||
@@ -15,14 +15,8 @@ import { CodeAction, CodeActionContext, CodeActionProviderRegistry, CodeActionTr
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, filtersAction, mayIncludeActionsOfKind } from './codeActionTrigger';
|
||||
import { TextModelCancellationTokenSource } from 'vs/editor/browser/core/editorState';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface CodeActionSet extends IDisposable {
|
||||
readonly actions: readonly CodeAction[];
|
||||
readonly hasAutoFix: boolean;
|
||||
}
|
||||
|
||||
class ManagedCodeActionSet extends Disposable implements CodeActionSet {
|
||||
export class CodeActionSet {
|
||||
|
||||
private static codeActionsComparator(a: CodeAction, b: CodeAction): number {
|
||||
if (isNonEmptyArray(a.diagnostics)) {
|
||||
@@ -40,10 +34,8 @@ class ManagedCodeActionSet extends Disposable implements CodeActionSet {
|
||||
|
||||
public readonly actions: readonly CodeAction[];
|
||||
|
||||
public constructor(actions: readonly CodeAction[], disposables: DisposableStore) {
|
||||
super();
|
||||
this._register(disposables);
|
||||
this.actions = mergeSort([...actions], ManagedCodeActionSet.codeActionsComparator);
|
||||
public constructor(actions: readonly CodeAction[]) {
|
||||
this.actions = mergeSort([...actions], CodeActionSet.codeActionsComparator);
|
||||
}
|
||||
|
||||
public get hasAutoFix() {
|
||||
@@ -67,14 +59,12 @@ export function getCodeActions(
|
||||
const cts = new TextModelCancellationTokenSource(model, token);
|
||||
const providers = getCodeActionProviders(model, filter);
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
const promises = providers.map(provider => {
|
||||
return Promise.resolve(provider.provideCodeActions(model, rangeOrSelection, codeActionContext, cts.token)).then(providedCodeActions => {
|
||||
if (cts.token.isCancellationRequested || !providedCodeActions) {
|
||||
if (cts.token.isCancellationRequested || !Array.isArray(providedCodeActions)) {
|
||||
return [];
|
||||
}
|
||||
disposables.add(providedCodeActions);
|
||||
return providedCodeActions.actions.filter(action => action && filtersAction(filter, action));
|
||||
return providedCodeActions.filter(action => action && filtersAction(filter, action));
|
||||
}, (err): CodeAction[] => {
|
||||
if (isPromiseCanceledError(err)) {
|
||||
throw err;
|
||||
@@ -94,7 +84,7 @@ export function getCodeActions(
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(flatten)
|
||||
.then(actions => new ManagedCodeActionSet(actions, disposables))
|
||||
.then(actions => new CodeActionSet(actions))
|
||||
.finally(() => {
|
||||
listener.dispose();
|
||||
cts.dispose();
|
||||
@@ -116,7 +106,7 @@ function getCodeActionProviders(
|
||||
});
|
||||
}
|
||||
|
||||
registerLanguageCommand('_executeCodeActionProvider', async function (accessor, args): Promise<ReadonlyArray<CodeAction>> {
|
||||
registerLanguageCommand('_executeCodeActionProvider', function (accessor, args): Promise<ReadonlyArray<CodeAction>> {
|
||||
const { resource, range, kind } = args;
|
||||
if (!(resource instanceof URI) || !Range.isIRange(range)) {
|
||||
throw illegalArgument();
|
||||
@@ -127,11 +117,9 @@ registerLanguageCommand('_executeCodeActionProvider', async function (accessor,
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const codeActionSet = await getCodeActions(
|
||||
return getCodeActions(
|
||||
model,
|
||||
model.validateRange(range),
|
||||
{ type: 'manual', filter: { includeSourceActions: true, kind: kind && kind.value ? new CodeActionKind(kind.value) : undefined } },
|
||||
CancellationToken.None);
|
||||
codeActionSet.dispose();
|
||||
return codeActionSet.actions;
|
||||
CancellationToken.None).then(actions => actions.actions);
|
||||
});
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CancelablePromise } from 'vs/base/common/async';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, EditorCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
@@ -19,10 +20,10 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { CodeActionModel, SUPPORTED_CODE_ACTIONS, CodeActionsState } from './codeActionModel';
|
||||
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind, CodeActionTrigger } from './codeActionTrigger';
|
||||
import { CodeActionWidget } from './codeActionWidget';
|
||||
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind } from './codeActionTrigger';
|
||||
import { CodeActionContextMenu } from './codeActionWidget';
|
||||
import { LightBulbWidget } from './lightBulbWidget';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
@@ -44,15 +45,16 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
||||
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly _model: CodeActionModel;
|
||||
private readonly _codeActionWidget: CodeActionWidget;
|
||||
private readonly _codeActionContextMenu: CodeActionContextMenu;
|
||||
private readonly _lightBulbWidget: LightBulbWidget;
|
||||
private _currentCodeActions: CodeActionSet | undefined;
|
||||
|
||||
private _activeRequest: CancelablePromise<CodeActionSet> | undefined;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@IMarkerService markerService: IMarkerService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ILocalProgressService progressService: ILocalProgressService,
|
||||
@IProgressService progressService: IProgressService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@@ -61,70 +63,58 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
||||
super();
|
||||
|
||||
this._editor = editor;
|
||||
this._model = this._register(new CodeActionModel(this._editor, markerService, contextKeyService, progressService));
|
||||
this._codeActionWidget = new CodeActionWidget(editor, contextMenuService, {
|
||||
onSelectCodeAction: async (action) => {
|
||||
try {
|
||||
await this._applyCodeAction(action);
|
||||
} finally {
|
||||
// Retrigger
|
||||
this._trigger({ type: 'auto', filter: {} });
|
||||
}
|
||||
}
|
||||
});
|
||||
this._model = new CodeActionModel(this._editor, markerService, contextKeyService, progressService);
|
||||
this._codeActionContextMenu = new CodeActionContextMenu(editor, contextMenuService, action => this._onApplyCodeAction(action));
|
||||
this._lightBulbWidget = this._register(new LightBulbWidget(editor));
|
||||
|
||||
this._updateLightBulbTitle();
|
||||
|
||||
this._register(this._codeActionContextMenu.onDidExecuteCodeAction(_ => this._model.trigger({ type: 'auto', filter: {} })));
|
||||
this._register(this._lightBulbWidget.onClick(this._handleLightBulbSelect, this));
|
||||
this._register(this._model.onDidChangeState((newState) => this._onDidChangeCodeActionsState(newState)));
|
||||
this._register(this._model.onDidChangeState(e => this._onDidChangeCodeActionsState(e)));
|
||||
this._register(this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this));
|
||||
}
|
||||
|
||||
dipose() {
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
dispose(this._currentCodeActions);
|
||||
this._model.dispose();
|
||||
}
|
||||
|
||||
private _onDidChangeCodeActionsState(newState: CodeActionsState.State): void {
|
||||
if (newState.type === CodeActionsState.Type.Triggered) {
|
||||
newState.actions.then(actions => {
|
||||
dispose(this._currentCodeActions);
|
||||
this._currentCodeActions = actions;
|
||||
if (this._activeRequest) {
|
||||
this._activeRequest.cancel();
|
||||
this._activeRequest = undefined;
|
||||
}
|
||||
|
||||
if (!actions.actions.length && newState.trigger.context) {
|
||||
MessageController.get(this._editor).showMessage(newState.trigger.context.notAvailableMessage, newState.trigger.context.position);
|
||||
}
|
||||
});
|
||||
if (newState.type === CodeActionsState.Type.Triggered) {
|
||||
this._activeRequest = newState.actions;
|
||||
|
||||
if (newState.trigger.filter && newState.trigger.filter.kind) {
|
||||
// Triggered for specific scope
|
||||
newState.actions.then(codeActions => {
|
||||
if (codeActions.actions.length > 0) {
|
||||
newState.actions.then(fixes => {
|
||||
if (fixes.actions.length > 0) {
|
||||
// Apply if we only have one action or requested autoApply
|
||||
if (newState.trigger.autoApply === CodeActionAutoApply.First || (newState.trigger.autoApply === CodeActionAutoApply.IfSingle && codeActions.actions.length === 1)) {
|
||||
this._applyCodeAction(codeActions.actions[0]);
|
||||
if (newState.trigger.autoApply === CodeActionAutoApply.First || (newState.trigger.autoApply === CodeActionAutoApply.IfSingle && fixes.actions.length === 1)) {
|
||||
this._onApplyCodeAction(fixes.actions[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._codeActionWidget.show(newState.actions, newState.position);
|
||||
this._codeActionContextMenu.show(newState.actions, newState.position);
|
||||
|
||||
}).catch(onUnexpectedError);
|
||||
} else if (newState.trigger.type === 'manual') {
|
||||
this._codeActionWidget.show(newState.actions, newState.position);
|
||||
this._codeActionContextMenu.show(newState.actions, newState.position);
|
||||
} else {
|
||||
// auto magically triggered
|
||||
// * update an existing list of code actions
|
||||
// * manage light bulb
|
||||
if (this._codeActionWidget.isVisible) {
|
||||
this._codeActionWidget.show(newState.actions, newState.position);
|
||||
if (this._codeActionContextMenu.isVisible) {
|
||||
this._codeActionContextMenu.show(newState.actions, newState.position);
|
||||
} else {
|
||||
this._lightBulbWidget.tryShow(newState);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dispose(this._currentCodeActions);
|
||||
this._currentCodeActions = undefined;
|
||||
this._lightBulbWidget.hide();
|
||||
}
|
||||
}
|
||||
@@ -133,26 +123,12 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
||||
return QuickFixController.ID;
|
||||
}
|
||||
|
||||
public manualTriggerAtCurrentPosition(
|
||||
notAvailableMessage: string,
|
||||
filter?: CodeActionFilter,
|
||||
autoApply?: CodeActionAutoApply
|
||||
): void {
|
||||
if (!this._editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageController.get(this._editor).closeMessage();
|
||||
const triggerPosition = this._editor.getPosition();
|
||||
this._trigger({ type: 'manual', filter, autoApply, context: { notAvailableMessage, position: triggerPosition } });
|
||||
}
|
||||
|
||||
private _trigger(trigger: CodeActionTrigger) {
|
||||
return this._model.trigger(trigger);
|
||||
}
|
||||
|
||||
private _handleLightBulbSelect(e: { x: number, y: number, state: CodeActionsState.Triggered }): void {
|
||||
this._codeActionWidget.show(e.state.actions, e);
|
||||
this._codeActionContextMenu.show(e.state.actions, e);
|
||||
}
|
||||
|
||||
public triggerFromEditorSelection(filter?: CodeActionFilter, autoApply?: CodeActionAutoApply): Promise<CodeActionSet | undefined> {
|
||||
return this._model.trigger({ type: 'manual', filter, autoApply });
|
||||
}
|
||||
|
||||
private _updateLightBulbTitle(): void {
|
||||
@@ -166,7 +142,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
||||
this._lightBulbWidget.title = title;
|
||||
}
|
||||
|
||||
private _applyCodeAction(action: CodeAction): Promise<void> {
|
||||
private _onApplyCodeAction(action: CodeAction): Promise<void> {
|
||||
return applyCodeAction(action, this._bulkEditService, this._commandService, this._editor);
|
||||
}
|
||||
}
|
||||
@@ -185,18 +161,28 @@ export async function applyCodeAction(
|
||||
}
|
||||
}
|
||||
|
||||
function triggerCodeActionsForEditorSelection(
|
||||
function showCodeActionsForEditorSelection(
|
||||
editor: ICodeEditor,
|
||||
notAvailableMessage: string,
|
||||
filter: CodeActionFilter | undefined,
|
||||
autoApply: CodeActionAutoApply | undefined
|
||||
): void {
|
||||
if (editor.hasModel()) {
|
||||
const controller = QuickFixController.get(editor);
|
||||
if (controller) {
|
||||
controller.manualTriggerAtCurrentPosition(notAvailableMessage, filter, autoApply);
|
||||
}
|
||||
filter?: CodeActionFilter,
|
||||
autoApply?: CodeActionAutoApply
|
||||
) {
|
||||
if (!editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = QuickFixController.get(editor);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageController.get(editor).closeMessage();
|
||||
const pos = editor.getPosition();
|
||||
controller.triggerFromEditorSelection(filter, autoApply).then(codeActions => {
|
||||
if (!codeActions || !codeActions.actions.length) {
|
||||
MessageController.get(editor).showMessage(notAvailableMessage, pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export class QuickFixAction extends EditorAction {
|
||||
@@ -218,7 +204,7 @@ export class QuickFixAction extends EditorAction {
|
||||
}
|
||||
|
||||
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), undefined, undefined);
|
||||
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +284,7 @@ export class CodeActionCommand extends EditorCommand {
|
||||
kind: CodeActionKind.Empty,
|
||||
apply: CodeActionAutoApply.IfSingle,
|
||||
});
|
||||
return triggerCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"),
|
||||
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"),
|
||||
{
|
||||
kind: args.kind,
|
||||
includeSourceActions: true,
|
||||
@@ -361,7 +347,7 @@ export class RefactorAction extends EditorAction {
|
||||
kind: CodeActionKind.Refactor,
|
||||
apply: CodeActionAutoApply.Never
|
||||
});
|
||||
return triggerCodeActionsForEditorSelection(editor,
|
||||
return showCodeActionsForEditorSelection(editor,
|
||||
nls.localize('editor.action.refactor.noneMessage', "No refactorings available"),
|
||||
{
|
||||
kind: CodeActionKind.Refactor.contains(args.kind) ? args.kind : CodeActionKind.Empty,
|
||||
@@ -416,7 +402,7 @@ export class SourceAction extends EditorAction {
|
||||
kind: CodeActionKind.Source,
|
||||
apply: CodeActionAutoApply.Never
|
||||
});
|
||||
return triggerCodeActionsForEditorSelection(editor,
|
||||
return showCodeActionsForEditorSelection(editor,
|
||||
nls.localize('editor.action.source.noneMessage', "No source actions available"),
|
||||
{
|
||||
kind: CodeActionKind.Source.contains(args.kind) ? args.kind : CodeActionKind.Empty,
|
||||
@@ -448,7 +434,7 @@ export class OrganizeImportsAction extends EditorAction {
|
||||
}
|
||||
|
||||
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
return triggerCodeActionsForEditorSelection(editor,
|
||||
return showCodeActionsForEditorSelection(editor,
|
||||
nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),
|
||||
{ kind: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },
|
||||
CodeActionAutoApply.IfSingle);
|
||||
@@ -471,7 +457,7 @@ export class FixAllAction extends EditorAction {
|
||||
}
|
||||
|
||||
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
return triggerCodeActionsForEditorSelection(editor,
|
||||
return showCodeActionsForEditorSelection(editor,
|
||||
nls.localize('fixAll.noneMessage', "No fix all action available"),
|
||||
{ kind: CodeActionKind.SourceFixAll, includeSourceActions: true },
|
||||
CodeActionAutoApply.IfSingle);
|
||||
@@ -502,7 +488,7 @@ export class AutoFixAction extends EditorAction {
|
||||
}
|
||||
|
||||
public run(_accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
return triggerCodeActionsForEditorSelection(editor,
|
||||
return showCodeActionsForEditorSelection(editor,
|
||||
nls.localize('editor.action.autoFix.noneMessage', "No auto fixes available"),
|
||||
{
|
||||
kind: CodeActionKind.QuickFix,
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CancelablePromise, createCancelablePromise, TimeoutTimer } from 'vs/base/common/async';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
@@ -14,34 +14,36 @@ import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { CodeActionProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { getCodeActions, CodeActionSet } from './codeAction';
|
||||
import { CodeActionTrigger } from './codeActionTrigger';
|
||||
|
||||
export const SUPPORTED_CODE_ACTIONS = new RawContextKey<string>('supportedCodeAction', '');
|
||||
|
||||
export type TriggeredCodeAction = undefined | {
|
||||
readonly selection: Selection;
|
||||
readonly trigger: CodeActionTrigger;
|
||||
readonly position: Position;
|
||||
};
|
||||
export class CodeActionOracle {
|
||||
|
||||
class CodeActionOracle extends Disposable {
|
||||
|
||||
private readonly _autoTriggerTimer = this._register(new TimeoutTimer());
|
||||
private _disposables: IDisposable[] = [];
|
||||
private readonly _autoTriggerTimer = new TimeoutTimer();
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
private readonly _markerService: IMarkerService,
|
||||
private readonly _signalChange: (triggered: TriggeredCodeAction) => void,
|
||||
private readonly _signalChange: (newState: CodeActionsState.State) => void,
|
||||
private readonly _delay: number = 250,
|
||||
private readonly _progressService?: IProgressService,
|
||||
) {
|
||||
super();
|
||||
this._register(this._markerService.onMarkerChanged(e => this._onMarkerChanges(e)));
|
||||
this._register(this._editor.onDidChangeCursorPosition(() => this._onCursorChange()));
|
||||
this._disposables.push(
|
||||
this._markerService.onMarkerChanged(e => this._onMarkerChanges(e)),
|
||||
this._editor.onDidChangeCursorPosition(() => this._onCursorChange()),
|
||||
);
|
||||
}
|
||||
|
||||
public trigger(trigger: CodeActionTrigger): TriggeredCodeAction {
|
||||
dispose(): void {
|
||||
this._disposables = dispose(this._disposables);
|
||||
this._autoTriggerTimer.cancel();
|
||||
}
|
||||
|
||||
trigger(trigger: CodeActionTrigger) {
|
||||
const selection = this._getRangeOfSelectionUnlessWhitespaceEnclosed(trigger);
|
||||
return this._createEventAndSignalChange(trigger, selection);
|
||||
}
|
||||
@@ -110,24 +112,35 @@ class CodeActionOracle extends Disposable {
|
||||
return selection ? selection : undefined;
|
||||
}
|
||||
|
||||
private _createEventAndSignalChange(trigger: CodeActionTrigger, selection: Selection | undefined): TriggeredCodeAction {
|
||||
const model = this._editor.getModel();
|
||||
if (!selection || !model) {
|
||||
private _createEventAndSignalChange(trigger: CodeActionTrigger, selection: Selection | undefined): Promise<CodeActionSet | undefined> {
|
||||
if (!selection) {
|
||||
// cancel
|
||||
this._signalChange(undefined);
|
||||
return undefined;
|
||||
this._signalChange(CodeActionsState.Empty);
|
||||
return Promise.resolve(undefined);
|
||||
} else {
|
||||
const model = this._editor.getModel();
|
||||
if (!model) {
|
||||
// cancel
|
||||
this._signalChange(CodeActionsState.Empty);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const markerRange = this._getRangeOfMarker(selection);
|
||||
const position = markerRange ? markerRange.getStartPosition() : selection.getStartPosition();
|
||||
const actions = createCancelablePromise(token => getCodeActions(model, selection, trigger, token));
|
||||
|
||||
if (this._progressService && trigger.type === 'manual') {
|
||||
this._progressService.showWhile(actions, 250);
|
||||
}
|
||||
|
||||
this._signalChange(new CodeActionsState.Triggered(
|
||||
trigger,
|
||||
selection,
|
||||
position,
|
||||
actions
|
||||
));
|
||||
return actions;
|
||||
}
|
||||
|
||||
const markerRange = this._getRangeOfMarker(selection);
|
||||
const position = markerRange ? markerRange.getStartPosition() : selection.getStartPosition();
|
||||
|
||||
const e: TriggeredCodeAction = {
|
||||
trigger,
|
||||
selection,
|
||||
position
|
||||
};
|
||||
this._signalChange(e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,35 +167,36 @@ export namespace CodeActionsState {
|
||||
export type State = typeof Empty | Triggered;
|
||||
}
|
||||
|
||||
export class CodeActionModel extends Disposable {
|
||||
export class CodeActionModel {
|
||||
|
||||
private _codeActionOracle?: CodeActionOracle;
|
||||
private _state: CodeActionsState.State = CodeActionsState.Empty;
|
||||
private _onDidChangeState = new Emitter<CodeActionsState.State>();
|
||||
private _disposables: IDisposable[] = [];
|
||||
private readonly _supportedCodeActions: IContextKey<string>;
|
||||
|
||||
private readonly _onDidChangeState = this._register(new Emitter<CodeActionsState.State>());
|
||||
public readonly onDidChangeState = this._onDidChangeState.event;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
private readonly _markerService: IMarkerService,
|
||||
contextKeyService: IContextKeyService,
|
||||
private readonly _progressService?: ILocalProgressService
|
||||
private readonly _progressService: IProgressService
|
||||
) {
|
||||
super();
|
||||
this._supportedCodeActions = SUPPORTED_CODE_ACTIONS.bindTo(contextKeyService);
|
||||
|
||||
this._register(this._editor.onDidChangeModel(() => this._update()));
|
||||
this._register(this._editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._register(CodeActionProviderRegistry.onDidChange(() => this._update()));
|
||||
this._disposables.push(this._editor.onDidChangeModel(() => this._update()));
|
||||
this._disposables.push(this._editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._disposables.push(CodeActionProviderRegistry.onDidChange(() => this._update()));
|
||||
|
||||
this._update();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this._disposables = dispose(this._disposables);
|
||||
dispose(this._codeActionOracle);
|
||||
this.setState(CodeActionsState.Empty, true);
|
||||
}
|
||||
|
||||
get onDidChangeState(): Event<CodeActionsState.State> {
|
||||
return this._onDidChangeState.event;
|
||||
}
|
||||
|
||||
private _update(): void {
|
||||
@@ -191,6 +205,9 @@ export class CodeActionModel extends Disposable {
|
||||
this._codeActionOracle = undefined;
|
||||
}
|
||||
|
||||
if (this._state.type === CodeActionsState.Type.Triggered) {
|
||||
this._state.actions.cancel();
|
||||
}
|
||||
this.setState(CodeActionsState.Empty);
|
||||
|
||||
const model = this._editor.getModel();
|
||||
@@ -207,46 +224,25 @@ export class CodeActionModel extends Disposable {
|
||||
|
||||
this._supportedCodeActions.set(supportedActions.join(' '));
|
||||
|
||||
this._codeActionOracle = new CodeActionOracle(this._editor, this._markerService, trigger => {
|
||||
if (!trigger) {
|
||||
this.setState(CodeActionsState.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
const actions = createCancelablePromise(token => getCodeActions(model, trigger.selection, trigger.trigger, token));
|
||||
if (this._progressService && trigger.trigger.type === 'manual') {
|
||||
this._progressService.showWhile(actions, 250);
|
||||
}
|
||||
|
||||
this.setState(new CodeActionsState.Triggered(trigger.trigger, trigger.selection, trigger.position, actions));
|
||||
|
||||
}, undefined);
|
||||
this._codeActionOracle = new CodeActionOracle(this._editor, this._markerService, newState => this.setState(newState), undefined, this._progressService);
|
||||
this._codeActionOracle.trigger({ type: 'auto' });
|
||||
} else {
|
||||
this._supportedCodeActions.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public trigger(trigger: CodeActionTrigger) {
|
||||
public trigger(trigger: CodeActionTrigger): Promise<CodeActionSet | undefined> {
|
||||
if (this._codeActionOracle) {
|
||||
this._codeActionOracle.trigger(trigger);
|
||||
return this._codeActionOracle.trigger(trigger);
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private setState(newState: CodeActionsState.State, skipNotify?: boolean) {
|
||||
private setState(newState: CodeActionsState.State) {
|
||||
if (newState === this._state) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel old request
|
||||
if (this._state.type === CodeActionsState.Type.Triggered) {
|
||||
this._state.actions.cancel();
|
||||
}
|
||||
|
||||
this._state = newState;
|
||||
|
||||
if (!skipNotify) {
|
||||
this._onDidChangeState.fire(newState);
|
||||
}
|
||||
this._onDidChangeState.fire(newState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { CodeAction } from 'vs/editor/common/modes';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
|
||||
export class CodeActionKind {
|
||||
private static readonly sep = '.';
|
||||
@@ -91,8 +90,4 @@ export interface CodeActionTrigger {
|
||||
readonly type: 'auto' | 'manual';
|
||||
readonly filter?: CodeActionFilter;
|
||||
readonly autoApply?: CodeActionAutoApply;
|
||||
readonly context?: {
|
||||
readonly notAvailableMessage: string;
|
||||
readonly position: Position;
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
import { getDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
@@ -13,32 +14,25 @@ import { CodeAction } from 'vs/editor/common/modes';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
|
||||
interface CodeActionWidgetDelegate {
|
||||
onSelectCodeAction: (action: CodeAction) => Promise<any>;
|
||||
}
|
||||
|
||||
export class CodeActionWidget {
|
||||
export class CodeActionContextMenu {
|
||||
|
||||
private _visible: boolean;
|
||||
|
||||
private readonly _onDidExecuteCodeAction = new Emitter<void>();
|
||||
public readonly onDidExecuteCodeAction: Event<void> = this._onDidExecuteCodeAction.event;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
private readonly _contextMenuService: IContextMenuService,
|
||||
private readonly _delegate: CodeActionWidgetDelegate
|
||||
private readonly _onApplyCodeAction: (action: CodeAction) => Promise<any>
|
||||
) { }
|
||||
|
||||
public async show(actionsToShow: Promise<CodeActionSet>, at?: { x: number; y: number } | Position): Promise<void> {
|
||||
async show(actionsToShow: Promise<CodeActionSet>, at?: { x: number; y: number } | Position): Promise<void> {
|
||||
const codeActions = await actionsToShow;
|
||||
if (!codeActions.actions.length) {
|
||||
this._visible = false;
|
||||
return;
|
||||
}
|
||||
if (!this._editor.getDomNode()) {
|
||||
// cancel when editor went off-dom
|
||||
this._visible = false;
|
||||
return Promise.reject(canceled());
|
||||
}
|
||||
|
||||
this._visible = true;
|
||||
const actions = codeActions.actions.map(action => this.codeActionToAction(action));
|
||||
this._contextMenuService.showContextMenu({
|
||||
@@ -60,7 +54,9 @@ export class CodeActionWidget {
|
||||
private codeActionToAction(action: CodeAction): Action {
|
||||
const id = action.command ? action.command.id : action.title;
|
||||
const title = action.title;
|
||||
return new Action(id, title, undefined, true, () => this._delegate.onSelectCodeAction(action));
|
||||
return new Action(id, title, undefined, true, () =>
|
||||
this._onApplyCodeAction(action)
|
||||
.finally(() => this._onDidExecuteCodeAction.fire(undefined)));
|
||||
}
|
||||
|
||||
get isVisible(): boolean {
|
||||
|
||||
@@ -45,14 +45,13 @@ export class LightBulbWidget extends Disposable implements IContentWidget {
|
||||
this._futureFixes.cancel();
|
||||
}
|
||||
}));
|
||||
this._register(dom.addStandardDisposableListener(this._domNode, 'mousedown', e => {
|
||||
this._register(dom.addStandardDisposableListener(this._domNode, 'click', e => {
|
||||
if (this._state.type !== CodeActionsState.Type.Triggered) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that focus / cursor location is not lost when clicking widget icon
|
||||
this._editor.focus();
|
||||
dom.EventHelper.stop(e, true);
|
||||
// a bit of extra work to make sure the menu
|
||||
// doesn't cover the line-text
|
||||
const { top, height } = dom.getDomNodePagePosition(this._domNode);
|
||||
@@ -107,8 +106,9 @@ export class LightBulbWidget extends Disposable implements IContentWidget {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
tryShow(newState: CodeActionsState.Triggered) {
|
||||
if (this._position && (!newState.position || this._position.position && this._position.position.lineNumber !== newState.position.lineNumber)) {
|
||||
tryShow(newState: CodeActionsState.State) {
|
||||
|
||||
if (newState.type !== CodeActionsState.Type.Triggered || this._position && (!newState.position || this._position.position && this._position.position.lineNumber !== newState.position.lineNumber)) {
|
||||
// hide when getting a 'hide'-request or when currently
|
||||
// showing on another line
|
||||
this.hide();
|
||||
@@ -121,6 +121,10 @@ export class LightBulbWidget extends Disposable implements IContentWidget {
|
||||
const { token } = this._futureFixes;
|
||||
this._state = newState;
|
||||
|
||||
if (this._state.type === CodeActionsState.Empty.type) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = this._state.rangeOrSelection;
|
||||
this._state.actions.then(fixes => {
|
||||
if (!token.isCancellationRequested && fixes.actions.length > 0 && selection) {
|
||||
|
||||
@@ -3,34 +3,22 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CodeAction, CodeActionContext, CodeActionProvider, CodeActionProviderRegistry, Command, LanguageIdentifier, ResourceTextEdit, WorkspaceEdit } from 'vs/editor/common/modes';
|
||||
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
|
||||
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
function staticCodeActionProvider(...actions: modes.CodeAction[]): modes.CodeActionProvider {
|
||||
return new class implements modes.CodeActionProvider {
|
||||
provideCodeActions(): modes.CodeActionList {
|
||||
return {
|
||||
actions: actions,
|
||||
dispose: () => { }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
suite('CodeAction', () => {
|
||||
|
||||
let langId = new modes.LanguageIdentifier('fooLang', 17);
|
||||
let langId = new LanguageIdentifier('fooLang', 17);
|
||||
let uri = URI.parse('untitled:path');
|
||||
let model: TextModel;
|
||||
const disposables = new DisposableStore();
|
||||
let disposables: IDisposable[] = [];
|
||||
let testData = {
|
||||
diagnostics: {
|
||||
abc: {
|
||||
@@ -58,7 +46,7 @@ suite('CodeAction', () => {
|
||||
},
|
||||
command: {
|
||||
abc: {
|
||||
command: new class implements modes.Command {
|
||||
command: new class implements Command {
|
||||
id: '1';
|
||||
title: 'abc';
|
||||
},
|
||||
@@ -68,8 +56,8 @@ suite('CodeAction', () => {
|
||||
spelling: {
|
||||
bcd: {
|
||||
diagnostics: <IMarkerData[]>[],
|
||||
edit: new class implements modes.WorkspaceEdit {
|
||||
edits: modes.ResourceTextEdit[];
|
||||
edit: new class implements WorkspaceEdit {
|
||||
edits: ResourceTextEdit[];
|
||||
},
|
||||
title: 'abc'
|
||||
}
|
||||
@@ -91,27 +79,30 @@ suite('CodeAction', () => {
|
||||
};
|
||||
|
||||
setup(function () {
|
||||
disposables.clear();
|
||||
model = TextModel.createFromString('test1\ntest2\ntest3', undefined, langId, uri);
|
||||
disposables.add(model);
|
||||
disposables = [model];
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
disposables.clear();
|
||||
dispose(disposables);
|
||||
});
|
||||
|
||||
test('CodeActions are sorted by type, #38623', async function () {
|
||||
|
||||
const provider = staticCodeActionProvider(
|
||||
testData.command.abc,
|
||||
testData.diagnostics.bcd,
|
||||
testData.spelling.bcd,
|
||||
testData.tsLint.bcd,
|
||||
testData.tsLint.abc,
|
||||
testData.diagnostics.abc
|
||||
);
|
||||
const provider = new class implements CodeActionProvider {
|
||||
provideCodeActions() {
|
||||
return [
|
||||
testData.command.abc,
|
||||
testData.diagnostics.bcd,
|
||||
testData.spelling.bcd,
|
||||
testData.tsLint.bcd,
|
||||
testData.tsLint.abc,
|
||||
testData.diagnostics.abc
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
disposables.push(CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const expected = [
|
||||
// CodeActions with a diagnostics array are shown first ordered by diagnostics.message
|
||||
@@ -131,13 +122,17 @@ suite('CodeAction', () => {
|
||||
});
|
||||
|
||||
test('getCodeActions should filter by scope', async function () {
|
||||
const provider = staticCodeActionProvider(
|
||||
{ title: 'a', kind: 'a' },
|
||||
{ title: 'b', kind: 'b' },
|
||||
{ title: 'a.b', kind: 'a.b' }
|
||||
);
|
||||
const provider = new class implements CodeActionProvider {
|
||||
provideCodeActions(): CodeAction[] {
|
||||
return [
|
||||
{ title: 'a', kind: 'a' },
|
||||
{ title: 'b', kind: 'b' },
|
||||
{ title: 'a.b', kind: 'a.b' }
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
disposables.push(CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { kind: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
@@ -159,18 +154,15 @@ suite('CodeAction', () => {
|
||||
});
|
||||
|
||||
test('getCodeActions should forward requested scope to providers', async function () {
|
||||
const provider = new class implements modes.CodeActionProvider {
|
||||
provideCodeActions(_model: any, _range: Range, context: modes.CodeActionContext, _token: any): modes.CodeActionList {
|
||||
return {
|
||||
actions: [
|
||||
{ title: context.only || '', kind: context.only }
|
||||
],
|
||||
dispose: () => { }
|
||||
};
|
||||
const provider = new class implements CodeActionProvider {
|
||||
provideCodeActions(_model: any, _range: Range, context: CodeActionContext, _token: any): CodeAction[] {
|
||||
return [
|
||||
{ title: context.only || '', kind: context.only }
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
disposables.push(CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const { actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { kind: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
@@ -178,12 +170,16 @@ suite('CodeAction', () => {
|
||||
});
|
||||
|
||||
test('getCodeActions should not return source code action by default', async function () {
|
||||
const provider = staticCodeActionProvider(
|
||||
{ title: 'a', kind: CodeActionKind.Source.value },
|
||||
{ title: 'b', kind: 'b' }
|
||||
);
|
||||
const provider = new class implements CodeActionProvider {
|
||||
provideCodeActions(): CodeAction[] {
|
||||
return [
|
||||
{ title: 'a', kind: CodeActionKind.Source.value },
|
||||
{ title: 'b', kind: 'b' }
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
disposables.push(CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto' }, CancellationToken.None);
|
||||
@@ -200,16 +196,16 @@ suite('CodeAction', () => {
|
||||
|
||||
test('getCodeActions should not invoke code action providers filtered out by providedCodeActionKinds', async function () {
|
||||
let wasInvoked = false;
|
||||
const provider = new class implements modes.CodeActionProvider {
|
||||
provideCodeActions(): modes.CodeActionList {
|
||||
const provider = new class implements CodeActionProvider {
|
||||
provideCodeActions() {
|
||||
wasInvoked = true;
|
||||
return { actions: [], dispose: () => { } };
|
||||
return [];
|
||||
}
|
||||
|
||||
providedCodeActionKinds = [CodeActionKind.Refactor.value];
|
||||
};
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
disposables.push(CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const { actions } = await getCodeActions(model, new Range(1, 1, 2, 1), {
|
||||
type: 'auto',
|
||||
|
||||
@@ -4,38 +4,32 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CodeActionModel, CodeActionsState } from 'vs/editor/contrib/codeAction/codeActionModel';
|
||||
import { CodeActionProviderRegistry, LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { CodeActionOracle, CodeActionsState } from 'vs/editor/contrib/codeAction/codeActionModel';
|
||||
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
|
||||
const testProvider = {
|
||||
provideCodeActions(): modes.CodeActionList {
|
||||
return {
|
||||
actions: [
|
||||
{ title: 'test', command: { id: 'test-command', title: 'test', arguments: [] } }
|
||||
],
|
||||
dispose() { /* noop*/ }
|
||||
};
|
||||
provideCodeActions() {
|
||||
return [{ id: 'test-command', title: 'test', arguments: [] }];
|
||||
}
|
||||
};
|
||||
suite('CodeActionModel', () => {
|
||||
suite('CodeAction', () => {
|
||||
|
||||
const languageIdentifier = new modes.LanguageIdentifier('foo-lang', 3);
|
||||
const languageIdentifier = new LanguageIdentifier('foo-lang', 3);
|
||||
let uri = URI.parse('untitled:path');
|
||||
let model: TextModel;
|
||||
let markerService: MarkerService;
|
||||
let editor: ICodeEditor;
|
||||
const disposables = new DisposableStore();
|
||||
let disposables: IDisposable[];
|
||||
|
||||
setup(() => {
|
||||
disposables.clear();
|
||||
disposables = [];
|
||||
markerService = new MarkerService();
|
||||
model = TextModel.createFromString('foobar foo bar\nfarboo far boo', undefined, languageIdentifier, uri);
|
||||
editor = createTestCodeEditor({ model: model });
|
||||
@@ -43,28 +37,26 @@ suite('CodeActionModel', () => {
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
disposables.clear();
|
||||
dispose(disposables);
|
||||
editor.dispose();
|
||||
model.dispose();
|
||||
markerService.dispose();
|
||||
});
|
||||
|
||||
test('Orcale -> marker added', done => {
|
||||
const reg = modes.CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.add(reg);
|
||||
const reg = CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.push(reg);
|
||||
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
const oracle = new CodeActionOracle(editor, markerService, (e: CodeActionsState.Triggered) => {
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.ok(e.actions);
|
||||
|
||||
e.actions.then(fixes => {
|
||||
model.dispose();
|
||||
oracle.dispose();
|
||||
assert.equal(fixes.actions.length, 1);
|
||||
done();
|
||||
}, done);
|
||||
}));
|
||||
});
|
||||
|
||||
// start here
|
||||
markerService.changeOne('fake', uri, [{
|
||||
@@ -78,8 +70,8 @@ suite('CodeActionModel', () => {
|
||||
});
|
||||
|
||||
test('Orcale -> position changed', () => {
|
||||
const reg = modes.CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.add(reg);
|
||||
const reg = CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.push(reg);
|
||||
|
||||
markerService.changeOne('fake', uri, [{
|
||||
startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
|
||||
@@ -92,29 +84,28 @@ suite('CodeActionModel', () => {
|
||||
editor.setPosition({ lineNumber: 2, column: 1 });
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
|
||||
const oracle = new CodeActionOracle(editor, markerService, (e: CodeActionsState.Triggered) => {
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.ok(e.actions);
|
||||
e.actions.then(fixes => {
|
||||
model.dispose();
|
||||
oracle.dispose();
|
||||
assert.equal(fixes.actions.length, 1);
|
||||
resolve(undefined);
|
||||
}, reject);
|
||||
}));
|
||||
});
|
||||
// start here
|
||||
editor.setPosition({ lineNumber: 1, column: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
test('Lightbulb is in the wrong place, #29933', async function () {
|
||||
const reg = modes.CodeActionProviderRegistry.register(languageIdentifier.language, {
|
||||
provideCodeActions(_doc, _range): modes.CodeActionList {
|
||||
return { actions: [], dispose() { /* noop*/ } };
|
||||
const reg = CodeActionProviderRegistry.register(languageIdentifier.language, {
|
||||
provideCodeActions(_doc, _range) {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
disposables.add(reg);
|
||||
disposables.push(reg);
|
||||
|
||||
editor.getModel()!.setValue('// @ts-check\n2\ncon\n');
|
||||
|
||||
@@ -128,9 +119,8 @@ suite('CodeActionModel', () => {
|
||||
|
||||
// case 1 - drag selection over multiple lines -> range of enclosed marker, position or marker
|
||||
await new Promise(resolve => {
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
|
||||
let oracle = new CodeActionOracle(editor, markerService, (e: CodeActionsState.Triggered) => {
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
const selection = <Selection>e.rangeOrSelection;
|
||||
assert.deepEqual(selection.selectionStartLineNumber, 1);
|
||||
@@ -138,32 +128,31 @@ suite('CodeActionModel', () => {
|
||||
assert.deepEqual(selection.endLineNumber, 4);
|
||||
assert.deepEqual(selection.endColumn, 1);
|
||||
assert.deepEqual(e.position, { lineNumber: 3, column: 1 });
|
||||
model.dispose();
|
||||
|
||||
oracle.dispose();
|
||||
resolve(undefined);
|
||||
}, 5));
|
||||
}, 5);
|
||||
|
||||
editor.setSelection({ startLineNumber: 1, startColumn: 1, endLineNumber: 4, endColumn: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
test('Orcale -> should only auto trigger once for cursor and marker update right after each other', done => {
|
||||
const reg = modes.CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.add(reg);
|
||||
const reg = CodeActionProviderRegistry.register(languageIdentifier.language, testProvider);
|
||||
disposables.push(reg);
|
||||
|
||||
let triggerCount = 0;
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
const oracle = new CodeActionOracle(editor, markerService, (e: CodeActionsState.Triggered) => {
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
++triggerCount;
|
||||
|
||||
// give time for second trigger before completing test
|
||||
setTimeout(() => {
|
||||
model.dispose();
|
||||
oracle.dispose();
|
||||
assert.strictEqual(triggerCount, 1);
|
||||
done();
|
||||
}, 50);
|
||||
}, 5 /*delay*/));
|
||||
}, 5 /*delay*/);
|
||||
|
||||
markerService.changeOne('fake', uri, [{
|
||||
startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
|
||||
|
||||
@@ -6,19 +6,18 @@
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { CodeLensModel } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { ICodeLensData } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { LRUCache, values } from 'vs/base/common/map';
|
||||
import { CodeLensProvider, CodeLensList, CodeLens } from 'vs/editor/common/modes';
|
||||
import { ICodeLensSymbol, CodeLensProvider } from 'vs/editor/common/modes';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { runWhenIdle } from 'vs/base/common/async';
|
||||
|
||||
export const ICodeLensCache = createDecorator<ICodeLensCache>('ICodeLensCache');
|
||||
|
||||
export interface ICodeLensCache {
|
||||
_serviceBrand: any;
|
||||
put(model: ITextModel, data: CodeLensModel): void;
|
||||
get(model: ITextModel): CodeLensModel | undefined;
|
||||
put(model: ITextModel, data: ICodeLensData[]): void;
|
||||
get(model: ITextModel): ICodeLensData[] | undefined;
|
||||
delete(model: ITextModel): void;
|
||||
}
|
||||
|
||||
@@ -31,7 +30,7 @@ class CacheItem {
|
||||
|
||||
constructor(
|
||||
readonly lineCount: number,
|
||||
readonly data: CodeLensModel
|
||||
readonly data: ICodeLensData[]
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -40,7 +39,7 @@ export class CodeLensCache implements ICodeLensCache {
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly _fakeProvider = new class implements CodeLensProvider {
|
||||
provideCodeLenses(): CodeLensList {
|
||||
provideCodeLenses(): ICodeLensSymbol[] {
|
||||
throw new Error('not supported');
|
||||
}
|
||||
};
|
||||
@@ -49,12 +48,9 @@ export class CodeLensCache implements ICodeLensCache {
|
||||
|
||||
constructor(@IStorageService storageService: IStorageService) {
|
||||
|
||||
// remove old data
|
||||
const oldkey = 'codelens/cache';
|
||||
runWhenIdle(() => storageService.remove(oldkey, StorageScope.WORKSPACE));
|
||||
const key = 'codelens/cache';
|
||||
|
||||
// restore lens data on start
|
||||
const key = 'codelens/cache2';
|
||||
const raw = storageService.get(key, StorageScope.WORKSPACE, '{}');
|
||||
this._deserialize(raw);
|
||||
|
||||
@@ -65,12 +61,13 @@ export class CodeLensCache implements ICodeLensCache {
|
||||
});
|
||||
}
|
||||
|
||||
put(model: ITextModel, data: CodeLensModel): void {
|
||||
|
||||
const lensModel = new CodeLensModel();
|
||||
lensModel.add({ lenses: data.lenses.map(v => v.symbol), dispose() { } }, this._fakeProvider);
|
||||
|
||||
const item = new CacheItem(model.getLineCount(), lensModel);
|
||||
put(model: ITextModel, data: ICodeLensData[]): void {
|
||||
const item = new CacheItem(model.getLineCount(), data.map(item => {
|
||||
return {
|
||||
symbol: item.symbol,
|
||||
provider: this._fakeProvider
|
||||
};
|
||||
}));
|
||||
this._cache.set(model.uri.toString(), item);
|
||||
}
|
||||
|
||||
@@ -89,7 +86,7 @@ export class CodeLensCache implements ICodeLensCache {
|
||||
const data: Record<string, ISerializedCacheData> = Object.create(null);
|
||||
this._cache.forEach((value, key) => {
|
||||
const lines = new Set<number>();
|
||||
for (const d of value.data.lenses) {
|
||||
for (const d of value.data) {
|
||||
lines.add(d.symbol.range.startLineNumber);
|
||||
}
|
||||
data[key] = {
|
||||
@@ -105,14 +102,14 @@ export class CodeLensCache implements ICodeLensCache {
|
||||
const data: Record<string, ISerializedCacheData> = JSON.parse(raw);
|
||||
for (const key in data) {
|
||||
const element = data[key];
|
||||
const lenses: CodeLens[] = [];
|
||||
const symbols: ICodeLensData[] = [];
|
||||
for (const line of element.lines) {
|
||||
lenses.push({ range: new Range(line, 1, line, 11) });
|
||||
symbols.push({
|
||||
provider: this._fakeProvider,
|
||||
symbol: { range: new Range(line, 1, line, 11) }
|
||||
});
|
||||
}
|
||||
|
||||
const model = new CodeLensModel();
|
||||
model.add({ lenses, dispose() { } }, this._fakeProvider);
|
||||
this._cache.set(key, new CacheItem(element.lineCount, model));
|
||||
this._cache.set(key, new CacheItem(element.lineCount, symbols));
|
||||
}
|
||||
} catch {
|
||||
// ignore...
|
||||
|
||||
@@ -9,59 +9,38 @@ import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/error
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { CodeLensProvider, CodeLensProviderRegistry, CodeLens, CodeLensList } from 'vs/editor/common/modes';
|
||||
import { CodeLensProvider, CodeLensProviderRegistry, ICodeLensSymbol } from 'vs/editor/common/modes';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface CodeLensItem {
|
||||
symbol: CodeLens;
|
||||
export interface ICodeLensData {
|
||||
symbol: ICodeLensSymbol;
|
||||
provider: CodeLensProvider;
|
||||
}
|
||||
|
||||
export class CodeLensModel {
|
||||
|
||||
lenses: CodeLensItem[] = [];
|
||||
|
||||
private readonly _dispoables = new DisposableStore();
|
||||
|
||||
dispose(): void {
|
||||
this._dispoables.dispose();
|
||||
}
|
||||
|
||||
add(list: CodeLensList, provider: CodeLensProvider): void {
|
||||
this._dispoables.add(list);
|
||||
for (const symbol of list.lenses) {
|
||||
this.lenses.push({ symbol, provider });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getCodeLensData(model: ITextModel, token: CancellationToken): Promise<CodeLensModel> {
|
||||
export function getCodeLensData(model: ITextModel, token: CancellationToken): Promise<ICodeLensData[]> {
|
||||
|
||||
const symbols: ICodeLensData[] = [];
|
||||
const provider = CodeLensProviderRegistry.ordered(model);
|
||||
const providerRanks = new Map<CodeLensProvider, number>();
|
||||
const result = new CodeLensModel();
|
||||
|
||||
const promises = provider.map((provider, i) => {
|
||||
|
||||
providerRanks.set(provider, i);
|
||||
|
||||
return Promise.resolve(provider.provideCodeLenses(model, token))
|
||||
.then(list => list && result.add(list, provider))
|
||||
.catch(onUnexpectedExternalError);
|
||||
});
|
||||
const promises = provider.map(provider => Promise.resolve(provider.provideCodeLenses(model, token)).then(result => {
|
||||
if (Array.isArray(result)) {
|
||||
for (let symbol of result) {
|
||||
symbols.push({ symbol, provider });
|
||||
}
|
||||
}
|
||||
}).catch(onUnexpectedExternalError));
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
|
||||
result.lenses = mergeSort(result.lenses, (a, b) => {
|
||||
return mergeSort(symbols, (a, b) => {
|
||||
// sort by lineNumber, provider-rank, and column
|
||||
if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) {
|
||||
return -1;
|
||||
} else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) {
|
||||
return 1;
|
||||
} else if (providerRanks.get(a.provider)! < providerRanks.get(b.provider)!) {
|
||||
} else if (provider.indexOf(a.provider) < provider.indexOf(b.provider)) {
|
||||
return -1;
|
||||
} else if (providerRanks.get(a.provider)! > providerRanks.get(b.provider)!) {
|
||||
} else if (provider.indexOf(a.provider) > provider.indexOf(b.provider)) {
|
||||
return 1;
|
||||
} else if (a.symbol.range.startColumn < b.symbol.range.startColumn) {
|
||||
return -1;
|
||||
@@ -71,8 +50,6 @@ export function getCodeLensData(model: ITextModel, token: CancellationToken): Pr
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,12 +65,12 @@ registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) {
|
||||
throw illegalArgument();
|
||||
}
|
||||
|
||||
const result: CodeLens[] = [];
|
||||
const result: ICodeLensSymbol[] = [];
|
||||
return getCodeLensData(model, CancellationToken.None).then(value => {
|
||||
|
||||
let resolve: Promise<any>[] = [];
|
||||
|
||||
for (const item of value.lenses) {
|
||||
for (const item of value) {
|
||||
if (typeof itemResolveCount === 'undefined' || Boolean(item.symbol.command)) {
|
||||
result.push(item.symbol);
|
||||
} else if (itemResolveCount-- > 0 && item.provider.resolveCodeLens) {
|
||||
@@ -101,7 +78,7 @@ registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) {
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(resolve).finally(() => value.dispose());
|
||||
return Promise.all(resolve);
|
||||
|
||||
}).then(() => {
|
||||
return result;
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
import { CancelablePromise, RunOnceScheduler, createCancelablePromise, disposableTimeout } from 'vs/base/common/async';
|
||||
import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { StableEditorScrollState } from 'vs/editor/browser/core/editorState';
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model';
|
||||
import { CodeLensProviderRegistry, CodeLens } from 'vs/editor/common/modes';
|
||||
import { CodeLensModel, getCodeLensData, CodeLensItem } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { CodeLensWidget, CodeLensHelper } from 'vs/editor/contrib/codelens/codelensWidget';
|
||||
import { CodeLensProviderRegistry, ICodeLensSymbol } from 'vs/editor/common/modes';
|
||||
import { ICodeLensData, getCodeLensData } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { CodeLens, CodeLensHelper } from 'vs/editor/contrib/codelens/codelensWidget';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ICodeLensCache } from 'vs/editor/contrib/codelens/codeLensCache';
|
||||
@@ -25,13 +25,12 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
private _isEnabled: boolean;
|
||||
|
||||
private readonly _globalToDispose = new DisposableStore();
|
||||
private readonly _localToDispose = new DisposableStore();
|
||||
private _lenses: CodeLensWidget[] = [];
|
||||
private _currentFindCodeLensSymbolsPromise: CancelablePromise<CodeLensModel> | undefined;
|
||||
private _currentCodeLensModel: CodeLensModel | undefined;
|
||||
private _modelChangeCounter: number = 0;
|
||||
private _currentResolveCodeLensSymbolsPromise: CancelablePromise<any> | undefined;
|
||||
private _globalToDispose: IDisposable[];
|
||||
private _localToDispose: IDisposable[];
|
||||
private _lenses: CodeLens[];
|
||||
private _currentFindCodeLensSymbolsPromise: CancelablePromise<ICodeLensData[]> | null;
|
||||
private _modelChangeCounter: number;
|
||||
private _currentResolveCodeLensSymbolsPromise: CancelablePromise<any> | null;
|
||||
private _detectVisibleLenses: RunOnceScheduler;
|
||||
|
||||
constructor(
|
||||
@@ -42,36 +41,41 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
) {
|
||||
this._isEnabled = this._editor.getConfiguration().contribInfo.codeLens;
|
||||
|
||||
this._globalToDispose.add(this._editor.onDidChangeModel(() => this._onModelChange()));
|
||||
this._globalToDispose.add(this._editor.onDidChangeModelLanguage(() => this._onModelChange()));
|
||||
this._globalToDispose.add(this._editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
|
||||
this._globalToDispose = [];
|
||||
this._localToDispose = [];
|
||||
this._lenses = [];
|
||||
this._currentFindCodeLensSymbolsPromise = null;
|
||||
this._modelChangeCounter = 0;
|
||||
|
||||
this._globalToDispose.push(this._editor.onDidChangeModel(() => this._onModelChange()));
|
||||
this._globalToDispose.push(this._editor.onDidChangeModelLanguage(() => this._onModelChange()));
|
||||
this._globalToDispose.push(this._editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
|
||||
let prevIsEnabled = this._isEnabled;
|
||||
this._isEnabled = this._editor.getConfiguration().contribInfo.codeLens;
|
||||
if (prevIsEnabled !== this._isEnabled) {
|
||||
this._onModelChange();
|
||||
}
|
||||
}));
|
||||
this._globalToDispose.add(CodeLensProviderRegistry.onDidChange(this._onModelChange, this));
|
||||
this._globalToDispose.push(CodeLensProviderRegistry.onDidChange(this._onModelChange, this));
|
||||
this._onModelChange();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._localDispose();
|
||||
this._globalToDispose.dispose();
|
||||
this._globalToDispose = dispose(this._globalToDispose);
|
||||
}
|
||||
|
||||
private _localDispose(): void {
|
||||
if (this._currentFindCodeLensSymbolsPromise) {
|
||||
this._currentFindCodeLensSymbolsPromise.cancel();
|
||||
this._currentFindCodeLensSymbolsPromise = undefined;
|
||||
this._currentFindCodeLensSymbolsPromise = null;
|
||||
this._modelChangeCounter++;
|
||||
}
|
||||
if (this._currentResolveCodeLensSymbolsPromise) {
|
||||
this._currentResolveCodeLensSymbolsPromise.cancel();
|
||||
this._currentResolveCodeLensSymbolsPromise = undefined;
|
||||
this._currentResolveCodeLensSymbolsPromise = null;
|
||||
}
|
||||
this._localToDispose.clear();
|
||||
dispose(this._currentCodeLensModel);
|
||||
this._localToDispose = dispose(this._localToDispose);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -100,7 +104,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
// no provider -> return but check with
|
||||
// cached lenses. they expire after 30 seconds
|
||||
if (cachedLenses) {
|
||||
this._localToDispose.add(disposableTimeout(() => {
|
||||
this._localToDispose.push(disposableTimeout(() => {
|
||||
const cachedLensesNow = this._codeLensCache.get(model);
|
||||
if (cachedLenses === cachedLensesNow) {
|
||||
this._codeLensCache.delete(model);
|
||||
@@ -114,7 +118,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
for (const provider of CodeLensProviderRegistry.all(model)) {
|
||||
if (typeof provider.onDidChange === 'function') {
|
||||
let registration = provider.onDidChange(() => scheduler.schedule());
|
||||
this._localToDispose.add(registration);
|
||||
this._localToDispose.push(registration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,25 +136,18 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
this._currentFindCodeLensSymbolsPromise.then(result => {
|
||||
if (counterValue === this._modelChangeCounter) { // only the last one wins
|
||||
// lifecycle -> dispose old model
|
||||
dispose(this._currentCodeLensModel);
|
||||
this._currentCodeLensModel = result;
|
||||
|
||||
// cache model to reduce flicker
|
||||
this._codeLensCache.put(model, result);
|
||||
|
||||
// render lenses
|
||||
this._renderCodeLensSymbols(result);
|
||||
this._detectVisibleLenses.schedule();
|
||||
}
|
||||
}, onUnexpectedError);
|
||||
}, 250);
|
||||
this._localToDispose.add(scheduler);
|
||||
this._localToDispose.add(this._detectVisibleLenses);
|
||||
this._localToDispose.add(this._editor.onDidChangeModelContent((e) => {
|
||||
this._localToDispose.push(scheduler);
|
||||
this._localToDispose.push(this._detectVisibleLenses);
|
||||
this._localToDispose.push(this._editor.onDidChangeModelContent((e) => {
|
||||
this._editor.changeDecorations((changeAccessor) => {
|
||||
this._editor.changeViewZones((viewAccessor) => {
|
||||
let toDispose: CodeLensWidget[] = [];
|
||||
let toDispose: CodeLens[] = [];
|
||||
let lastLensLineNumber: number = -1;
|
||||
|
||||
this._lenses.forEach((lens) => {
|
||||
@@ -179,15 +176,15 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
// Ask for all references again
|
||||
scheduler.schedule();
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onDidScrollChange(e => {
|
||||
this._localToDispose.push(this._editor.onDidScrollChange(e => {
|
||||
if (e.scrollTopChanged && this._lenses.length > 0) {
|
||||
this._detectVisibleLenses.schedule();
|
||||
}
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onDidLayoutChange(e => {
|
||||
this._localToDispose.push(this._editor.onDidLayoutChange(e => {
|
||||
this._detectVisibleLenses.schedule();
|
||||
}));
|
||||
this._localToDispose.add(toDisposable(() => {
|
||||
this._localToDispose.push(toDisposable(() => {
|
||||
if (this._editor.getModel()) {
|
||||
const scrollState = StableEditorScrollState.capture(this._editor);
|
||||
this._editor.changeDecorations((changeAccessor) => {
|
||||
@@ -201,14 +198,14 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
this._disposeAllLenses(undefined, undefined);
|
||||
}
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onDidChangeConfiguration(e => {
|
||||
this._localToDispose.push(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.fontInfo) {
|
||||
for (const lens of this._lenses) {
|
||||
lens.updateHeight();
|
||||
}
|
||||
}
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onMouseUp(e => {
|
||||
this._localToDispose.push(this._editor.onMouseUp(e => {
|
||||
if (e.target.type === editorBrowser.MouseTargetType.CONTENT_WIDGET && e.target.element && e.target.element.tagName === 'A') {
|
||||
for (const lens of this._lenses) {
|
||||
let command = lens.getCommand(e.target.element as HTMLLinkElement);
|
||||
@@ -231,16 +228,16 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
this._lenses = [];
|
||||
}
|
||||
|
||||
private _renderCodeLensSymbols(symbols: CodeLensModel): void {
|
||||
private _renderCodeLensSymbols(symbols: ICodeLensData[]): void {
|
||||
if (!this._editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let maxLineNumber = this._editor.getModel().getLineCount();
|
||||
let groups: CodeLensItem[][] = [];
|
||||
let lastGroup: CodeLensItem[] | undefined;
|
||||
let groups: ICodeLensData[][] = [];
|
||||
let lastGroup: ICodeLensData[] | undefined;
|
||||
|
||||
for (let symbol of symbols.lenses) {
|
||||
for (let symbol of symbols) {
|
||||
let line = symbol.symbol.range.startLineNumber;
|
||||
if (line < 1 || line > maxLineNumber) {
|
||||
// invalid code lens
|
||||
@@ -275,7 +272,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
groupsIndex++;
|
||||
codeLensIndex++;
|
||||
} else {
|
||||
this._lenses.splice(codeLensIndex, 0, new CodeLensWidget(groups[groupsIndex], this._editor, helper, accessor, () => this._detectVisibleLenses.schedule()));
|
||||
this._lenses.splice(codeLensIndex, 0, new CodeLens(groups[groupsIndex], this._editor, helper, accessor, () => this._detectVisibleLenses.schedule()));
|
||||
codeLensIndex++;
|
||||
groupsIndex++;
|
||||
}
|
||||
@@ -289,7 +286,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
// Create extra symbols
|
||||
while (groupsIndex < groups.length) {
|
||||
this._lenses.push(new CodeLensWidget(groups[groupsIndex], this._editor, helper, accessor, () => this._detectVisibleLenses.schedule()));
|
||||
this._lenses.push(new CodeLens(groups[groupsIndex], this._editor, helper, accessor, () => this._detectVisibleLenses.schedule()));
|
||||
groupsIndex++;
|
||||
}
|
||||
|
||||
@@ -303,7 +300,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
private _onViewportChanged(): void {
|
||||
if (this._currentResolveCodeLensSymbolsPromise) {
|
||||
this._currentResolveCodeLensSymbolsPromise.cancel();
|
||||
this._currentResolveCodeLensSymbolsPromise = undefined;
|
||||
this._currentResolveCodeLensSymbolsPromise = null;
|
||||
}
|
||||
|
||||
const model = this._editor.getModel();
|
||||
@@ -311,8 +308,8 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
const toResolve: CodeLensItem[][] = [];
|
||||
const lenses: CodeLensWidget[] = [];
|
||||
const toResolve: ICodeLensData[][] = [];
|
||||
const lenses: CodeLens[] = [];
|
||||
this._lenses.forEach((lens) => {
|
||||
const request = lens.computeIfNecessary(model);
|
||||
if (request) {
|
||||
@@ -329,7 +326,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
const promises = toResolve.map((request, i) => {
|
||||
|
||||
const resolvedSymbols = new Array<CodeLens | undefined | null>(request.length);
|
||||
const resolvedSymbols = new Array<ICodeLensSymbol | undefined | null>(request.length);
|
||||
const promises = request.map((request, i) => {
|
||||
if (!request.symbol.command && typeof request.provider.resolveCodeLens === 'function') {
|
||||
return Promise.resolve(request.provider.resolveCodeLens(model, request.symbol, token)).then(symbol => {
|
||||
@@ -349,10 +346,11 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
this._currentResolveCodeLensSymbolsPromise.catch(err => {
|
||||
this._currentResolveCodeLensSymbolsPromise.then(() => {
|
||||
this._currentResolveCodeLensSymbolsPromise = null;
|
||||
}).catch(err => {
|
||||
this._currentResolveCodeLensSymbolsPromise = null;
|
||||
onUnexpectedError(err);
|
||||
}).finally(() => {
|
||||
this._currentResolveCodeLensSymbolsPromise = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { Command, CodeLens } from 'vs/editor/common/modes';
|
||||
import { Command, ICodeLensSymbol } from 'vs/editor/common/modes';
|
||||
import { editorCodeLensForeground } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { CodeLensItem } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { ICodeLensData } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
@@ -65,7 +65,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
||||
constructor(
|
||||
editor: editorBrowser.ICodeEditor,
|
||||
symbolRange: Range,
|
||||
data: CodeLensItem[]
|
||||
data: ICodeLensData[]
|
||||
) {
|
||||
this._id = 'codeLensWidget' + (++CodeLensContentWidget._idPool);
|
||||
this._editor = editor;
|
||||
@@ -88,7 +88,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
||||
this._domNode.innerHTML = ' ';
|
||||
}
|
||||
|
||||
withCommands(inSymbols: Array<CodeLens | undefined | null>, animate: boolean): void {
|
||||
withCommands(inSymbols: Array<ICodeLensSymbol | undefined | null>, animate: boolean): void {
|
||||
this._commands.clear();
|
||||
|
||||
const symbols = coalesce(inSymbols);
|
||||
@@ -189,17 +189,17 @@ export class CodeLensHelper {
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeLensWidget {
|
||||
export class CodeLens {
|
||||
|
||||
private readonly _editor: editorBrowser.ICodeEditor;
|
||||
private readonly _viewZone: CodeLensViewZone;
|
||||
private readonly _viewZoneId: number;
|
||||
private readonly _contentWidget: CodeLensContentWidget;
|
||||
private _decorationIds: string[];
|
||||
private _data: CodeLensItem[];
|
||||
private _data: ICodeLensData[];
|
||||
|
||||
constructor(
|
||||
data: CodeLensItem[],
|
||||
data: ICodeLensData[],
|
||||
editor: editorBrowser.ICodeEditor,
|
||||
helper: CodeLensHelper,
|
||||
viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor,
|
||||
@@ -256,7 +256,7 @@ export class CodeLensWidget {
|
||||
});
|
||||
}
|
||||
|
||||
updateCodeLensSymbols(data: CodeLensItem[], helper: CodeLensHelper): void {
|
||||
updateCodeLensSymbols(data: ICodeLensData[], helper: CodeLensHelper): void {
|
||||
while (this._decorationIds.length) {
|
||||
helper.removeDecoration(this._decorationIds.pop()!);
|
||||
}
|
||||
@@ -270,7 +270,7 @@ export class CodeLensWidget {
|
||||
});
|
||||
}
|
||||
|
||||
computeIfNecessary(model: ITextModel): CodeLensItem[] | null {
|
||||
computeIfNecessary(model: ITextModel): ICodeLensData[] | null {
|
||||
if (!this._contentWidget.isVisible()) {
|
||||
return null;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ export class CodeLensWidget {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
updateCommands(symbols: Array<CodeLens | undefined | null>): void {
|
||||
updateCommands(symbols: Array<ICodeLensSymbol | undefined | null>): void {
|
||||
this._contentWidget.withCommands(symbols, true);
|
||||
for (let i = 0; i < this._data.length; i++) {
|
||||
const resolved = symbols[i];
|
||||
|
||||
@@ -7,7 +7,7 @@ import { CancelablePromise, TimeoutTimer, createCancelablePromise } from 'vs/bas
|
||||
import { RGBA } from 'vs/base/common/color';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
@@ -22,13 +22,14 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
|
||||
const MAX_DECORATORS = 500;
|
||||
|
||||
export class ColorDetector extends Disposable implements IEditorContribution {
|
||||
export class ColorDetector implements IEditorContribution {
|
||||
|
||||
private static readonly ID: string = 'editor.contrib.colorDetector';
|
||||
|
||||
static RECOMPUTE_TIME = 1000; // ms
|
||||
|
||||
private readonly _localToDispose = this._register(new DisposableStore());
|
||||
private _globalToDispose: IDisposable[] = [];
|
||||
private _localToDispose: IDisposable[] = [];
|
||||
private _computePromise: CancelablePromise<IColorData[]> | null;
|
||||
private _timeoutTimer: TimeoutTimer | null;
|
||||
|
||||
@@ -44,14 +45,13 @@ export class ColorDetector extends Disposable implements IEditorContribution {
|
||||
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
this._register(_editor.onDidChangeModel((e) => {
|
||||
this._globalToDispose.push(_editor.onDidChangeModel((e) => {
|
||||
this._isEnabled = this.isEnabled();
|
||||
this.onModelChanged();
|
||||
}));
|
||||
this._register(_editor.onDidChangeModelLanguage((e) => this.onModelChanged()));
|
||||
this._register(ColorProviderRegistry.onDidChange((e) => this.onModelChanged()));
|
||||
this._register(_editor.onDidChangeConfiguration((e) => {
|
||||
this._globalToDispose.push(_editor.onDidChangeModelLanguage((e) => this.onModelChanged()));
|
||||
this._globalToDispose.push(ColorProviderRegistry.onDidChange((e) => this.onModelChanged()));
|
||||
this._globalToDispose.push(_editor.onDidChangeConfiguration((e) => {
|
||||
let prevIsEnabled = this._isEnabled;
|
||||
this._isEnabled = this.isEnabled();
|
||||
if (prevIsEnabled !== this._isEnabled) {
|
||||
@@ -98,7 +98,7 @@ export class ColorDetector extends Disposable implements IEditorContribution {
|
||||
dispose(): void {
|
||||
this.stop();
|
||||
this.removeAllDecorations();
|
||||
super.dispose();
|
||||
this._globalToDispose = dispose(this._globalToDispose);
|
||||
}
|
||||
|
||||
private onModelChanged(): void {
|
||||
@@ -113,7 +113,7 @@ export class ColorDetector extends Disposable implements IEditorContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
this._localToDispose.add(this._editor.onDidChangeModelContent((e) => {
|
||||
this._localToDispose.push(this._editor.onDidChangeModelContent((e) => {
|
||||
if (!this._timeoutTimer) {
|
||||
this._timeoutTimer = new TimeoutTimer();
|
||||
this._timeoutTimer.cancelAndSet(() => {
|
||||
@@ -149,7 +149,7 @@ export class ColorDetector extends Disposable implements IEditorContribution {
|
||||
this._computePromise.cancel();
|
||||
this._computePromise = null;
|
||||
}
|
||||
this._localToDispose.clear();
|
||||
this._localToDispose = dispose(this._localToDispose);
|
||||
}
|
||||
|
||||
private updateDecorations(colorDatas: IColorData[]): void {
|
||||
|
||||
@@ -125,7 +125,7 @@ export class ContextMenuController implements IEditorContribution {
|
||||
}
|
||||
}
|
||||
|
||||
private _getMenuActions(model: ITextModel): ReadonlyArray<IAction> {
|
||||
private _getMenuActions(model: ITextModel): IAction[] {
|
||||
const result: IAction[] = [];
|
||||
|
||||
let contextMenu = this._menuService.createMenu(MenuId.EditorContext, this._contextKeyService);
|
||||
@@ -141,7 +141,7 @@ export class ContextMenuController implements IEditorContribution {
|
||||
return result;
|
||||
}
|
||||
|
||||
private _doShowContextMenu(actions: ReadonlyArray<IAction>, anchor: IAnchor | null = null): void {
|
||||
private _doShowContextMenu(actions: IAction[], anchor: IAnchor | null = null): void {
|
||||
if (!this._editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./dnd';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ICodeEditor, IEditorMouseEvent, IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -28,11 +28,12 @@ function hasTriggerModifier(e: IKeyboardEvent | IMouseEvent): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
export class DragAndDropController extends Disposable implements editorCommon.IEditorContribution {
|
||||
export class DragAndDropController implements editorCommon.IEditorContribution {
|
||||
|
||||
private static readonly ID = 'editor.contrib.dragAndDrop';
|
||||
|
||||
private readonly _editor: ICodeEditor;
|
||||
private _toUnhook: IDisposable[];
|
||||
private _dragSelection: Selection | null;
|
||||
private _dndDecorationIds: string[];
|
||||
private _mouseDown: boolean;
|
||||
@@ -44,15 +45,15 @@ export class DragAndDropController extends Disposable implements editorCommon.IE
|
||||
}
|
||||
|
||||
constructor(editor: ICodeEditor) {
|
||||
super();
|
||||
this._editor = editor;
|
||||
this._register(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e)));
|
||||
this._register(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(e)));
|
||||
this._register(this._editor.onMouseDrag((e: IEditorMouseEvent) => this._onEditorMouseDrag(e)));
|
||||
this._register(this._editor.onMouseDrop((e: IEditorMouseEvent) => this._onEditorMouseDrop(e)));
|
||||
this._register(this._editor.onKeyDown((e: IKeyboardEvent) => this.onEditorKeyDown(e)));
|
||||
this._register(this._editor.onKeyUp((e: IKeyboardEvent) => this.onEditorKeyUp(e)));
|
||||
this._register(this._editor.onDidBlurEditorWidget(() => this.onEditorBlur()));
|
||||
this._toUnhook = [];
|
||||
this._toUnhook.push(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e)));
|
||||
this._toUnhook.push(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(e)));
|
||||
this._toUnhook.push(this._editor.onMouseDrag((e: IEditorMouseEvent) => this._onEditorMouseDrag(e)));
|
||||
this._toUnhook.push(this._editor.onMouseDrop((e: IEditorMouseEvent) => this._onEditorMouseDrop(e)));
|
||||
this._toUnhook.push(this._editor.onKeyDown((e: IKeyboardEvent) => this.onEditorKeyDown(e)));
|
||||
this._toUnhook.push(this._editor.onKeyUp((e: IKeyboardEvent) => this.onEditorKeyUp(e)));
|
||||
this._toUnhook.push(this._editor.onDidBlurEditorWidget(() => this.onEditorBlur()));
|
||||
this._dndDecorationIds = [];
|
||||
this._mouseDown = false;
|
||||
this._modifierPressed = false;
|
||||
@@ -227,7 +228,7 @@ export class DragAndDropController extends Disposable implements editorCommon.IE
|
||||
this._dragSelection = null;
|
||||
this._mouseDown = false;
|
||||
this._modifierPressed = false;
|
||||
super.dispose();
|
||||
this._toUnhook = dispose(this._toUnhook);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,29 +99,29 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
}
|
||||
}));
|
||||
|
||||
const prevBtn = this._register(new SimpleButton({
|
||||
const prevBtn = new SimpleButton({
|
||||
label: NLS_PREVIOUS_MATCH_BTN_LABEL,
|
||||
className: 'previous',
|
||||
onTrigger: () => {
|
||||
this.find(true);
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
const nextBtn = this._register(new SimpleButton({
|
||||
const nextBtn = new SimpleButton({
|
||||
label: NLS_NEXT_MATCH_BTN_LABEL,
|
||||
className: 'next',
|
||||
onTrigger: () => {
|
||||
this.find(false);
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
const closeBtn = this._register(new SimpleButton({
|
||||
const closeBtn = 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');
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as types from 'vs/base/common/types';
|
||||
import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
import { RunOnceScheduler, Delayer, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ScrollType, IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions';
|
||||
@@ -46,7 +46,7 @@ interface FoldingStateMemento {
|
||||
provider?: string;
|
||||
}
|
||||
|
||||
export class FoldingController extends Disposable implements IEditorContribution {
|
||||
export class FoldingController implements IEditorContribution {
|
||||
|
||||
static MAX_FOLDING_REGIONS = 5000;
|
||||
|
||||
@@ -73,25 +73,27 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
private foldingModelPromise: Promise<FoldingModel | null> | null;
|
||||
private updateScheduler: Delayer<FoldingModel | null> | null;
|
||||
|
||||
private globalToDispose: IDisposable[];
|
||||
|
||||
private cursorChangedScheduler: RunOnceScheduler | null;
|
||||
|
||||
private readonly localToDispose = this._register(new DisposableStore());
|
||||
private localToDispose: IDisposable[];
|
||||
|
||||
constructor(editor: ICodeEditor) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this._isEnabled = this.editor.getConfiguration().contribInfo.folding;
|
||||
this._autoHideFoldingControls = this.editor.getConfiguration().contribInfo.showFoldingControls === 'mouseover';
|
||||
this._useFoldingProviders = this.editor.getConfiguration().contribInfo.foldingStrategy !== 'indentation';
|
||||
|
||||
this.globalToDispose = [];
|
||||
this.localToDispose = [];
|
||||
|
||||
this.foldingDecorationProvider = new FoldingDecorationProvider(editor);
|
||||
this.foldingDecorationProvider.autoHideFoldingControls = this._autoHideFoldingControls;
|
||||
|
||||
this._register(this.editor.onDidChangeModel(() => this.onModelChanged()));
|
||||
this.globalToDispose.push(this.editor.onDidChangeModel(() => this.onModelChanged()));
|
||||
|
||||
this._register(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
|
||||
this.globalToDispose.push(this.editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
|
||||
if (e.contribInfo) {
|
||||
let oldIsEnabled = this._isEnabled;
|
||||
this._isEnabled = this.editor.getConfiguration().contribInfo.folding;
|
||||
@@ -111,6 +113,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
}
|
||||
}
|
||||
}));
|
||||
this.globalToDispose.push({ dispose: () => dispose(this.localToDispose) });
|
||||
this.onModelChanged();
|
||||
}
|
||||
|
||||
@@ -118,6 +121,10 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
return ID;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.globalToDispose = dispose(this.globalToDispose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store view state.
|
||||
*/
|
||||
@@ -166,7 +173,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
}
|
||||
|
||||
private onModelChanged(): void {
|
||||
this.localToDispose.clear();
|
||||
this.localToDispose = dispose(this.localToDispose);
|
||||
|
||||
let model = this.editor.getModel();
|
||||
if (!this._isEnabled || !model || model.isTooLargeForTokenization()) {
|
||||
@@ -175,23 +182,23 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
}
|
||||
|
||||
this.foldingModel = new FoldingModel(model, this.foldingDecorationProvider);
|
||||
this.localToDispose.add(this.foldingModel);
|
||||
this.localToDispose.push(this.foldingModel);
|
||||
|
||||
this.hiddenRangeModel = new HiddenRangeModel(this.foldingModel);
|
||||
this.localToDispose.add(this.hiddenRangeModel);
|
||||
this.localToDispose.add(this.hiddenRangeModel.onDidChange(hr => this.onHiddenRangesChanges(hr)));
|
||||
this.localToDispose.push(this.hiddenRangeModel);
|
||||
this.localToDispose.push(this.hiddenRangeModel.onDidChange(hr => this.onHiddenRangesChanges(hr)));
|
||||
|
||||
this.updateScheduler = new Delayer<FoldingModel>(200);
|
||||
|
||||
this.cursorChangedScheduler = new RunOnceScheduler(() => this.revealCursor(), 200);
|
||||
this.localToDispose.add(this.cursorChangedScheduler);
|
||||
this.localToDispose.add(FoldingRangeProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged()));
|
||||
this.localToDispose.add(this.editor.onDidChangeModelLanguageConfiguration(() => this.onFoldingStrategyChanged())); // covers model language changes as well
|
||||
this.localToDispose.add(this.editor.onDidChangeModelContent(() => this.onModelContentChanged()));
|
||||
this.localToDispose.add(this.editor.onDidChangeCursorPosition(() => this.onCursorPositionChanged()));
|
||||
this.localToDispose.add(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
this.localToDispose.add(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
|
||||
this.localToDispose.add({
|
||||
this.localToDispose.push(this.cursorChangedScheduler);
|
||||
this.localToDispose.push(FoldingRangeProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged()));
|
||||
this.localToDispose.push(this.editor.onDidChangeModelLanguageConfiguration(() => this.onFoldingStrategyChanged())); // covers model language changes as well
|
||||
this.localToDispose.push(this.editor.onDidChangeModelContent(() => this.onModelContentChanged()));
|
||||
this.localToDispose.push(this.editor.onDidChangeCursorPosition(() => this.onCursorPositionChanged()));
|
||||
this.localToDispose.push(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
|
||||
this.localToDispose.push(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
|
||||
this.localToDispose.push({
|
||||
dispose: () => {
|
||||
if (this.foldingRegionPromise) {
|
||||
this.foldingRegionPromise.cancel();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, registerEditorAction, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
@@ -30,18 +30,18 @@ class FormatOnType implements editorCommon.IEditorContribution {
|
||||
private static readonly ID = 'editor.contrib.autoFormat';
|
||||
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private readonly _callOnModel = new DisposableStore();
|
||||
private _callOnDispose: IDisposable[] = [];
|
||||
private _callOnModel: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@IEditorWorkerService private readonly _workerService: IEditorWorkerService
|
||||
) {
|
||||
this._editor = editor;
|
||||
this._callOnDispose.add(editor.onDidChangeConfiguration(() => this._update()));
|
||||
this._callOnDispose.add(editor.onDidChangeModel(() => this._update()));
|
||||
this._callOnDispose.add(editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._callOnDispose.add(OnTypeFormattingEditProviderRegistry.onDidChange(this._update, this));
|
||||
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
|
||||
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
|
||||
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this._update, this));
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -49,14 +49,14 @@ class FormatOnType implements editorCommon.IEditorContribution {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._callOnDispose.dispose();
|
||||
this._callOnModel.dispose();
|
||||
this._callOnDispose = dispose(this._callOnDispose);
|
||||
this._callOnModel = dispose(this._callOnModel);
|
||||
}
|
||||
|
||||
private _update(): void {
|
||||
|
||||
// clean up
|
||||
this._callOnModel.clear();
|
||||
this._callOnModel = dispose(this._callOnModel);
|
||||
|
||||
// we are disabled
|
||||
if (!this._editor.getConfiguration().contribInfo.formatOnType) {
|
||||
@@ -81,7 +81,7 @@ class FormatOnType implements editorCommon.IEditorContribution {
|
||||
for (let ch of support.autoFormatTriggerCharacters) {
|
||||
triggerChars.add(ch.charCodeAt(0));
|
||||
}
|
||||
this._callOnModel.add(this._editor.onDidType((text: string) => {
|
||||
this._callOnModel.push(this._editor.onDidType((text: string) => {
|
||||
let lastCharCode = text.charCodeAt(text.length - 1);
|
||||
if (triggerChars.has(lastCharCode)) {
|
||||
this._trigger(String.fromCharCode(lastCharCode));
|
||||
@@ -156,17 +156,20 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
|
||||
|
||||
private static readonly ID = 'editor.contrib.formatOnPaste';
|
||||
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private readonly _callOnModel = new DisposableStore();
|
||||
private _callOnDispose: IDisposable[];
|
||||
private _callOnModel: IDisposable[];
|
||||
|
||||
constructor(
|
||||
private readonly editor: ICodeEditor,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
this._callOnDispose.add(editor.onDidChangeConfiguration(() => this._update()));
|
||||
this._callOnDispose.add(editor.onDidChangeModel(() => this._update()));
|
||||
this._callOnDispose.add(editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._callOnDispose.add(DocumentRangeFormattingEditProviderRegistry.onDidChange(this._update, this));
|
||||
this._callOnDispose = [];
|
||||
this._callOnModel = [];
|
||||
|
||||
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
|
||||
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
|
||||
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
|
||||
this._callOnDispose.push(DocumentRangeFormattingEditProviderRegistry.onDidChange(this._update, this));
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
@@ -174,14 +177,14 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._callOnDispose.dispose();
|
||||
this._callOnModel.dispose();
|
||||
this._callOnDispose = dispose(this._callOnDispose);
|
||||
this._callOnModel = dispose(this._callOnModel);
|
||||
}
|
||||
|
||||
private _update(): void {
|
||||
|
||||
// clean up
|
||||
this._callOnModel.dispose();
|
||||
this._callOnModel = dispose(this._callOnModel);
|
||||
|
||||
// we are disabled
|
||||
if (!this.editor.getConfiguration().contribInfo.formatOnPaste) {
|
||||
@@ -198,7 +201,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
this._callOnModel.add(this.editor.onDidPaste(range => this._trigger(range)));
|
||||
this._callOnModel.push(this.editor.onDidPaste(range => this._trigger(range)));
|
||||
}
|
||||
|
||||
private _trigger(range: Range): void {
|
||||
|
||||
@@ -25,7 +25,7 @@ import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition, getDeclarationsAtPosition } from './goToDefinition';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { EditorStateCancellationTokenSource, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
|
||||
@@ -58,7 +58,7 @@ export class DefinitionAction extends EditorAction {
|
||||
}
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
const editorService = accessor.get(ICodeEditorService);
|
||||
const progressService = accessor.get(ILocalProgressService);
|
||||
const progressService = accessor.get(IProgressService);
|
||||
const symbolNavService = accessor.get(ISymbolNavigationService);
|
||||
|
||||
const model = editor.getModel();
|
||||
@@ -176,6 +176,7 @@ export class DefinitionAction extends EditorAction {
|
||||
resource: reference.uri,
|
||||
options: {
|
||||
selection: Range.collapseToStart(range),
|
||||
revealIfOpened: true,
|
||||
revealInCenterIfOutsideViewport: true
|
||||
}
|
||||
}, editor, sideBySide);
|
||||
|
||||
@@ -13,11 +13,11 @@ import { registerEditorCommand, EditorCommand } from 'vs/editor/browser/editorEx
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { dispose, IDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, dispose, combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export const ctxHasSymbols = new RawContextKey('hasSymbols', false);
|
||||
|
||||
@@ -38,14 +38,14 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
|
||||
private _currentModel?: ReferencesModel = undefined;
|
||||
private _currentIdx: number = -1;
|
||||
private _currentState?: IDisposable;
|
||||
private _currentMessage?: IDisposable;
|
||||
private _currentDisposables: IDisposable[] = [];
|
||||
private _currentMessage?: IDisposable = undefined;
|
||||
private _ignoreEditorChange: boolean = false;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ICodeEditorService private readonly _editorService: ICodeEditorService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IStatusbarService private readonly _statusbarService: IStatusbarService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
) {
|
||||
this._ctxHasSymbols = ctxHasSymbols.bindTo(contextKeyService);
|
||||
@@ -53,7 +53,7 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
|
||||
reset(): void {
|
||||
this._ctxHasSymbols.reset();
|
||||
dispose(this._currentState);
|
||||
dispose(this._currentDisposables);
|
||||
dispose(this._currentMessage);
|
||||
this._currentModel = undefined;
|
||||
this._currentIdx = -1;
|
||||
@@ -72,8 +72,8 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
this._ctxHasSymbols.set(true);
|
||||
this._showMessage();
|
||||
|
||||
const editorState = new EditorState(this._editorService);
|
||||
const listener = editorState.onDidChange(_ => {
|
||||
const editorStatus = new EditorStatus(this._editorService);
|
||||
const listener = editorStatus.onDidChange(_ => {
|
||||
|
||||
if (this._ignoreEditorChange) {
|
||||
return;
|
||||
@@ -104,7 +104,7 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
}
|
||||
});
|
||||
|
||||
this._currentState = combinedDisposable(editorState, listener);
|
||||
this._currentDisposables = [editorStatus, listener];
|
||||
}
|
||||
|
||||
revealNext(source: ICodeEditor): Promise<any> {
|
||||
@@ -126,7 +126,8 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
resource: reference.uri,
|
||||
options: {
|
||||
selection: Range.collapseToStart(reference.range),
|
||||
revealInCenterIfOutsideViewport: true
|
||||
revealInCenterIfOutsideViewport: true,
|
||||
revealIfOpened: true
|
||||
}
|
||||
}, source).finally(() => {
|
||||
this._ignoreEditorChange = false;
|
||||
@@ -140,10 +141,10 @@ class SymbolNavigationService implements ISymbolNavigationService {
|
||||
|
||||
const kb = this._keybindingService.lookupKeybinding('editor.gotoNextSymbolFromResult');
|
||||
const message = kb
|
||||
? localize('location.kb', "Symbol {0} of {1}, {2} for next", this._currentIdx + 1, this._currentModel!.references.length, kb.getLabel())
|
||||
? localize('location.kb', "Symbol {0} of {1}, press {2} to reveal next", this._currentIdx + 1, this._currentModel!.references.length, kb.getLabel())
|
||||
: localize('location', "Symbol {0} of {1}", this._currentIdx + 1, this._currentModel!.references.length);
|
||||
|
||||
this._currentMessage = this._notificationService.status(message);
|
||||
this._currentMessage = this._statusbarService.setStatusMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,31 +183,26 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
|
||||
//
|
||||
|
||||
class EditorState {
|
||||
class EditorStatus extends Disposable {
|
||||
|
||||
private readonly _listener = new Map<ICodeEditor, IDisposable>();
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
private readonly _onDidChange = new Emitter<{ editor: ICodeEditor }>();
|
||||
readonly onDidChange: Event<{ editor: ICodeEditor }> = this._onDidChange.event;
|
||||
|
||||
constructor(@ICodeEditorService editorService: ICodeEditorService) {
|
||||
this._disposables.add(editorService.onCodeEditorRemove(this._onDidRemoveEditor, this));
|
||||
this._disposables.add(editorService.onCodeEditorAdd(this._onDidAddEditor, this));
|
||||
super();
|
||||
this._register(this._onDidChange);
|
||||
this._register(editorService.onCodeEditorRemove(this._onDidRemoveEditor, this));
|
||||
this._register(editorService.onCodeEditorAdd(this._onDidAddEditor, this));
|
||||
editorService.listCodeEditors().forEach(this._onDidAddEditor, this);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
this._onDidChange.dispose();
|
||||
this._listener.forEach(dispose);
|
||||
}
|
||||
|
||||
private _onDidAddEditor(editor: ICodeEditor): void {
|
||||
this._listener.set(editor, combinedDisposable(
|
||||
this._listener.set(editor, combinedDisposable([
|
||||
editor.onDidChangeCursorPosition(_ => this._onDidChange.fire({ editor })),
|
||||
editor.onDidChangeModelContent(_ => this._onDidChange.fire({ editor })),
|
||||
));
|
||||
]));
|
||||
}
|
||||
|
||||
private _onDidRemoveEditor(editor: ICodeEditor): void {
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
import 'vs/css!./media/gotoErrorWidget';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerColor, oneOf, textLinkForeground, editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoForeground, editorInfoBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerColor, oneOf, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IThemeService, ITheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoForeground, editorInfoBorder } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
@@ -26,7 +27,6 @@ import { IAction } from 'vs/base/common/actions';
|
||||
import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { peekViewTitleForeground, peekViewTitleInfoForeground } from 'vs/editor/contrib/referenceSearch/referencesWidget';
|
||||
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
|
||||
|
||||
class MessageWidget {
|
||||
|
||||
@@ -168,9 +168,8 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
|
||||
private _parentContainer: HTMLElement;
|
||||
private _container: HTMLElement;
|
||||
private _icon: HTMLElement;
|
||||
private _message: MessageWidget;
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private _callOnDispose: IDisposable[] = [];
|
||||
private _severity: MarkerSeverity;
|
||||
private _backgroundColor?: Color;
|
||||
private _onDidSelectRelatedInformation = new Emitter<IRelatedInformation>();
|
||||
@@ -180,7 +179,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
private readonly actions: ReadonlyArray<IAction>,
|
||||
private readonly actions: IAction[],
|
||||
private readonly _themeService: IThemeService
|
||||
) {
|
||||
super(editor, { showArrow: true, showFrame: true, isAccessible: true });
|
||||
@@ -188,7 +187,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
this._backgroundColor = Color.white;
|
||||
|
||||
this._applyTheme(_themeService.getTheme());
|
||||
this._callOnDispose.add(_themeService.onThemeChange(this._applyTheme.bind(this)));
|
||||
this._callOnDispose.push(_themeService.onThemeChange(this._applyTheme.bind(this)));
|
||||
|
||||
this.create();
|
||||
}
|
||||
@@ -219,7 +218,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._callOnDispose.dispose();
|
||||
this._callOnDispose = dispose(this._callOnDispose);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -232,10 +231,6 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
this._actionbarWidget.push(this.actions, { label: false, icon: true });
|
||||
}
|
||||
|
||||
protected _fillTitleIcon(container: HTMLElement): void {
|
||||
this._icon = dom.append(container, dom.$(''));
|
||||
}
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {
|
||||
orientation: ActionsOrientation.HORIZONTAL_REVERSE
|
||||
@@ -252,7 +247,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
container.appendChild(this._container);
|
||||
|
||||
this._message = new MessageWidget(this._container, this.editor, related => this._onDidSelectRelatedInformation.fire(related));
|
||||
this._disposables.add(this._message);
|
||||
this._disposables.push(this._message);
|
||||
}
|
||||
|
||||
show(where: Position, heightInLines: number): void {
|
||||
@@ -283,7 +278,13 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
: nls.localize('change', "{0} of {1} problem", markerIdx, markerCount);
|
||||
this.setTitle(basename(model.uri), detail);
|
||||
}
|
||||
this._icon.className = SeverityIcon.className(MarkerSeverity.toSeverity(this._severity));
|
||||
let headingIconClassName = 'error';
|
||||
if (this._severity === MarkerSeverity.Warning) {
|
||||
headingIconClassName = 'warning';
|
||||
} else if (this._severity === MarkerSeverity.Info) {
|
||||
headingIconClassName = 'info';
|
||||
}
|
||||
this.setTitleIcon(headingIconClassName);
|
||||
|
||||
this.editor.revealPositionInCenter(position, ScrollType.Smooth);
|
||||
|
||||
|
||||
@@ -5,10 +5,28 @@
|
||||
|
||||
/* marker zone */
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .severity-icon {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
margin-right: 4px;
|
||||
.monaco-editor .peekview-widget .head .peekview-title .icon.warning {
|
||||
background: url('status-warning.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .icon.error {
|
||||
background: url('status-error.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .icon.info {
|
||||
background: url('status-info.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-editor .peekview-widget .head .peekview-title .icon.warning {
|
||||
background: url('status-warning-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-editor .peekview-widget .head .peekview-title .icon.error {
|
||||
background: url('status-error-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-editor .peekview-widget .head .peekview-title .icon.info {
|
||||
background: url('status-info-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor .marker-widget {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16" width="16"><circle cx="8" cy="8" r="6" fill="#1E1E1E"/><path d="M8 3C5.238 3 3 5.238 3 8s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm3 7l-1 1-2-2-2 2-1-1 2-2.027L5 6l1-1 2 2 2-2 1 1-2 1.973L11 10z" fill="#F48771"/><path fill="#252526" d="M11 6l-1-1-2 2-2-2-1 1 2 1.973L5 10l1 1 2-2 2 2 1-1-2-2.027z"/></svg>
|
||||
|
After Width: | Height: | Size: 372 B |
1
src/vs/editor/contrib/gotoError/media/status-error.svg
Normal file
1
src/vs/editor/contrib/gotoError/media/status-error.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8" cy="8" r="6" fill="#F6F6F6"/><path d="M8 3C5.238 3 3 5.238 3 8s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm3 7l-1 1-2-2-2 2-1-1 2-2.027L5 6l1-1 2 2 2-2 1 1-2 1.973L11 10z" fill="#E51400"/><path fill="#fff" d="M11 6l-1-1-2 2-2-2-1 1 2 1.973L5 10l1 1 2-2 2 2 1-1-2-2.027z"/></svg>
|
||||
|
After Width: | Height: | Size: 403 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#1E1E1E"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="#1BA1E2"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#252526"/></svg>
|
||||
|
After Width: | Height: | Size: 356 B |
1
src/vs/editor/contrib/gotoError/media/status-info.svg
Normal file
1
src/vs/editor/contrib/gotoError/media/status-info.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#F6F6F6"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="#1BA1E2"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 353 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="#fc0"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>
|
||||
|
After Width: | Height: | Size: 263 B |
1
src/vs/editor/contrib/gotoError/media/status-warning.svg
Normal file
1
src/vs/editor/contrib/gotoError/media/status-warning.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="#fc0"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>
|
||||
|
After Width: | Height: | Size: 297 B |
@@ -7,7 +7,7 @@ import 'vs/css!./hover';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
@@ -34,7 +34,7 @@ export class ModesHoverController implements IEditorContribution {
|
||||
|
||||
private static readonly ID = 'editor.contrib.hover';
|
||||
|
||||
private readonly _toUnhook = new DisposableStore();
|
||||
private _toUnhook: IDisposable[];
|
||||
private readonly _didChangeConfigurationHandler: IDisposable;
|
||||
|
||||
private _contentWidget: ModesContentHoverWidget;
|
||||
@@ -73,6 +73,8 @@ export class ModesHoverController implements IEditorContribution {
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IThemeService private readonly _themeService: IThemeService
|
||||
) {
|
||||
this._toUnhook = [];
|
||||
|
||||
this._isMouseDown = false;
|
||||
this._hoverClicked = false;
|
||||
|
||||
@@ -94,22 +96,22 @@ export class ModesHoverController implements IEditorContribution {
|
||||
this._isHoverEnabled = hoverOpts.enabled;
|
||||
this._isHoverSticky = hoverOpts.sticky;
|
||||
if (this._isHoverEnabled) {
|
||||
this._toUnhook.add(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e)));
|
||||
this._toUnhook.add(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(e)));
|
||||
this._toUnhook.add(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onEditorMouseMove(e)));
|
||||
this._toUnhook.add(this._editor.onKeyDown((e: IKeyboardEvent) => this._onKeyDown(e)));
|
||||
this._toUnhook.add(this._editor.onDidChangeModelDecorations(() => this._onModelDecorationsChanged()));
|
||||
this._toUnhook.push(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e)));
|
||||
this._toUnhook.push(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(e)));
|
||||
this._toUnhook.push(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onEditorMouseMove(e)));
|
||||
this._toUnhook.push(this._editor.onKeyDown((e: IKeyboardEvent) => this._onKeyDown(e)));
|
||||
this._toUnhook.push(this._editor.onDidChangeModelDecorations(() => this._onModelDecorationsChanged()));
|
||||
} else {
|
||||
this._toUnhook.add(this._editor.onMouseMove(hideWidgetsEventHandler));
|
||||
this._toUnhook.push(this._editor.onMouseMove(hideWidgetsEventHandler));
|
||||
}
|
||||
|
||||
this._toUnhook.add(this._editor.onMouseLeave(hideWidgetsEventHandler));
|
||||
this._toUnhook.add(this._editor.onDidChangeModel(hideWidgetsEventHandler));
|
||||
this._toUnhook.add(this._editor.onDidScrollChange((e: IScrollEvent) => this._onEditorScrollChanged(e)));
|
||||
this._toUnhook.push(this._editor.onMouseLeave(hideWidgetsEventHandler));
|
||||
this._toUnhook.push(this._editor.onDidChangeModel(hideWidgetsEventHandler));
|
||||
this._toUnhook.push(this._editor.onDidScrollChange((e: IScrollEvent) => this._onEditorScrollChanged(e)));
|
||||
}
|
||||
|
||||
private _unhookEvents(): void {
|
||||
this._toUnhook.clear();
|
||||
this._toUnhook = dispose(this._toUnhook);
|
||||
}
|
||||
|
||||
private _onModelDecorationsChanged(): void {
|
||||
@@ -225,7 +227,6 @@ export class ModesHoverController implements IEditorContribution {
|
||||
|
||||
public dispose(): void {
|
||||
this._unhookEvents();
|
||||
this._toUnhook.dispose();
|
||||
this._didChangeConfigurationHandler.dispose();
|
||||
|
||||
if (this._glyphWidget) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
@@ -24,6 +25,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
protected _showAtRange: Range | null;
|
||||
private _stoleFocus: boolean;
|
||||
private readonly scrollbar: DomScrollableElement;
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
// Editor.IContentWidget.allowEditorOverflow
|
||||
public allowEditorOverflow = true;
|
||||
@@ -51,7 +53,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
this._domNode.className = 'monaco-editor-hover-content';
|
||||
|
||||
this.scrollbar = new DomScrollableElement(this._domNode, {});
|
||||
this._register(this.scrollbar);
|
||||
this.disposables.push(this.scrollbar);
|
||||
this._containerDomNode.appendChild(this.scrollbar.getDomNode());
|
||||
|
||||
this.onkeydown(this._containerDomNode, (e: IKeyboardEvent) => {
|
||||
@@ -127,6 +129,7 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
|
||||
public dispose(): void {
|
||||
this._editor.removeContentWidget(this);
|
||||
this.disposables = dispose(this.disposables);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { IMarkdownString, MarkdownString, isEmptyMarkdownString, markedStringsEquals } from 'vs/base/common/htmlContent';
|
||||
import { Disposable, IDisposable, toDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
@@ -187,10 +187,6 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
|
||||
}
|
||||
}
|
||||
|
||||
interface ActionSet extends IDisposable {
|
||||
readonly actions: Action[];
|
||||
}
|
||||
|
||||
export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
|
||||
static readonly ID = 'editor.contrib.modesContentHoverWidget';
|
||||
@@ -440,7 +436,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
this.updateContents(fragment);
|
||||
this._colorPicker.layout();
|
||||
|
||||
this.renderDisposable = combinedDisposable(colorListener, colorChangeListener, widget, ...markdownDisposeables);
|
||||
this.renderDisposable = combinedDisposable([colorListener, colorChangeListener, widget, ...markdownDisposeables]);
|
||||
});
|
||||
} else {
|
||||
if (msg instanceof MarkerHover) {
|
||||
@@ -530,25 +526,24 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
|
||||
private renderMarkerStatusbar(markerHover: MarkerHover): HTMLElement {
|
||||
const hoverElement = $('div.hover-row.status-bar');
|
||||
const disposables = new DisposableStore();
|
||||
const disposables: IDisposable[] = [];
|
||||
const actionsElement = dom.append(hoverElement, $('div.actions'));
|
||||
disposables.add(this.renderAction(actionsElement, {
|
||||
disposables.push(this.renderAction(actionsElement, {
|
||||
label: nls.localize('quick fixes', "Quick Fix..."),
|
||||
commandId: QuickFixAction.Id,
|
||||
run: async (target) => {
|
||||
const codeActionsPromise = this.getCodeActions(markerHover.marker);
|
||||
disposables.add(toDisposable(() => codeActionsPromise.cancel()));
|
||||
disposables.push(toDisposable(() => codeActionsPromise.cancel()));
|
||||
const actions = await codeActionsPromise;
|
||||
disposables.add(actions);
|
||||
const elementPosition = dom.getDomNodePagePosition(target);
|
||||
this._contextMenuService.showContextMenu({
|
||||
getAnchor: () => ({ x: elementPosition.left + 6, y: elementPosition.top + elementPosition.height + 6 }),
|
||||
getActions: () => actions.actions
|
||||
getActions: () => actions
|
||||
});
|
||||
}
|
||||
}));
|
||||
if (markerHover.marker.severity === MarkerSeverity.Error || markerHover.marker.severity === MarkerSeverity.Warning || markerHover.marker.severity === MarkerSeverity.Info) {
|
||||
disposables.add(this.renderAction(actionsElement, {
|
||||
disposables.push(this.renderAction(actionsElement, {
|
||||
label: nls.localize('peek problem', "Peek Problem"),
|
||||
commandId: NextMarkerAction.ID,
|
||||
run: () => {
|
||||
@@ -558,37 +553,24 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
}
|
||||
}));
|
||||
}
|
||||
this.renderDisposable = disposables;
|
||||
this.renderDisposable = combinedDisposable(disposables);
|
||||
return hoverElement;
|
||||
}
|
||||
|
||||
private getCodeActions(marker: IMarker): CancelablePromise<ActionSet> {
|
||||
private getCodeActions(marker: IMarker): CancelablePromise<Action[]> {
|
||||
return createCancelablePromise(async cancellationToken => {
|
||||
const codeActions = await getCodeActions(this._editor.getModel()!, new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn), { type: 'manual', filter: { kind: CodeActionKind.QuickFix } }, cancellationToken);
|
||||
if (codeActions.actions.length) {
|
||||
const disposables = new DisposableStore();
|
||||
const actions: Action[] = [];
|
||||
for (const codeAction of codeActions.actions) {
|
||||
disposables.add(disposables);
|
||||
actions.push(new Action(
|
||||
codeAction.command ? codeAction.command.id : codeAction.title,
|
||||
codeAction.title,
|
||||
undefined,
|
||||
true,
|
||||
() => applyCodeAction(codeAction, this._bulkEditService, this._commandService)));
|
||||
}
|
||||
return {
|
||||
actions: actions,
|
||||
dispose: () => disposables.dispose()
|
||||
};
|
||||
return codeActions.actions.map(codeAction => new Action(
|
||||
codeAction.command ? codeAction.command.id : codeAction.title,
|
||||
codeAction.title,
|
||||
undefined,
|
||||
true,
|
||||
() => applyCodeAction(codeAction, this._bulkEditService, this._commandService)));
|
||||
}
|
||||
|
||||
return {
|
||||
actions: [
|
||||
new Action('', nls.localize('editor.action.quickFix.noneMessage', "No code actions available"))
|
||||
],
|
||||
dispose() { }
|
||||
};
|
||||
return [
|
||||
new Action('', nls.localize('editor.action.quickFix.noneMessage', "No code actions available"))
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ export class Link implements ILink {
|
||||
toJSON(): ILink {
|
||||
return {
|
||||
range: this.range,
|
||||
url: this.url,
|
||||
tooltip: this.tooltip
|
||||
url: this.url
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,10 +39,6 @@ export class Link implements ILink {
|
||||
return this._link.url;
|
||||
}
|
||||
|
||||
get tooltip(): string | undefined {
|
||||
return this._link.tooltip;
|
||||
}
|
||||
|
||||
resolve(token: CancellationToken): Promise<URI> {
|
||||
if (this._link.url) {
|
||||
try {
|
||||
@@ -148,14 +143,7 @@ export function getLinks(model: ITextModel, token: CancellationToken): Promise<L
|
||||
}, onUnexpectedExternalError);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
const result = new LinksList(coalesce(lists));
|
||||
if (!token.isCancellationRequested) {
|
||||
return result;
|
||||
}
|
||||
result.dispose();
|
||||
return new LinksList([]);
|
||||
});
|
||||
return Promise.all(promises).then(() => new LinksList(coalesce(lists)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -111,23 +111,6 @@ class LinkOccurrence {
|
||||
}
|
||||
|
||||
private static _getOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions {
|
||||
const options = { ...this._getBaseOptions(link, useMetaKey, isActive) };
|
||||
if (typeof link.tooltip === 'string') {
|
||||
const message = new MarkdownString().appendText(
|
||||
platform.isMacintosh
|
||||
? useMetaKey
|
||||
? nls.localize('links.custom.mac', "Cmd + click to {0}", link.tooltip)
|
||||
: nls.localize('links.custom.mac.al', "Option + click to {0}", link.tooltip)
|
||||
: useMetaKey
|
||||
? nls.localize('links.custom', "Ctrl + click to {0}", link.tooltip)
|
||||
: nls.localize('links.custom.al', "Alt + click to {0}", link.tooltip)
|
||||
);
|
||||
options.hoverMessage = message;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
private static _getBaseOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions {
|
||||
if (link.url && /^command:/i.test(link.url.toString())) {
|
||||
if (useMetaKey) {
|
||||
return (isActive ? decoration.metaCommandActive : decoration.metaCommand);
|
||||
|
||||
@@ -78,7 +78,7 @@ export class MarkdownRenderer {
|
||||
}
|
||||
|
||||
render(markdown: IMarkdownString | undefined): IMarkdownRenderResult {
|
||||
const disposeables: IDisposable[] = [];
|
||||
let disposeables: IDisposable[] = [];
|
||||
|
||||
let element: HTMLElement;
|
||||
if (!markdown) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { RevealTarget } from 'vs/editor/common/controller/cursorCommon';
|
||||
@@ -427,7 +427,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito
|
||||
private readonly _editor: ICodeEditor;
|
||||
private _ignoreSelectionChange: boolean;
|
||||
private _session: MultiCursorSession | null;
|
||||
private readonly _sessionDispose = this._register(new DisposableStore());
|
||||
private _sessionDispose: IDisposable[];
|
||||
|
||||
public static get(editor: ICodeEditor): MultiCursorSelectionController {
|
||||
return editor.getContribution<MultiCursorSelectionController>(MultiCursorSelectionController.ID);
|
||||
@@ -438,6 +438,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito
|
||||
this._editor = editor;
|
||||
this._ignoreSelectionChange = false;
|
||||
this._session = null;
|
||||
this._sessionDispose = [];
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -467,25 +468,27 @@ export class MultiCursorSelectionController extends Disposable implements IEdito
|
||||
}
|
||||
findController.getState().change(newState, false);
|
||||
|
||||
this._sessionDispose.add(this._editor.onDidChangeCursorSelection((e) => {
|
||||
if (this._ignoreSelectionChange) {
|
||||
return;
|
||||
}
|
||||
this._endSession();
|
||||
}));
|
||||
this._sessionDispose.add(this._editor.onDidBlurEditorText(() => {
|
||||
this._endSession();
|
||||
}));
|
||||
this._sessionDispose.add(findController.getState().onFindReplaceStateChange((e) => {
|
||||
if (e.matchCase || e.wholeWord) {
|
||||
this._sessionDispose = [
|
||||
this._editor.onDidChangeCursorSelection((e) => {
|
||||
if (this._ignoreSelectionChange) {
|
||||
return;
|
||||
}
|
||||
this._endSession();
|
||||
}
|
||||
}));
|
||||
}),
|
||||
this._editor.onDidBlurEditorText(() => {
|
||||
this._endSession();
|
||||
}),
|
||||
findController.getState().onFindReplaceStateChange((e) => {
|
||||
if (e.matchCase || e.wholeWord) {
|
||||
this._endSession();
|
||||
}
|
||||
})
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private _endSession(): void {
|
||||
this._sessionDispose.clear();
|
||||
this._sessionDispose = dispose(this._sessionDispose);
|
||||
if (this._session && this._session.isDisconnectedFromFindController) {
|
||||
const newState: INewFindReplaceState = {
|
||||
wholeWordOverride: FindOptionOverride.NotSet,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { domEvent, stop } from 'vs/base/browser/event';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import 'vs/css!./parameterHints';
|
||||
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -25,12 +25,12 @@ import { ParameterHintsModel, TriggerContext } from 'vs/editor/contrib/parameter
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
export class ParameterHintsWidget extends Disposable implements IContentWidget, IDisposable {
|
||||
export class ParameterHintsWidget implements IContentWidget, IDisposable {
|
||||
|
||||
private static readonly ID = 'editor.widget.parameterHintsWidget';
|
||||
|
||||
private readonly markdownRenderer: MarkdownRenderer;
|
||||
private readonly renderDisposeables = this._register(new DisposableStore());
|
||||
private renderDisposeables: IDisposable[];
|
||||
private model: ParameterHintsModel | null;
|
||||
private readonly keyVisible: IContextKey<boolean>;
|
||||
private readonly keyMultipleSignatures: IContextKey<boolean>;
|
||||
@@ -41,6 +41,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
private visible: boolean;
|
||||
private announcedLabel: string | null;
|
||||
private scrollbar: DomScrollableElement;
|
||||
private disposables: IDisposable[];
|
||||
|
||||
// Editor.IContentWidget.allowEditorOverflow
|
||||
allowEditorOverflow = true;
|
||||
@@ -51,14 +52,14 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@IModeService modeService: IModeService,
|
||||
) {
|
||||
super();
|
||||
this.markdownRenderer = new MarkdownRenderer(editor, modeService, openerService);
|
||||
this.model = new ParameterHintsModel(editor);
|
||||
this.keyVisible = Context.Visible.bindTo(contextKeyService);
|
||||
this.keyMultipleSignatures = Context.MultipleSignatures.bindTo(contextKeyService);
|
||||
this.visible = false;
|
||||
this.disposables = [];
|
||||
|
||||
this._register(this.model.onChangedHints(newParameterHints => {
|
||||
this.disposables.push(this.model.onChangedHints(newParameterHints => {
|
||||
if (newParameterHints) {
|
||||
this.show();
|
||||
this.render(newParameterHints);
|
||||
@@ -78,16 +79,16 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
const next = dom.append(buttons, $('.button.next'));
|
||||
|
||||
const onPreviousClick = stop(domEvent(previous, 'click'));
|
||||
this._register(onPreviousClick(this.previous, this));
|
||||
onPreviousClick(this.previous, this, this.disposables);
|
||||
|
||||
const onNextClick = stop(domEvent(next, 'click'));
|
||||
this._register(onNextClick(this.next, this));
|
||||
onNextClick(this.next, this, this.disposables);
|
||||
|
||||
this.overloads = dom.append(wrapper, $('.overloads'));
|
||||
|
||||
const body = $('.body');
|
||||
this.scrollbar = new DomScrollableElement(body, {});
|
||||
this._register(this.scrollbar);
|
||||
this.disposables.push(this.scrollbar);
|
||||
wrapper.appendChild(this.scrollbar.getDomNode());
|
||||
|
||||
this.signature = dom.append(body, $('.signature'));
|
||||
@@ -98,7 +99,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
this.hide();
|
||||
|
||||
this.element.style.userSelect = 'text';
|
||||
this._register(this.editor.onDidChangeCursorSelection(e => {
|
||||
this.disposables.push(this.editor.onDidChangeCursorSelection(e => {
|
||||
if (this.visible) {
|
||||
this.editor.layoutContentWidget(this);
|
||||
}
|
||||
@@ -111,11 +112,11 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
|
||||
updateFont();
|
||||
|
||||
this._register(Event.chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
|
||||
Event.chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
|
||||
.filter(e => e.fontInfo)
|
||||
.on(updateFont, null));
|
||||
.on(updateFont, null, this.disposables);
|
||||
|
||||
this._register(this.editor.onDidLayoutChange(e => this.updateMaxHeight()));
|
||||
this.disposables.push(this.editor.onDidLayoutChange(e => this.updateMaxHeight()));
|
||||
this.updateMaxHeight();
|
||||
}
|
||||
|
||||
@@ -189,7 +190,8 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
this.renderParameters(code, signature, hints.activeParameter);
|
||||
}
|
||||
|
||||
this.renderDisposeables.clear();
|
||||
dispose(this.renderDisposeables);
|
||||
this.renderDisposeables = [];
|
||||
|
||||
const activeParameter = signature.parameters[hints.activeParameter];
|
||||
|
||||
@@ -200,7 +202,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
} else {
|
||||
const renderedContents = this.markdownRenderer.render(activeParameter.documentation);
|
||||
dom.addClass(renderedContents.element, 'markdown-docs');
|
||||
this.renderDisposeables.add(renderedContents);
|
||||
this.renderDisposeables.push(renderedContents);
|
||||
documentation.appendChild(renderedContents.element);
|
||||
}
|
||||
dom.append(this.docs, $('p', {}, documentation));
|
||||
@@ -214,7 +216,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
} else {
|
||||
const renderedContents = this.markdownRenderer.render(signature.documentation);
|
||||
dom.addClass(renderedContents.element, 'markdown-docs');
|
||||
this.renderDisposeables.add(renderedContents);
|
||||
this.renderDisposeables.push(renderedContents);
|
||||
dom.append(this.docs, renderedContents.element);
|
||||
}
|
||||
|
||||
@@ -321,7 +323,8 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget,
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.disposables = dispose(this.disposables);
|
||||
this.renderDisposeables = dispose(this.renderDisposeables);
|
||||
|
||||
if (this.model) {
|
||||
this.model.dispose();
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .icon {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
vertical-align: text-bottom;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .dirname:not(:empty) {
|
||||
font-size: 0.9em;
|
||||
margin-left: 0.5em;
|
||||
|
||||
@@ -85,6 +85,7 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
private _onDidClose = new Emitter<PeekViewWidget>();
|
||||
|
||||
protected _headElement: HTMLDivElement;
|
||||
protected _headingIcon: HTMLElement;
|
||||
protected _primaryHeading: HTMLElement;
|
||||
protected _secondaryHeading: HTMLElement;
|
||||
protected _metaHeading: HTMLElement;
|
||||
@@ -154,18 +155,18 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
dom.append(this._headElement, titleElement);
|
||||
dom.addStandardDisposableListener(titleElement, 'click', event => this._onTitleClick(event));
|
||||
|
||||
this._fillTitleIcon(titleElement);
|
||||
this._headingIcon = dom.$('span');
|
||||
this._primaryHeading = dom.$('span.filename');
|
||||
this._secondaryHeading = dom.$('span.dirname');
|
||||
this._metaHeading = dom.$('span.meta');
|
||||
dom.append(titleElement, this._primaryHeading, this._secondaryHeading, this._metaHeading);
|
||||
dom.append(titleElement, this._headingIcon, this._primaryHeading, this._secondaryHeading, this._metaHeading);
|
||||
|
||||
const actionsContainer = dom.$('.peekview-actions');
|
||||
dom.append(this._headElement, actionsContainer);
|
||||
|
||||
const actionBarOptions = this._getActionBarOptions();
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, actionBarOptions);
|
||||
this._disposables.add(this._actionbarWidget);
|
||||
this._disposables.push(this._actionbarWidget);
|
||||
|
||||
this._actionbarWidget.push(new Action('peekview.close', nls.localize('label.close', "Close"), 'close-peekview-action', true, () => {
|
||||
this.dispose();
|
||||
@@ -173,9 +174,6 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
}), { label: false, icon: true });
|
||||
}
|
||||
|
||||
protected _fillTitleIcon(container: HTMLElement): void {
|
||||
}
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {};
|
||||
}
|
||||
@@ -184,6 +182,10 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
// implement me
|
||||
}
|
||||
|
||||
public setTitleIcon(iconClassName: string): void {
|
||||
this._headingIcon.className = iconClassName ? `icon ${iconClassName}` : '';
|
||||
}
|
||||
|
||||
public setTitle(primaryHeading: string, secondaryHeading?: string): void {
|
||||
this._primaryHeading.innerHTML = strings.escape(primaryHeading);
|
||||
this._primaryHeading.setAttribute('aria-label', primaryHeading);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -32,11 +32,11 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
|
||||
private static readonly ID = 'editor.contrib.referencesController';
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
private readonly _editor: ICodeEditor;
|
||||
private _widget: ReferenceWidget | null;
|
||||
private _model: ReferencesModel | null;
|
||||
private _requestIdPool = 0;
|
||||
private _disposables: IDisposable[] = [];
|
||||
private _ignoreModelChangeEvent = false;
|
||||
|
||||
private readonly _referenceSearchVisible: IContextKey<boolean>;
|
||||
@@ -91,8 +91,8 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
this._referenceSearchVisible.set(true);
|
||||
|
||||
// close the widget on model/mode changes
|
||||
this._disposables.add(this._editor.onDidChangeModelLanguage(() => { this.closeWidget(); }));
|
||||
this._disposables.add(this._editor.onDidChangeModel(() => {
|
||||
this._disposables.push(this._editor.onDidChangeModelLanguage(() => { this.closeWidget(); }));
|
||||
this._disposables.push(this._editor.onDidChangeModel(() => {
|
||||
if (!this._ignoreModelChangeEvent) {
|
||||
this.closeWidget();
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
this._widget.setTitle(nls.localize('labelLoading', "Loading..."));
|
||||
this._widget.show(range);
|
||||
|
||||
this._disposables.add(this._widget.onDidClose(() => {
|
||||
this._disposables.push(this._widget.onDidClose(() => {
|
||||
modelPromise.cancel();
|
||||
if (this._widget) {
|
||||
this._storageService.store(storageKey, JSON.stringify(this._widget.layoutData), StorageScope.GLOBAL);
|
||||
@@ -112,7 +112,7 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
this.closeWidget();
|
||||
}));
|
||||
|
||||
this._disposables.add(this._widget.onDidSelectReference(event => {
|
||||
this._disposables.push(this._widget.onDidSelectReference(event => {
|
||||
let { element, kind } = event;
|
||||
switch (kind) {
|
||||
case 'open':
|
||||
@@ -205,7 +205,7 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
|
||||
this._widget = null;
|
||||
}
|
||||
this._referenceSearchVisible.reset();
|
||||
this._disposables.clear();
|
||||
this._disposables = dispose(this._disposables);
|
||||
if (this._model) {
|
||||
dispose(this._model);
|
||||
this._model = null;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { localize } from 'vs/nls';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
import { IDisposable, dispose, IReference, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { defaultGenerator } from 'vs/base/common/idGenerator';
|
||||
@@ -14,7 +14,6 @@ import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { Location, LocationLink } from 'vs/editor/common/modes';
|
||||
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { IMatch } from 'vs/base/common/filters';
|
||||
|
||||
export class OneReference {
|
||||
readonly id: string;
|
||||
@@ -62,7 +61,7 @@ export class FilePreview implements IDisposable {
|
||||
dispose(this._modelReference);
|
||||
}
|
||||
|
||||
preview(range: IRange, n: number = 8): { value: string; highlight: IMatch } | undefined {
|
||||
preview(range: IRange, n: number = 8): { before: string; inside: string; after: string } | undefined {
|
||||
const model = this._modelReference.object.textEditorModel;
|
||||
|
||||
if (!model) {
|
||||
@@ -74,14 +73,13 @@ export class FilePreview implements IDisposable {
|
||||
const beforeRange = new Range(startLineNumber, word.startColumn, startLineNumber, startColumn);
|
||||
const afterRange = new Range(endLineNumber, endColumn, endLineNumber, Number.MAX_VALUE);
|
||||
|
||||
const before = model.getValueInRange(beforeRange).replace(/^\s+/, strings.empty);
|
||||
const inside = model.getValueInRange(range);
|
||||
const after = model.getValueInRange(afterRange).replace(/\s+$/, strings.empty);
|
||||
|
||||
return {
|
||||
value: before + inside + after,
|
||||
highlight: { start: before.length, end: before.length + inside.length }
|
||||
const ret = {
|
||||
before: model.getValueInRange(beforeRange).replace(/^\s+/, strings.empty),
|
||||
inside: model.getValueInRange(range),
|
||||
after: model.getValueInRange(afterRange).replace(/\s+$/, strings.empty)
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +164,7 @@ export class FileReferences implements IDisposable {
|
||||
|
||||
export class ReferencesModel implements IDisposable {
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
private readonly _disposables: IDisposable[];
|
||||
readonly groups: FileReferences[] = [];
|
||||
readonly references: OneReference[] = [];
|
||||
|
||||
@@ -174,7 +172,7 @@ export class ReferencesModel implements IDisposable {
|
||||
readonly onDidChangeReferenceRange: Event<OneReference> = this._onDidChangeReferenceRange.event;
|
||||
|
||||
constructor(references: LocationLink[]) {
|
||||
|
||||
this._disposables = [];
|
||||
// grouping and sorting
|
||||
const [providersFirst] = references;
|
||||
references.sort(ReferencesModel._compareReferences);
|
||||
@@ -192,7 +190,7 @@ export class ReferencesModel implements IDisposable {
|
||||
|| !Range.equalsRange(ref.range, current.children[current.children.length - 1].range)) {
|
||||
|
||||
let oneRef = new OneReference(current, ref.targetSelectionRange || ref.range, providersFirst === ref);
|
||||
this._disposables.add(oneRef.onRefChanged((e) => this._onDidChangeReferenceRange.fire(e)));
|
||||
this._disposables.push(oneRef.onRefChanged((e) => this._onDidChangeReferenceRange.fire(e)));
|
||||
this.references.push(oneRef);
|
||||
current.children.push(oneRef);
|
||||
}
|
||||
@@ -282,8 +280,9 @@ export class ReferencesModel implements IDisposable {
|
||||
|
||||
dispose(): void {
|
||||
dispose(this.groups);
|
||||
this._disposables.dispose();
|
||||
dispose(this._disposables);
|
||||
this.groups.length = 0;
|
||||
this._disposables.length = 0;
|
||||
}
|
||||
|
||||
private static _compareReferences(a: Location, b: Location): number {
|
||||
|
||||
@@ -15,6 +15,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import { getBaseLabel } from 'vs/base/common/labels';
|
||||
import { dirname, basename } from 'vs/base/common/resources';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
@@ -22,7 +23,6 @@ import { IListVirtualDelegate, IKeyboardNavigationLabelProvider, IIdentityProvid
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { FuzzyScore, createMatches, IMatch } from 'vs/base/common/filters';
|
||||
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
|
||||
//#region data source
|
||||
|
||||
@@ -82,14 +82,8 @@ export class StringRepresentationProvider implements IKeyboardNavigationLabelPro
|
||||
constructor(@IKeybindingService private readonly _keybindingService: IKeybindingService) { }
|
||||
|
||||
getKeyboardNavigationLabel(element: TreeElement): { toString(): string; } {
|
||||
if (element instanceof OneReference) {
|
||||
const { preview } = element.parent;
|
||||
const parts = preview && preview.preview(element.range);
|
||||
if (parts) {
|
||||
return parts.value;
|
||||
}
|
||||
}
|
||||
// FileReferences or unresolved OneReference
|
||||
// todo@joao `OneReference` elements are lazy and their "real" label
|
||||
// isn't known yet
|
||||
return basename(element.uri);
|
||||
}
|
||||
|
||||
@@ -167,29 +161,31 @@ export class FileReferencesRenderer implements ITreeRenderer<FileReferences, Fuz
|
||||
//#region render: Reference
|
||||
class OneReferenceTemplate {
|
||||
|
||||
readonly label: HighlightedLabel;
|
||||
readonly before: HTMLSpanElement;
|
||||
readonly inside: HTMLSpanElement;
|
||||
readonly after: HTMLSpanElement;
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
this.label = new HighlightedLabel(container, false);
|
||||
const parent = document.createElement('div');
|
||||
this.before = document.createElement('span');
|
||||
this.inside = document.createElement('span');
|
||||
this.after = document.createElement('span');
|
||||
dom.addClass(this.inside, 'referenceMatch');
|
||||
dom.addClass(parent, 'reference');
|
||||
parent.appendChild(this.before);
|
||||
parent.appendChild(this.inside);
|
||||
parent.appendChild(this.after);
|
||||
container.appendChild(parent);
|
||||
}
|
||||
|
||||
set(element: OneReference, score?: FuzzyScore): void {
|
||||
set(element: OneReference): void {
|
||||
const filePreview = element.parent.preview;
|
||||
const preview = filePreview && filePreview.preview(element.range);
|
||||
if (!preview) {
|
||||
// this means we FAILED to resolve the document...
|
||||
this.label.set(`${basename(element.uri)}:${element.range.startLineNumber + 1}:${element.range.startColumn + 1}`);
|
||||
} else {
|
||||
// render search match as highlight unless
|
||||
// we have score, then render the score
|
||||
const { value, highlight } = preview;
|
||||
if (score && !FuzzyScore.isDefault(score)) {
|
||||
dom.toggleClass(this.label.element, 'referenceMatch', false);
|
||||
this.label.set(value, createMatches(score));
|
||||
} else {
|
||||
dom.toggleClass(this.label.element, 'referenceMatch', true);
|
||||
this.label.set(value, [highlight]);
|
||||
}
|
||||
if (preview) {
|
||||
const { before, inside, after } = preview;
|
||||
this.before.innerHTML = escape(before);
|
||||
this.inside.innerHTML = escape(inside);
|
||||
this.after.innerHTML = escape(after);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,10 +199,11 @@ export class OneReferenceRenderer implements ITreeRenderer<OneReference, FuzzySc
|
||||
renderTemplate(container: HTMLElement): OneReferenceTemplate {
|
||||
return new OneReferenceTemplate(container);
|
||||
}
|
||||
renderElement(node: ITreeNode<OneReference, FuzzyScore>, index: number, templateData: OneReferenceTemplate): void {
|
||||
templateData.set(node.element, node.filterData);
|
||||
renderElement(element: ITreeNode<OneReference, FuzzyScore>, index: number, templateData: OneReferenceTemplate): void {
|
||||
templateData.set(element.element);
|
||||
}
|
||||
disposeTemplate(): void {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { dispose, IDisposable, IReference, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { dispose, IDisposable, IReference } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { basenameOrAuthority, dirname } from 'vs/base/common/resources';
|
||||
import 'vs/css!./media/referencesWidget';
|
||||
@@ -47,22 +47,22 @@ class DecorationsManager implements IDisposable {
|
||||
|
||||
private _decorations = new Map<string, OneReference>();
|
||||
private _decorationIgnoreSet = new Set<string>();
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private readonly _callOnModelChange = new DisposableStore();
|
||||
private _callOnDispose: IDisposable[] = [];
|
||||
private _callOnModelChange: IDisposable[] = [];
|
||||
|
||||
constructor(private _editor: ICodeEditor, private _model: ReferencesModel) {
|
||||
this._callOnDispose.add(this._editor.onDidChangeModel(() => this._onModelChanged()));
|
||||
this._callOnDispose.push(this._editor.onDidChangeModel(() => this._onModelChanged()));
|
||||
this._onModelChanged();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._callOnModelChange.dispose();
|
||||
this._callOnDispose.dispose();
|
||||
this._callOnModelChange = dispose(this._callOnModelChange);
|
||||
this._callOnDispose = dispose(this._callOnDispose);
|
||||
this.removeDecorations();
|
||||
}
|
||||
|
||||
private _onModelChanged(): void {
|
||||
this._callOnModelChange.clear();
|
||||
this._callOnModelChange = dispose(this._callOnModelChange);
|
||||
const model = this._editor.getModel();
|
||||
if (model) {
|
||||
for (const ref of this._model.groups) {
|
||||
@@ -78,7 +78,7 @@ class DecorationsManager implements IDisposable {
|
||||
if (!this._editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
this._callOnModelChange.add(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged()));
|
||||
this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged()));
|
||||
|
||||
const newDecorations: IModelDeltaDecoration[] = [];
|
||||
const newDecorationsActualIndex: number[] = [];
|
||||
@@ -194,8 +194,8 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
private _model: ReferencesModel | undefined;
|
||||
private _decorationsManager: DecorationsManager;
|
||||
|
||||
private readonly _disposeOnNewModel = new DisposableStore();
|
||||
private readonly _callOnDispose = new DisposableStore();
|
||||
private _disposeOnNewModel: IDisposable[] = [];
|
||||
private _callOnDispose: IDisposable[] = [];
|
||||
private _onDidSelectReference = new Emitter<SelectionEvent>();
|
||||
|
||||
private _tree: WorkbenchAsyncDataTree<ReferencesModel | FileReferences, TreeElement, FuzzyScore>;
|
||||
@@ -222,19 +222,15 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true });
|
||||
|
||||
this._applyTheme(themeService.getTheme());
|
||||
this._callOnDispose.add(themeService.onThemeChange(this._applyTheme.bind(this)));
|
||||
this._callOnDispose.push(themeService.onThemeChange(this._applyTheme.bind(this)));
|
||||
this._peekViewService.addExclusiveWidget(editor, this);
|
||||
this.create();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.setModel(undefined);
|
||||
this._callOnDispose.dispose();
|
||||
this._disposeOnNewModel.dispose();
|
||||
dispose(this._preview);
|
||||
dispose(this._previewNotAvailableMessage);
|
||||
dispose(this._tree);
|
||||
dispose(this._previewModelReference);
|
||||
this._callOnDispose = dispose(this._callOnDispose);
|
||||
dispose<IDisposable>(this._preview, this._previewNotAvailableMessage, this._tree, this._previewModelReference);
|
||||
this._splitView.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -348,11 +344,11 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
}
|
||||
}, Sizing.Distribute);
|
||||
|
||||
this._disposables.add(this._splitView.onDidSashChange(() => {
|
||||
this._splitView.onDidSashChange(() => {
|
||||
if (this._dim.width) {
|
||||
this.layoutData.ratio = this._splitView.getViewSize(0) / this._dim.width;
|
||||
}
|
||||
}, undefined));
|
||||
}, undefined, this._disposables);
|
||||
|
||||
// listen on selection and focus
|
||||
let onEvent = (element: any, kind: 'show' | 'goto' | 'side') => {
|
||||
@@ -425,7 +421,7 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
|
||||
public setModel(newModel: ReferencesModel | undefined): Promise<any> {
|
||||
// clean up
|
||||
this._disposeOnNewModel.clear();
|
||||
this._disposeOnNewModel = dispose(this._disposeOnNewModel);
|
||||
this._model = newModel;
|
||||
if (this._model) {
|
||||
return this._onNewModel();
|
||||
@@ -447,13 +443,13 @@ export class ReferenceWidget extends PeekViewWidget {
|
||||
|
||||
dom.hide(this._messageContainer);
|
||||
this._decorationsManager = new DecorationsManager(this._preview, this._model);
|
||||
this._disposeOnNewModel.add(this._decorationsManager);
|
||||
this._disposeOnNewModel.push(this._decorationsManager);
|
||||
|
||||
// listen on model changes
|
||||
this._disposeOnNewModel.add(this._model.onDidChangeReferenceRange(reference => this._tree.rerender(reference)));
|
||||
this._disposeOnNewModel.push(this._model.onDidChangeReferenceRange(reference => this._tree.rerender(reference)));
|
||||
|
||||
// listen on editor
|
||||
this._disposeOnNewModel.add(this._preview.onMouseDown(e => {
|
||||
this._disposeOnNewModel.push(this._preview.onMouseDown(e => {
|
||||
const { event, target } = e;
|
||||
if (event.detail !== 2) {
|
||||
return;
|
||||
@@ -570,7 +566,7 @@ export const peekViewEditorMatchHighlightBorder = registerColor('peekViewEditor.
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
const findMatchHighlightColor = theme.getColor(peekViewResultsMatchHighlight);
|
||||
if (findMatchHighlightColor) {
|
||||
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch .highlight { background-color: ${findMatchHighlightColor}; }`);
|
||||
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { background-color: ${findMatchHighlightColor}; }`);
|
||||
}
|
||||
const referenceHighlightColor = theme.getColor(peekViewEditorMatchHighlight);
|
||||
if (referenceHighlightColor) {
|
||||
@@ -582,7 +578,7 @@ registerThemingParticipant((theme, collector) => {
|
||||
}
|
||||
const hcOutline = theme.getColor(activeContrastBorder);
|
||||
if (hcOutline) {
|
||||
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch .highlight { border: 1px dotted ${hcOutline}; box-sizing: border-box; }`);
|
||||
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { border: 1px dotted ${hcOutline}; box-sizing: border-box; }`);
|
||||
}
|
||||
const resultsBackground = theme.getColor(peekViewResultsBackground);
|
||||
if (resultsBackground) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
|
||||
import { illegalArgument, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, EditorCommand, registerEditorCommand, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -114,7 +114,7 @@ class RenameController extends Disposable implements IEditorContribution {
|
||||
private readonly editor: ICodeEditor,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
@ILocalProgressService private readonly _progressService: ILocalProgressService,
|
||||
@IProgressService private readonly _progressService: IProgressService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import 'vs/css!./renameInputField';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
@@ -24,10 +24,10 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
private _inputField: HTMLInputElement;
|
||||
private _visible: boolean;
|
||||
private readonly _visibleContextKey: IContextKey<boolean>;
|
||||
private readonly _disposables = new DisposableStore();
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
// Editor.IContentWidget.allowEditorOverflow
|
||||
allowEditorOverflow: boolean = true;
|
||||
public allowEditorOverflow: boolean = true;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@@ -39,13 +39,13 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
this._editor = editor;
|
||||
this._editor.addContentWidget(this);
|
||||
|
||||
this._disposables.add(editor.onDidChangeConfiguration(e => {
|
||||
this._disposables.push(editor.onDidChangeConfiguration(e => {
|
||||
if (e.fontInfo) {
|
||||
this.updateFont();
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.add(themeService.onThemeChange(theme => this.onThemeChange(theme)));
|
||||
this._disposables.push(themeService.onThemeChange(theme => this.onThemeChange(theme)));
|
||||
}
|
||||
|
||||
private onThemeChange(theme: ITheme): void {
|
||||
@@ -53,7 +53,7 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._disposables.dispose();
|
||||
this._disposables = dispose(this._disposables);
|
||||
this._editor.removeContentWidget(this);
|
||||
}
|
||||
|
||||
@@ -138,9 +138,9 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
this._inputField.setAttribute('selectionEnd', selectionEnd.toString());
|
||||
this._inputField.size = Math.max((where.endColumn - where.startColumn) * 1.1, 20);
|
||||
|
||||
const disposeOnDone = new DisposableStore();
|
||||
const disposeOnDone: IDisposable[] = [];
|
||||
const always = () => {
|
||||
disposeOnDone.dispose();
|
||||
dispose(disposeOnDone);
|
||||
this._hide();
|
||||
};
|
||||
|
||||
@@ -172,8 +172,8 @@ export class RenameInputField implements IContentWidget, IDisposable {
|
||||
}
|
||||
};
|
||||
|
||||
disposeOnDone.add(this._editor.onDidChangeCursorSelection(onCursorChanged));
|
||||
disposeOnDone.add(this._editor.onDidBlurEditorWidget(() => this.cancelInput(false)));
|
||||
disposeOnDone.push(this._editor.onDidChangeCursorSelection(onCursorChanged));
|
||||
disposeOnDone.push(this._editor.onDidBlurEditorWidget(() => this.cancelInput(false)));
|
||||
|
||||
this._show();
|
||||
|
||||
|
||||
@@ -115,8 +115,8 @@ export class BracketSelectionRangeProvider implements SelectionRangeProvider {
|
||||
}
|
||||
const innerBracket = Range.fromPositions(bracket.range.getEndPosition(), closing!.getStartPosition());
|
||||
const outerBracket = Range.fromPositions(bracket.range.getStartPosition(), closing!.getEndPosition());
|
||||
bucket.push({ range: innerBracket });
|
||||
bucket.push({ range: outerBracket });
|
||||
bucket.push({ range: innerBracket, kind: 'statement.brackets' });
|
||||
bucket.push({ range: outerBracket, kind: 'statement.brackets.full' });
|
||||
BracketSelectionRangeProvider._addBracketLeading(model, outerBracket, bucket);
|
||||
}
|
||||
}
|
||||
@@ -135,8 +135,8 @@ export class BracketSelectionRangeProvider implements SelectionRangeProvider {
|
||||
const startLine = bracket.startLineNumber;
|
||||
const column = model.getLineFirstNonWhitespaceColumn(startLine);
|
||||
if (column !== 0 && column !== bracket.startColumn) {
|
||||
bucket.push({ range: Range.fromPositions(new Position(startLine, column), bracket.getEndPosition()) });
|
||||
bucket.push({ range: Range.fromPositions(new Position(startLine, 1), bracket.getEndPosition()) });
|
||||
bucket.push({ range: Range.fromPositions(new Position(startLine, column), bracket.getEndPosition()), kind: 'statement.brackets.leading' });
|
||||
bucket.push({ range: Range.fromPositions(new Position(startLine, 1), bracket.getEndPosition()), kind: 'statement.brackets.leading.full' });
|
||||
}
|
||||
|
||||
// xxxxxxxx
|
||||
@@ -147,8 +147,8 @@ export class BracketSelectionRangeProvider implements SelectionRangeProvider {
|
||||
if (aboveLine > 0) {
|
||||
const column = model.getLineFirstNonWhitespaceColumn(aboveLine);
|
||||
if (column === bracket.startColumn && column !== model.getLineLastNonWhitespaceColumn(aboveLine)) {
|
||||
bucket.push({ range: Range.fromPositions(new Position(aboveLine, column), bracket.getEndPosition()) });
|
||||
bucket.push({ range: Range.fromPositions(new Position(aboveLine, 1), bracket.getEndPosition()) });
|
||||
bucket.push({ range: Range.fromPositions(new Position(aboveLine, column), bracket.getEndPosition()), kind: 'statement.brackets.leading' });
|
||||
bucket.push({ range: Range.fromPositions(new Position(aboveLine, 1), bracket.getEndPosition()), kind: 'statement.brackets.leading.full' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,12 +284,12 @@ export function provideSelectionRanges(model: ITextModel, positions: Position[],
|
||||
if (cur.startLineNumber !== prev.startLineNumber || cur.endLineNumber !== prev.endLineNumber) {
|
||||
// add line/block range without leading/failing whitespace
|
||||
const rangeNoWhitespace = new Range(prev.startLineNumber, model.getLineFirstNonWhitespaceColumn(prev.startLineNumber), prev.endLineNumber, model.getLineLastNonWhitespaceColumn(prev.endLineNumber));
|
||||
if (rangeNoWhitespace.containsRange(prev) && !rangeNoWhitespace.equalsRange(prev) && cur.containsRange(rangeNoWhitespace) && !cur.equalsRange(rangeNoWhitespace)) {
|
||||
if (rangeNoWhitespace.containsRange(prev) && !rangeNoWhitespace.equalsRange(prev)) {
|
||||
oneRangesWithTrivia.push(rangeNoWhitespace);
|
||||
}
|
||||
// add line/block range
|
||||
const rangeFull = new Range(prev.startLineNumber, 1, prev.endLineNumber, model.getLineMaxColumn(prev.endLineNumber));
|
||||
if (rangeFull.containsRange(prev) && !rangeFull.equalsRange(rangeNoWhitespace) && cur.containsRange(rangeFull) && !cur.equalsRange(rangeFull)) {
|
||||
if (rangeFull.containsRange(prev) && !rangeFull.equalsRange(rangeNoWhitespace)) {
|
||||
oneRangesWithTrivia.push(rangeFull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as assert from 'assert';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { LanguageIdentifier, SelectionRangeProvider, SelectionRangeRegistry } from 'vs/editor/common/modes';
|
||||
import { LanguageIdentifier, SelectionRangeProvider } from 'vs/editor/common/modes';
|
||||
import { MockMode, StaticLanguageSelector } from 'vs/editor/test/common/mocks/mockMode';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
|
||||
@@ -320,25 +320,4 @@ suite('SmartSelect', () => {
|
||||
new Range(1, 1, 1, 21),
|
||||
);
|
||||
});
|
||||
|
||||
test('Smart select: only add line ranges if they’re contained by the next range #73850', async function () {
|
||||
|
||||
const reg = SelectionRangeRegistry.register('*', {
|
||||
provideSelectionRanges() {
|
||||
return [[
|
||||
{ range: { startLineNumber: 1, startColumn: 10, endLineNumber: 1, endColumn: 11 } },
|
||||
{ range: { startLineNumber: 1, startColumn: 10, endLineNumber: 3, endColumn: 2 } },
|
||||
{ range: { startLineNumber: 1, startColumn: 1, endLineNumber: 3, endColumn: 2 } },
|
||||
]];
|
||||
}
|
||||
});
|
||||
|
||||
await assertGetRangesToPosition(['type T = {', '\tx: number', '}'], 1, 10, [
|
||||
new Range(1, 1, 3, 2), // all
|
||||
new Range(1, 10, 3, 2), // { ... }
|
||||
new Range(1, 10, 1, 11), // {
|
||||
]);
|
||||
|
||||
reg.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export class WordSelectionRangeProvider implements SelectionRangeProvider {
|
||||
this._addInWordRanges(bucket, model, position);
|
||||
this._addWordRanges(bucket, model, position);
|
||||
this._addWhitespaceLine(bucket, model, position);
|
||||
bucket.push({ range: model.getFullModelRange() });
|
||||
bucket.push({ range: model.getFullModelRange(), kind: 'statement.all' });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -65,14 +65,14 @@ export class WordSelectionRangeProvider implements SelectionRangeProvider {
|
||||
}
|
||||
|
||||
if (start < end) {
|
||||
bucket.push({ range: new Range(pos.lineNumber, startColumn + start, pos.lineNumber, startColumn + end) });
|
||||
bucket.push({ range: new Range(pos.lineNumber, startColumn + start, pos.lineNumber, startColumn + end), kind: 'statement.word.part' });
|
||||
}
|
||||
}
|
||||
|
||||
private _addWordRanges(bucket: SelectionRange[], model: ITextModel, pos: Position): void {
|
||||
const word = model.getWordAtPosition(pos);
|
||||
if (word) {
|
||||
bucket.push({ range: new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn) });
|
||||
bucket.push({ range: new Range(pos.lineNumber, word.startColumn, pos.lineNumber, word.endColumn), kind: 'statement.word' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ export class WordSelectionRangeProvider implements SelectionRangeProvider {
|
||||
&& model.getLineFirstNonWhitespaceColumn(pos.lineNumber) === 0
|
||||
&& model.getLineLastNonWhitespaceColumn(pos.lineNumber) === 0
|
||||
) {
|
||||
bucket.push({ range: new Range(pos.lineNumber, 1, pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)) });
|
||||
bucket.push({ range: new Range(pos.lineNumber, 1, pos.lineNumber, model.getLineMaxColumn(pos.lineNumber)), kind: 'statement.line' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Choice, Placeholder, SnippetParser, Text, TextmateSnippet, Marker } from './snippetParser';
|
||||
import { Choice, Placeholder, SnippetParser, Text, TextmateSnippet } from './snippetParser';
|
||||
import { ClipboardBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, SelectionBasedVariableResolver, TimeBasedVariableResolver, CommentBasedVariableResolver, WorkspaceBasedVariableResolver } from './snippetVariables';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
||||
@@ -122,14 +122,14 @@ export class OneSnippet {
|
||||
}
|
||||
}
|
||||
|
||||
let couldSkipThisPlaceholder = false;
|
||||
let skipThisPlaceholder = false;
|
||||
if (fwd === true && this._placeholderGroupsIdx < this._placeholderGroups.length - 1) {
|
||||
this._placeholderGroupsIdx += 1;
|
||||
couldSkipThisPlaceholder = true;
|
||||
skipThisPlaceholder = true;
|
||||
|
||||
} else if (fwd === false && this._placeholderGroupsIdx > 0) {
|
||||
this._placeholderGroupsIdx -= 1;
|
||||
couldSkipThisPlaceholder = true;
|
||||
skipThisPlaceholder = true;
|
||||
|
||||
} else {
|
||||
// the selection of the current placeholder might
|
||||
@@ -154,7 +154,7 @@ export class OneSnippet {
|
||||
// consider to skip this placeholder index when the decoration
|
||||
// range is empty but when the placeholder wasn't. that's a strong
|
||||
// hint that the placeholder has been deleted. (all placeholder must match this)
|
||||
couldSkipThisPlaceholder = couldSkipThisPlaceholder && this._hasPlaceholderBeenCollapsed(placeholder);
|
||||
skipThisPlaceholder = skipThisPlaceholder && (range.isEmpty() && placeholder.toString().length > 0);
|
||||
|
||||
accessor.changeDecorationOptions(id, placeholder.isFinalTabstop ? OneSnippet._decor.activeFinal : OneSnippet._decor.active);
|
||||
activePlaceholders.add(placeholder);
|
||||
@@ -177,25 +177,7 @@ export class OneSnippet {
|
||||
return selections;
|
||||
})!;
|
||||
|
||||
return !couldSkipThisPlaceholder ? newSelections : this.move(fwd);
|
||||
}
|
||||
|
||||
private _hasPlaceholderBeenCollapsed(placeholder: Placeholder): boolean {
|
||||
// A placeholder is empty when it wasn't empty when authored but
|
||||
// when its tracking decoration is empty. This also applies to all
|
||||
// potential parent placeholders
|
||||
let marker: Marker | undefined = placeholder;
|
||||
while (marker) {
|
||||
if (marker instanceof Placeholder) {
|
||||
const id = this._placeholderDecorations.get(marker)!;
|
||||
const range = this._editor.getModel().getDecorationRange(id)!;
|
||||
if (range.isEmpty() && marker.toString().length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
marker = marker.parent;
|
||||
}
|
||||
return false;
|
||||
return !skipThisPlaceholder ? newSelections : this.move(fwd);
|
||||
}
|
||||
|
||||
get isAtFirstPlaceholder() {
|
||||
|
||||
@@ -410,22 +410,4 @@ suite('SnippetController2', function () {
|
||||
ctrl.insert('export default $1');
|
||||
assertContextKeys(contextKeys, true, false, true);
|
||||
});
|
||||
|
||||
test('Optional tabstop in snippets #72358', function () {
|
||||
const ctrl = new SnippetController2(editor, logService, contextKeys);
|
||||
model.setValue('');
|
||||
editor.setSelection(new Selection(1, 1, 1, 1));
|
||||
|
||||
ctrl.insert('${1:prop: {$2\\},}\nmore$0');
|
||||
assertContextKeys(contextKeys, true, false, true);
|
||||
|
||||
assertSelections(editor, new Selection(1, 1, 1, 10));
|
||||
editor.trigger('test', Handler.Cut, {});
|
||||
|
||||
assertSelections(editor, new Selection(1, 1, 1, 1));
|
||||
|
||||
ctrl.next();
|
||||
assertSelections(editor, new Selection(2, 5, 2, 5));
|
||||
assertContextKeys(contextKeys, false, false, false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { FuzzyScore } from 'vs/base/common/filters';
|
||||
import { isDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
export const Context = {
|
||||
Visible: new RawContextKey<boolean>('suggestWidgetVisible', false),
|
||||
@@ -122,6 +121,7 @@ export function provideSuggestionItems(
|
||||
token: CancellationToken = CancellationToken.None
|
||||
): Promise<CompletionItem[]> {
|
||||
|
||||
const allSuggestions: CompletionItem[] = [];
|
||||
const wordUntil = model.getWordUntilPosition(position);
|
||||
const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
|
||||
|
||||
@@ -135,12 +135,9 @@ export function provideSuggestionItems(
|
||||
supports.unshift([_snippetSuggestSupport]);
|
||||
}
|
||||
|
||||
const allSuggestions: CompletionItem[] = [];
|
||||
const disposables = new DisposableStore();
|
||||
let hasResult = false;
|
||||
|
||||
// add suggestions from contributed providers - providers are ordered in groups of
|
||||
// equal score and once a group produces a result the process stops
|
||||
let hasResult = false;
|
||||
const factory = supports.map(supports => () => {
|
||||
// for each support in the group ask for suggestions
|
||||
return Promise.all(supports.map(provider => {
|
||||
@@ -165,9 +162,6 @@ export function provideSuggestionItems(
|
||||
allSuggestions.push(new CompletionItem(position, suggestion, container, provider, model));
|
||||
}
|
||||
}
|
||||
if (isDisposable(container)) {
|
||||
disposables.add(container);
|
||||
}
|
||||
}
|
||||
|
||||
if (len !== allSuggestions.length && provider !== _snippetSuggestSupport) {
|
||||
@@ -183,7 +177,6 @@ export function provideSuggestionItems(
|
||||
return hasResult || token.isCancellationRequested;
|
||||
}).then(() => {
|
||||
if (token.isCancellationRequested) {
|
||||
disposables.dispose();
|
||||
return Promise.reject<any>(canceled());
|
||||
}
|
||||
return allSuggestions.sort(getSuggestionComparator(options.snippetSortOrder));
|
||||
@@ -251,35 +244,29 @@ export function getSuggestionComparator(snippetConfig: SnippetSortOrder): (a: Co
|
||||
return _snippetComparators.get(snippetConfig)!;
|
||||
}
|
||||
|
||||
registerDefaultLanguageCommand('_executeCompletionItemProvider', async (model, position, args) => {
|
||||
registerDefaultLanguageCommand('_executeCompletionItemProvider', (model, position, args) => {
|
||||
|
||||
const result: modes.CompletionList = {
|
||||
incomplete: false,
|
||||
suggestions: []
|
||||
};
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
const resolving: Promise<any>[] = [];
|
||||
const maxItemsToResolve = args['maxItemsToResolve'] || 0;
|
||||
let resolving: Promise<any>[] = [];
|
||||
let maxItemsToResolve = args['maxItemsToResolve'] || 0;
|
||||
|
||||
const items = await provideSuggestionItems(model, position);
|
||||
for (const item of items) {
|
||||
if (resolving.length < maxItemsToResolve) {
|
||||
resolving.push(item.resolve(CancellationToken.None));
|
||||
return provideSuggestionItems(model, position).then(items => {
|
||||
for (const item of items) {
|
||||
if (resolving.length < maxItemsToResolve) {
|
||||
resolving.push(item.resolve(CancellationToken.None));
|
||||
}
|
||||
result.incomplete = result.incomplete || item.container.incomplete;
|
||||
result.suggestions.push(item.completion);
|
||||
}
|
||||
result.incomplete = result.incomplete || item.container.incomplete;
|
||||
result.suggestions.push(item.completion);
|
||||
if (isDisposable(item.container)) {
|
||||
disposables.add(item.container);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all(resolving);
|
||||
}).then(() => {
|
||||
return Promise.all(resolving);
|
||||
}).then(() => {
|
||||
return result;
|
||||
} finally {
|
||||
disposables.dispose();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface SuggestController extends IEditorContribution {
|
||||
|
||||
@@ -9,8 +9,8 @@ import { createMatches } from 'vs/base/common/filters';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { addClass, append, $, hide, removeClass, show, toggleClass, getDomNodePagePosition, hasClass, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { addClass, append, $, hide, removeClass, show, toggleClass, getDomNodePagePosition, hasClass } from 'vs/base/browser/dom';
|
||||
import { IListVirtualDelegate, IListEvent, IListRenderer, IListMouseEvent } from 'vs/base/browser/ui/list/list';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
@@ -103,9 +103,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
|
||||
|
||||
renderTemplate(container: HTMLElement): ISuggestionTemplateData {
|
||||
const data = <ISuggestionTemplateData>Object.create(null);
|
||||
const disposables = new DisposableStore();
|
||||
data.disposables = [disposables];
|
||||
|
||||
data.disposables = [];
|
||||
data.root = container;
|
||||
addClass(data.root, 'show-file-icons');
|
||||
|
||||
@@ -116,7 +114,7 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
|
||||
const main = append(text, $('.main'));
|
||||
|
||||
data.iconLabel = new IconLabel(main, { supportHighlights: true });
|
||||
disposables.add(data.iconLabel);
|
||||
data.disposables.push(data.iconLabel);
|
||||
|
||||
data.typeLabel = append(main, $('span.type-label'));
|
||||
|
||||
@@ -144,9 +142,9 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData>
|
||||
|
||||
configureFont();
|
||||
|
||||
disposables.add(Event.chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
|
||||
Event.chain<IConfigurationChangedEvent>(this.editor.onDidChangeConfiguration.bind(this.editor))
|
||||
.filter(e => e.fontInfo || e.contribInfo)
|
||||
.on(configureFont, null));
|
||||
.on(configureFont, null, data.disposables);
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -401,7 +399,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
|
||||
// Editor.IContentWidget.allowEditorOverflow
|
||||
readonly allowEditorOverflow = true;
|
||||
readonly suppressMouseDown = true;
|
||||
|
||||
private state: State | null;
|
||||
private isAuto: boolean;
|
||||
@@ -423,13 +420,14 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
|
||||
private readonly editorBlurTimeout = new TimeoutTimer();
|
||||
private readonly showTimeout = new TimeoutTimer();
|
||||
private readonly toDispose: IDisposable[] = [];
|
||||
private toDispose: IDisposable[];
|
||||
|
||||
private onDidSelectEmitter = new Emitter<ISelectedSuggestion>();
|
||||
private onDidFocusEmitter = new Emitter<ISelectedSuggestion>();
|
||||
private onDidHideEmitter = new Emitter<this>();
|
||||
private onDidShowEmitter = new Emitter<this>();
|
||||
|
||||
|
||||
readonly onDidSelect: Event<ISelectedSuggestion> = this.onDidSelectEmitter.event;
|
||||
readonly onDidFocus: Event<ISelectedSuggestion> = this.onDidFocusEmitter.event;
|
||||
readonly onDidHide: Event<this> = this.onDidHideEmitter.event;
|
||||
@@ -466,11 +464,6 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.storageService = storageService;
|
||||
|
||||
this.element = $('.editor-widget.suggest-widget');
|
||||
this.toDispose.push(addDisposableListener(this.element, 'click', e => {
|
||||
if (e.target === this.element) {
|
||||
this.hideWidget();
|
||||
}
|
||||
}));
|
||||
|
||||
this.messageElement = append(this.element, $('.message'));
|
||||
this.listElement = append(this.element, $('.tree'));
|
||||
@@ -487,7 +480,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
mouseSupport: false
|
||||
});
|
||||
|
||||
this.toDispose.push(
|
||||
this.toDispose = [
|
||||
attachListStyler(this.list, themeService, {
|
||||
listInactiveFocusBackground: editorSuggestWidgetSelectedBackground,
|
||||
listInactiveFocusOutline: activeContrastBorder
|
||||
@@ -499,7 +492,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.list.onFocusChange(e => this.onListFocus(e)),
|
||||
this.editor.onDidChangeCursorSelection(() => this.onCursorSelectionChanged()),
|
||||
this.editor.onDidChangeConfiguration(e => e.contribInfo && applyIconStyle())
|
||||
);
|
||||
];
|
||||
|
||||
this.suggestWidgetVisible = SuggestContext.Visible.bindTo(contextKeyService);
|
||||
this.suggestWidgetMultipleSuggestions = SuggestContext.MultipleSuggestions.bindTo(contextKeyService);
|
||||
@@ -1159,7 +1152,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
||||
this.details = null!; // StrictNullOverride: nulling out ok in dispose
|
||||
this.list.dispose();
|
||||
this.list = null!; // StrictNullOverride: nulling out ok in dispose
|
||||
dispose(this.toDispose);
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
if (this.loadingTimeout) {
|
||||
clearTimeout(this.loadingTimeout);
|
||||
this.loadingTimeout = null;
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export class WordContextKey extends Disposable {
|
||||
export class WordContextKey {
|
||||
|
||||
static readonly AtEnd = new RawContextKey<boolean>('atEndOfWord', false);
|
||||
|
||||
private readonly _ckAtEnd: IContextKey<boolean>;
|
||||
private readonly _confListener: IDisposable;
|
||||
|
||||
private _enabled: boolean;
|
||||
private _selectionListener?: IDisposable;
|
||||
@@ -20,15 +21,13 @@ export class WordContextKey extends Disposable {
|
||||
private readonly _editor: ICodeEditor,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
) {
|
||||
super();
|
||||
this._ckAtEnd = WordContextKey.AtEnd.bindTo(contextKeyService);
|
||||
this._register(this._editor.onDidChangeConfiguration(e => e.contribInfo && this._update()));
|
||||
this._confListener = this._editor.onDidChangeConfiguration(e => e.contribInfo && this._update());
|
||||
this._update();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
dispose(this._selectionListener);
|
||||
dispose(this._confListener, this._selectionListener);
|
||||
this._ckAtEnd.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { IHorizontalSashLayoutProvider, ISashEvent, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -165,7 +165,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
private _positionMarkerId: string[] = [];
|
||||
|
||||
protected _viewZone: ViewZoneDelegate | null;
|
||||
protected readonly _disposables = new DisposableStore();
|
||||
protected _disposables: IDisposable[] = [];
|
||||
|
||||
public container: HTMLElement;
|
||||
public domNode: HTMLElement;
|
||||
@@ -183,7 +183,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
this.domNode.setAttribute('role', 'presentation');
|
||||
}
|
||||
|
||||
this._disposables.add(this.editor.onDidLayoutChange((info: EditorLayoutInfo) => {
|
||||
this._disposables.push(this.editor.onDidLayoutChange((info: EditorLayoutInfo) => {
|
||||
const width = this._getWidth(info);
|
||||
this.domNode.style.width = width + 'px';
|
||||
this.domNode.style.left = this._getLeft(info) + 'px';
|
||||
@@ -193,7 +193,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
|
||||
public dispose(): void {
|
||||
|
||||
this._disposables.dispose();
|
||||
dispose(this._disposables);
|
||||
|
||||
if (this._overlayWidget) {
|
||||
this.editor.removeOverlayWidget(this._overlayWidget);
|
||||
@@ -225,7 +225,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
this.domNode.appendChild(this.container);
|
||||
if (this.options.showArrow) {
|
||||
this._arrow = new Arrow(this.editor);
|
||||
this._disposables.add(this._arrow);
|
||||
this._disposables.push(this._arrow);
|
||||
}
|
||||
this._fillContainer(this.container);
|
||||
this._initSash();
|
||||
@@ -470,10 +470,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
// --- sash
|
||||
|
||||
private _initSash(): void {
|
||||
if (this._resizeSash) {
|
||||
return;
|
||||
}
|
||||
this._resizeSash = this._disposables.add(new Sash(this.domNode, this, { orientation: Orientation.HORIZONTAL }));
|
||||
this._resizeSash = new Sash(this.domNode, this, { orientation: Orientation.HORIZONTAL });
|
||||
|
||||
if (!this.options.isResizeable) {
|
||||
this._resizeSash.hide();
|
||||
@@ -481,7 +478,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
}
|
||||
|
||||
let data: { startY: number; heightInLines: number; } | undefined;
|
||||
this._disposables.add(this._resizeSash.onDidStart((e: ISashEvent) => {
|
||||
this._disposables.push(this._resizeSash.onDidStart((e: ISashEvent) => {
|
||||
if (this._viewZone) {
|
||||
data = {
|
||||
startY: e.startY,
|
||||
@@ -490,11 +487,11 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
}
|
||||
}));
|
||||
|
||||
this._disposables.add(this._resizeSash.onDidEnd(() => {
|
||||
this._disposables.push(this._resizeSash.onDidEnd(() => {
|
||||
data = undefined;
|
||||
}));
|
||||
|
||||
this._disposables.add(this._resizeSash.onDidChange((evt: ISashEvent) => {
|
||||
this._disposables.push(this._resizeSash.onDidChange((evt: ISashEvent) => {
|
||||
if (data) {
|
||||
let lineDelta = (evt.currentY - data.startY) / this.editor.getConfiguration().lineHeight;
|
||||
let roundedLineDelta = lineDelta < 0 ? Math.ceil(lineDelta) : Math.floor(lineDelta);
|
||||
|
||||
@@ -6,23 +6,24 @@
|
||||
import 'vs/css!./iPadShowKeyboard';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
|
||||
export class IPadShowKeyboard extends Disposable implements IEditorContribution {
|
||||
export class IPadShowKeyboard implements IEditorContribution {
|
||||
|
||||
private static readonly ID = 'editor.contrib.iPadShowKeyboard';
|
||||
|
||||
private readonly editor: ICodeEditor;
|
||||
private widget: ShowKeyboardWidget | null;
|
||||
private toDispose: IDisposable[];
|
||||
|
||||
constructor(editor: ICodeEditor) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.toDispose = [];
|
||||
if (browser.isIPad) {
|
||||
this._register(editor.onDidChangeConfiguration(() => this.update()));
|
||||
this.toDispose.push(editor.onDidChangeConfiguration(() => this.update()));
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
@@ -47,7 +48,7 @@ export class IPadShowKeyboard extends Disposable implements IEditorContribution
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
this.toDispose = dispose(this.toDispose);
|
||||
if (this.widget) {
|
||||
this.widget.dispose();
|
||||
this.widget = null;
|
||||
@@ -55,24 +56,25 @@ export class IPadShowKeyboard extends Disposable implements IEditorContribution
|
||||
}
|
||||
}
|
||||
|
||||
class ShowKeyboardWidget extends Disposable implements IOverlayWidget {
|
||||
class ShowKeyboardWidget implements IOverlayWidget {
|
||||
|
||||
private static readonly ID = 'editor.contrib.ShowKeyboardWidget';
|
||||
|
||||
private readonly editor: ICodeEditor;
|
||||
|
||||
private readonly _domNode: HTMLElement;
|
||||
private _toDispose: IDisposable[];
|
||||
|
||||
constructor(editor: ICodeEditor) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this._domNode = document.createElement('textarea');
|
||||
this._domNode.className = 'iPadShowKeyboard';
|
||||
|
||||
this._register(dom.addDisposableListener(this._domNode, 'touchstart', (e) => {
|
||||
this._toDispose = [];
|
||||
this._toDispose.push(dom.addDisposableListener(this._domNode, 'touchstart', (e) => {
|
||||
this.editor.focus();
|
||||
}));
|
||||
this._register(dom.addDisposableListener(this._domNode, 'focus', (e) => {
|
||||
this._toDispose.push(dom.addDisposableListener(this._domNode, 'focus', (e) => {
|
||||
this.editor.focus();
|
||||
}));
|
||||
|
||||
@@ -81,7 +83,7 @@ class ShowKeyboardWidget extends Disposable implements IOverlayWidget {
|
||||
|
||||
public dispose(): void {
|
||||
this.editor.removeOverlayWidget(this);
|
||||
super.dispose();
|
||||
this._toDispose = dispose(this._toDispose);
|
||||
}
|
||||
|
||||
// ----- IOverlayWidget API
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Keybinding, ResolvedKeybinding, SimpleKeybinding, createKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { IDisposable, IReference, ImmortalReference, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, IReference, ImmortalReference, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { OS, isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -25,7 +25,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IResolvedTextEditorModel, ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { CommandsRegistry, ICommand, ICommandEvent, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfirmation, IConfirmationResult, IDialogOptions, IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
@@ -37,8 +37,8 @@ import { IKeybindingItem, KeybindingsRegistry } from 'vs/platform/keybinding/com
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressRunner, ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
|
||||
import { IProgressRunner, IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
@@ -136,7 +136,7 @@ export class SimpleEditorModelResolverService implements ITextModelService {
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleLocalProgressService implements ILocalProgressService {
|
||||
export class SimpleProgressService implements IProgressService {
|
||||
_serviceBrand: any;
|
||||
|
||||
private static NULL_PROGRESS_RUNNER: IProgressRunner = {
|
||||
@@ -148,7 +148,7 @@ export class SimpleLocalProgressService implements ILocalProgressService {
|
||||
show(infinite: true, delay?: number): IProgressRunner;
|
||||
show(total: number, delay?: number): IProgressRunner;
|
||||
show(): IProgressRunner {
|
||||
return SimpleLocalProgressService.NULL_PROGRESS_RUNNER;
|
||||
return SimpleProgressService.NULL_PROGRESS_RUNNER;
|
||||
}
|
||||
|
||||
showWhile(promise: Promise<any>, delay?: number): Promise<void> {
|
||||
@@ -220,10 +220,6 @@ export class SimpleNotificationService implements INotificationService {
|
||||
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
|
||||
return SimpleNotificationService.NO_OP;
|
||||
}
|
||||
|
||||
public status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
}
|
||||
|
||||
export class StandaloneCommandService implements ICommandService {
|
||||
@@ -295,7 +291,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
|
||||
throw new Error(`Invalid keybinding`);
|
||||
}
|
||||
|
||||
const toDispose = new DisposableStore();
|
||||
let toDispose: IDisposable[] = [];
|
||||
|
||||
this._dynamicKeybindings.push({
|
||||
keybinding: keybinding,
|
||||
@@ -305,7 +301,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
|
||||
weight2: 0
|
||||
});
|
||||
|
||||
toDispose.add(toDisposable(() => {
|
||||
toDispose.push(toDisposable(() => {
|
||||
for (let i = 0; i < this._dynamicKeybindings.length; i++) {
|
||||
let kb = this._dynamicKeybindings[i];
|
||||
if (kb.command === commandId) {
|
||||
@@ -318,7 +314,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
|
||||
|
||||
let commandService = this._commandService;
|
||||
if (commandService instanceof StandaloneCommandService) {
|
||||
toDispose.add(commandService.addCommand({
|
||||
toDispose.push(commandService.addCommand({
|
||||
id: commandId,
|
||||
handler: handler
|
||||
}));
|
||||
@@ -327,7 +323,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
|
||||
}
|
||||
this.updateResolver({ source: KeybindingSource.Default });
|
||||
|
||||
return toDispose;
|
||||
return combinedDisposable(toDispose);
|
||||
}
|
||||
|
||||
private updateResolver(event: IKeybindingEvent): void {
|
||||
@@ -450,17 +446,7 @@ export class SimpleConfigurationService implements IConfigurationService {
|
||||
}
|
||||
|
||||
public getConfigurationData(): IConfigurationData | null {
|
||||
const emptyModel: IConfigurationModel = {
|
||||
contents: {},
|
||||
keys: [],
|
||||
overrides: []
|
||||
};
|
||||
return {
|
||||
defaults: emptyModel,
|
||||
user: emptyModel,
|
||||
workspace: emptyModel,
|
||||
folders: {}
|
||||
};
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { Disposable, IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
@@ -227,13 +227,13 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
|
||||
};
|
||||
|
||||
|
||||
const toDispose = new DisposableStore();
|
||||
let toDispose: IDisposable[] = [];
|
||||
|
||||
// Generate a unique id to allow the same descriptor.id across multiple editor instances
|
||||
const uniqueId = this.getId() + ':' + id;
|
||||
|
||||
// Register the command
|
||||
toDispose.add(CommandsRegistry.registerCommand(uniqueId, run));
|
||||
toDispose.push(CommandsRegistry.registerCommand(uniqueId, run));
|
||||
|
||||
// Register the context menu item
|
||||
if (contextMenuGroupId) {
|
||||
@@ -246,14 +246,16 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
|
||||
group: contextMenuGroupId,
|
||||
order: contextMenuOrder
|
||||
};
|
||||
toDispose.add(MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem));
|
||||
toDispose.push(MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem));
|
||||
}
|
||||
|
||||
// Register the keybindings
|
||||
if (Array.isArray(keybindings)) {
|
||||
for (const kb of keybindings) {
|
||||
toDispose.add(this._standaloneKeybindingService.addDynamicKeybinding(uniqueId, kb, run, keybindingsWhen));
|
||||
}
|
||||
toDispose = toDispose.concat(
|
||||
keybindings.map((kb) => {
|
||||
return this._standaloneKeybindingService.addDynamicKeybinding(uniqueId, kb, run, keybindingsWhen);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Finally, register an internal editor action
|
||||
@@ -268,11 +270,11 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
|
||||
|
||||
// Store it under the original id, such that trigger with the original id will work
|
||||
this._actions[id] = internalAction;
|
||||
toDispose.add(toDisposable(() => {
|
||||
toDispose.push(toDisposable(() => {
|
||||
delete this._actions[id];
|
||||
}));
|
||||
|
||||
return toDispose;
|
||||
return combinedDisposable(toDispose);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ export interface IEncodedLineTokens {
|
||||
* - f = foreground ColorId (9 bits)
|
||||
* - b = background ColorId (9 bits)
|
||||
* - The color value for each colorId is defined in IStandaloneThemeData.customTokenColors:
|
||||
* e.g. colorId = 1 is stored in IStandaloneThemeData.customTokenColors[1]. Color id = 0 means no color,
|
||||
* e.g colorId = 1 is stored in IStandaloneThemeData.customTokenColors[1]. Color id = 0 means no color,
|
||||
* id = 1 is for the default foreground color, id = 2 for the default background.
|
||||
*/
|
||||
tokens: Uint32Array;
|
||||
@@ -427,7 +427,7 @@ export function registerCodeLensProvider(languageId: string, provider: modes.Cod
|
||||
*/
|
||||
export function registerCodeActionProvider(languageId: string, provider: CodeActionProvider): IDisposable {
|
||||
return modes.CodeActionProviderRegistry.register(languageId, {
|
||||
provideCodeActions: (model: model.ITextModel, range: Range, context: modes.CodeActionContext, token: CancellationToken): modes.CodeActionList | Promise<modes.CodeActionList> => {
|
||||
provideCodeActions: (model: model.ITextModel, range: Range, context: modes.CodeActionContext, token: CancellationToken): (modes.Command | modes.CodeAction)[] | Promise<(modes.Command | modes.CodeAction)[]> => {
|
||||
let markers = StaticServices.markerService.get().read({ resource: model.uri }).filter(m => {
|
||||
return Range.areIntersectingOrTouching(m, range);
|
||||
});
|
||||
@@ -510,7 +510,7 @@ export interface CodeActionProvider {
|
||||
/**
|
||||
* Provide commands for the given document and range.
|
||||
*/
|
||||
provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): modes.CodeActionList | Promise<modes.CodeActionList>;
|
||||
provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): (modes.Command | modes.CodeAction)[] | Promise<(modes.Command | modes.CodeAction)[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
|
||||
import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleLocalProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, SimpleLayoutService } from 'vs/editor/standalone/browser/simpleServices';
|
||||
import { SimpleBulkEditService, SimpleConfigurationService, SimpleDialogService, SimpleNotificationService, SimpleProgressService, SimpleResourceConfigurationService, SimpleResourcePropertiesService, SimpleUriLabelService, SimpleWorkspaceContextService, StandaloneCommandService, StandaloneKeybindingService, StandaloneTelemetryService, SimpleLayoutService } from 'vs/editor/standalone/browser/simpleServices';
|
||||
import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl';
|
||||
import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standaloneThemeServiceImpl';
|
||||
import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
|
||||
@@ -36,7 +36,7 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ILocalProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -150,7 +150,7 @@ export module StaticServices {
|
||||
|
||||
export const codeEditorService = define(ICodeEditorService, (o) => new StandaloneCodeEditorServiceImpl(standaloneThemeService.get(o)));
|
||||
|
||||
export const localProgressService = define(ILocalProgressService, () => new SimpleLocalProgressService());
|
||||
export const progressService = define(IProgressService, () => new SimpleProgressService());
|
||||
|
||||
export const storageService = define(IStorageService, () => new InMemoryStorageService());
|
||||
|
||||
|
||||
@@ -26,21 +26,17 @@ function testGuessIndentation(defaultInsertSpaces: boolean, defaultTabSize: numb
|
||||
assert.equal(r.tabSize, expectedTabSize, msg);
|
||||
}
|
||||
|
||||
function assertGuess(expectedInsertSpaces: boolean | undefined, expectedTabSize: number | undefined | [number], text: string[], msg?: string): void {
|
||||
function assertGuess(expectedInsertSpaces: boolean | undefined, expectedTabSize: number | undefined, text: string[], msg?: string): void {
|
||||
if (typeof expectedInsertSpaces === 'undefined') {
|
||||
// cannot guess insertSpaces
|
||||
if (typeof expectedTabSize === 'undefined') {
|
||||
// cannot guess tabSize
|
||||
testGuessIndentation(true, 13370, true, 13370, text, msg);
|
||||
testGuessIndentation(false, 13371, false, 13371, text, msg);
|
||||
} else if (typeof expectedTabSize === 'number') {
|
||||
} else {
|
||||
// can guess tabSize
|
||||
testGuessIndentation(true, 13370, true, expectedTabSize, text, msg);
|
||||
testGuessIndentation(false, 13371, false, expectedTabSize, text, msg);
|
||||
} else {
|
||||
// can only guess tabSize when insertSpaces is true
|
||||
testGuessIndentation(true, 13370, true, expectedTabSize[0], text, msg);
|
||||
testGuessIndentation(false, 13371, false, 13371, text, msg);
|
||||
}
|
||||
} else {
|
||||
// can guess insertSpaces
|
||||
@@ -48,19 +44,10 @@ function assertGuess(expectedInsertSpaces: boolean | undefined, expectedTabSize:
|
||||
// cannot guess tabSize
|
||||
testGuessIndentation(true, 13370, expectedInsertSpaces, 13370, text, msg);
|
||||
testGuessIndentation(false, 13371, expectedInsertSpaces, 13371, text, msg);
|
||||
} else if (typeof expectedTabSize === 'number') {
|
||||
} else {
|
||||
// can guess tabSize
|
||||
testGuessIndentation(true, 13370, expectedInsertSpaces, expectedTabSize, text, msg);
|
||||
testGuessIndentation(false, 13371, expectedInsertSpaces, expectedTabSize, text, msg);
|
||||
} else {
|
||||
// can only guess tabSize when insertSpaces is true
|
||||
if (expectedInsertSpaces === true) {
|
||||
testGuessIndentation(true, 13370, expectedInsertSpaces, expectedTabSize[0], text, msg);
|
||||
testGuessIndentation(false, 13371, expectedInsertSpaces, expectedTabSize[0], text, msg);
|
||||
} else {
|
||||
testGuessIndentation(true, 13370, expectedInsertSpaces, 13370, text, msg);
|
||||
testGuessIndentation(false, 13371, expectedInsertSpaces, 13371, text, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,7 +219,7 @@ suite('Editor Model - TextModel', () => {
|
||||
'\tx'
|
||||
], '7xTAB');
|
||||
|
||||
assertGuess(undefined, [2], [
|
||||
assertGuess(undefined, 2, [
|
||||
'\tx',
|
||||
' x',
|
||||
'\tx',
|
||||
@@ -252,7 +239,7 @@ suite('Editor Model - TextModel', () => {
|
||||
'\tx',
|
||||
' x'
|
||||
], '4x1, 4xTAB');
|
||||
assertGuess(false, undefined, [
|
||||
assertGuess(false, 2, [
|
||||
'\tx',
|
||||
'\tx',
|
||||
' x',
|
||||
@@ -263,7 +250,7 @@ suite('Editor Model - TextModel', () => {
|
||||
'\tx',
|
||||
' x',
|
||||
], '4x2, 5xTAB');
|
||||
assertGuess(false, undefined, [
|
||||
assertGuess(false, 2, [
|
||||
'\tx',
|
||||
'\tx',
|
||||
'x',
|
||||
@@ -274,7 +261,7 @@ suite('Editor Model - TextModel', () => {
|
||||
'\tx',
|
||||
' x',
|
||||
], '1x2, 5xTAB');
|
||||
assertGuess(false, undefined, [
|
||||
assertGuess(false, 4, [
|
||||
'\tx',
|
||||
'\tx',
|
||||
'x',
|
||||
@@ -285,7 +272,7 @@ suite('Editor Model - TextModel', () => {
|
||||
'\tx',
|
||||
' x',
|
||||
], '1x4, 5xTAB');
|
||||
assertGuess(false, undefined, [
|
||||
assertGuess(false, 2, [
|
||||
'\tx',
|
||||
'\tx',
|
||||
'x',
|
||||
@@ -537,7 +524,7 @@ suite('Editor Model - TextModel', () => {
|
||||
' \t x',
|
||||
'\tx'
|
||||
], 'mixed whitespace 1');
|
||||
assertGuess(false, undefined, [
|
||||
assertGuess(false, 4, [
|
||||
'\tx',
|
||||
'\t x'
|
||||
], 'mixed whitespace 2');
|
||||
@@ -588,26 +575,6 @@ suite('Editor Model - TextModel', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #70832: Broken indentation detection', () => {
|
||||
assertGuess(false, undefined, [
|
||||
'x',
|
||||
'x',
|
||||
'x',
|
||||
'x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
' x',
|
||||
'x',
|
||||
]);
|
||||
});
|
||||
|
||||
test('validatePosition', () => {
|
||||
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
|
||||
Reference in New Issue
Block a user