Archived
Merge from vscode 33a65245075e4d18908652865a79cf5489c30f40 (#9279)
* Merge from vscode 33a65245075e4d18908652865a79cf5489c30f40 * remove github
This commit is contained in:
+15
-2
@@ -138,8 +138,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
'disable-hardware-acceleration',
|
||||
|
||||
// provided by Electron
|
||||
'disable-color-correct-rendering'
|
||||
'disable-color-correct-rendering',
|
||||
|
||||
// override for the color profile to use
|
||||
'force-color-profile'
|
||||
];
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
SUPPORTED_ELECTRON_SWITCHES.push('force-renderer-accessibility');
|
||||
}
|
||||
@@ -154,7 +158,16 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
}
|
||||
|
||||
const argvValue = argvConfig[argvKey];
|
||||
if (argvValue === true || argvValue === 'true') {
|
||||
|
||||
// Color profile
|
||||
if (argvKey === 'force-color-profile') {
|
||||
if (argvValue) {
|
||||
app.commandLine.appendSwitch(argvKey, argvValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Others
|
||||
else if (argvValue === true || argvValue === 'true') {
|
||||
if (argvKey === 'disable-hardware-acceleration') {
|
||||
app.disableHardwareAcceleration(); // needs to be called explicitly
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,7 @@ import { attachModalDialogStyler, attachPanelStyler } from 'sql/workbench/common
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { ServiceOptionType } from 'sql/platform/connection/common/interfaces';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
export class CategoryView extends ViewPane {
|
||||
|
||||
@@ -51,9 +52,10 @@ export class CategoryView extends ViewPane {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IOpenerService protected openerService: IOpenerService,
|
||||
@IThemeService protected themeService: IThemeService
|
||||
@IThemeService protected themeService: IThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, opener, themeService);
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, opener, themeService, telemetryService);
|
||||
}
|
||||
|
||||
// we want a fixed size, so when we render to will measure our content and set that to be our
|
||||
|
||||
@@ -50,6 +50,7 @@ import { NodeContextKey } from 'sql/workbench/browser/parts/views/nodeContext';
|
||||
import { UserCancelledConnectionError } from 'sql/base/common/errors';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
export class CustomTreeViewPanel extends ViewPane {
|
||||
|
||||
@@ -65,9 +66,10 @@ export class CustomTreeViewPanel extends ViewPane {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IOpenerService protected openerService: IOpenerService,
|
||||
@IThemeService protected themeService: IThemeService
|
||||
@IThemeService protected themeService: IThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
|
||||
this.treeView = treeView as ITreeView;
|
||||
this._register(this.treeView.onDidChangeActions(() => this.updateActions(), this));
|
||||
|
||||
@@ -86,7 +86,7 @@ function createInstantiationService(addAccountFailureEmitter?: Emitter<string>):
|
||||
.returns(() => undefined);
|
||||
|
||||
// Create a mock account dialog
|
||||
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog);
|
||||
mockAccountDialog.setup(x => x.onAddAccountErrorEvent)
|
||||
.returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; });
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { TestEditorService, TestDialogService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestEditorService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TestQueryModelService } from 'sql/workbench/services/query/test/common/testQueryModelService';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -33,6 +33,7 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||
import { FileQueryEditorInput } from 'sql/workbench/contrib/query/common/fileQueryEditorInput';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
|
||||
class TestParsedArgs implements ParsedArgs {
|
||||
[arg: string]: any;
|
||||
|
||||
@@ -24,6 +24,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
export class ConnectionViewletPanel extends ViewPane {
|
||||
|
||||
@@ -46,9 +47,10 @@ export class ConnectionViewletPanel extends ViewPane {
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IOpenerService protected openerService: IOpenerService,
|
||||
@IThemeService protected themeService: IThemeService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, opener, themeService);
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, opener, themeService, telemetryService);
|
||||
this._addServerAction = this.instantiationService.createInstance(AddServerAction,
|
||||
AddServerAction.ID,
|
||||
AddServerAction.LABEL);
|
||||
|
||||
@@ -47,6 +47,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { GridPanelState, GridTableState } from 'sql/workbench/common/editor/query/gridPanelState';
|
||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||
import { SaveFormat } from 'sql/workbench/services/query/common/resultSerializer';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
|
||||
const ROW_HEIGHT = 29;
|
||||
const HEADER_HEIGHT = 26;
|
||||
@@ -580,7 +581,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
|
||||
let content = value.displayValue;
|
||||
|
||||
const input = this.untitledEditorService.create({ mode: column.isXml ? 'xml' : 'json', initialValue: content });
|
||||
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, input.textEditorModel, FormattingMode.Explicit, CancellationToken.None);
|
||||
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, input.textEditorModel, FormattingMode.Explicit, Progress.None, CancellationToken.None);
|
||||
return this.editorService.openEditor(input);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/vie
|
||||
import { attachModalDialogStyler, attachPanelStyler } from 'sql/workbench/common/styler';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
class AccountPanel extends ViewPane {
|
||||
public index: number;
|
||||
@@ -54,8 +55,9 @@ class AccountPanel extends ViewPane {
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
@@ -133,7 +135,8 @@ export class AccountDialog extends Modal {
|
||||
@ILogService logService: ILogService,
|
||||
@IViewDescriptorService private viewDescriptorService: IViewDescriptorService,
|
||||
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IOpenerService protected readonly openerService: IOpenerService
|
||||
@IOpenerService protected readonly openerService: IOpenerService,
|
||||
@ITelemetryService private readonly vstelemetryService: ITelemetryService,
|
||||
) {
|
||||
super(
|
||||
localize('linkedAccounts', "Linked accounts"),
|
||||
@@ -305,7 +308,8 @@ export class AccountDialog extends Modal {
|
||||
this.contextKeyService,
|
||||
this._instantiationService,
|
||||
this.viewDescriptorService,
|
||||
this.openerService
|
||||
this.openerService,
|
||||
this.vstelemetryService
|
||||
);
|
||||
|
||||
attachPanelStyler(providerView, this._themeService);
|
||||
|
||||
@@ -46,6 +46,7 @@ import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/vie
|
||||
import { attachPanelStyler, attachModalDialogStyler } from 'sql/workbench/common/styler';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
const labelDisplay = nls.localize("insights.item", "Item");
|
||||
const valueDisplay = nls.localize("insights.value", "Value");
|
||||
@@ -70,8 +71,9 @@ class InsightTableView<T> extends ViewPane {
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, opener, themeService);
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
|
||||
@@ -283,3 +283,20 @@ export function isRootOrDriveLetter(path: string): boolean {
|
||||
|
||||
return pathNormalized === posix.sep;
|
||||
}
|
||||
|
||||
export function indexOfPath(path: string, candidate: string, ignoreCase: boolean): number {
|
||||
if (candidate.length > path.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path === candidate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ignoreCase) {
|
||||
path = path.toLowerCase();
|
||||
candidate = candidate.toLowerCase();
|
||||
}
|
||||
|
||||
return path.indexOf(candidate);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
const _typeof = {
|
||||
number: 'number',
|
||||
string: 'string',
|
||||
@@ -262,3 +264,21 @@ export type AddFirstParameterToFunctions<Target, TargetFunctionsReturnType, Firs
|
||||
// Else: just leave as is
|
||||
Target[K]
|
||||
};
|
||||
|
||||
/**
|
||||
* Mapped-type that replaces all occurrences of URI with UriComponents
|
||||
*/
|
||||
export type UriDto<T> = { [K in keyof T]: T[K] extends URI
|
||||
? UriComponents
|
||||
: UriDto<T[K]> };
|
||||
|
||||
/**
|
||||
* Mapped-type that replaces all occurrences of URI with UriComponents and
|
||||
* drops all functions.
|
||||
* todo@joh use toJSON-results
|
||||
*/
|
||||
export type Dto<T> = { [K in keyof T]: T[K] extends URI
|
||||
? UriComponents
|
||||
: T[K] extends Function
|
||||
? never
|
||||
: UriDto<T[K]> };
|
||||
|
||||
@@ -575,10 +575,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
return this.visible ? this.ui.inputBox.hasFocus() : false;
|
||||
}
|
||||
|
||||
public focusOnInput() {
|
||||
this.ui.inputBox.setFocus();
|
||||
}
|
||||
|
||||
onDidChangeSelection = this.onDidChangeSelectionEmitter.event;
|
||||
|
||||
onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;
|
||||
|
||||
@@ -209,8 +209,6 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
|
||||
validationMessage: string | undefined;
|
||||
|
||||
inputHasFocus(): boolean;
|
||||
|
||||
focusOnInput(): void;
|
||||
}
|
||||
|
||||
export interface IInputBox extends IQuickInput {
|
||||
|
||||
@@ -24,7 +24,7 @@ import { MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
const CORE_WEIGHT = KeybindingWeight.EditorCore;
|
||||
@@ -1530,6 +1530,26 @@ export namespace CoreNavigationCommands {
|
||||
});
|
||||
}
|
||||
|
||||
const columnSelectionCondition = ContextKeyExpr.and(
|
||||
EditorContextKeys.textInputFocus,
|
||||
EditorContextKeys.columnSelection
|
||||
);
|
||||
function registerColumnSelection(id: string, keybinding: number): void {
|
||||
KeybindingsRegistry.registerKeybindingRule({
|
||||
id: id,
|
||||
primary: keybinding,
|
||||
when: columnSelectionCondition,
|
||||
weight: CORE_WEIGHT + 1
|
||||
});
|
||||
}
|
||||
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectLeft.id, KeyMod.Shift | KeyCode.LeftArrow);
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectRight.id, KeyMod.Shift | KeyCode.RightArrow);
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectUp.id, KeyMod.Shift | KeyCode.UpArrow);
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectPageUp.id, KeyMod.Shift | KeyCode.PageUp);
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectDown.id, KeyMod.Shift | KeyCode.DownArrow);
|
||||
registerColumnSelection(CoreNavigationCommands.CursorColumnSelectPageDown.id, KeyMod.Shift | KeyCode.PageDown);
|
||||
|
||||
/**
|
||||
* A command that will:
|
||||
* 1. invoke a command on the focused editor.
|
||||
|
||||
@@ -352,6 +352,7 @@ class MouseDownOperation extends Disposable {
|
||||
|
||||
if (!options.get(EditorOption.readOnly)
|
||||
&& options.get(EditorOption.dragAndDrop)
|
||||
&& !options.get(EditorOption.columnSelection)
|
||||
&& !this._mouseState.altKey // we don't support multiple mouse
|
||||
&& e.detail < 2 // only single click on a selection can work
|
||||
&& !this._isActive // the mouse is not down yet
|
||||
|
||||
@@ -133,7 +133,9 @@ export class ViewController {
|
||||
}
|
||||
|
||||
public dispatchMouse(data: IMouseDispatchData): void {
|
||||
const selectionClipboardIsOn = (platform.isLinux && this.configuration.options.get(EditorOption.selectionClipboard));
|
||||
const options = this.configuration.options;
|
||||
const selectionClipboardIsOn = (platform.isLinux && options.get(EditorOption.selectionClipboard));
|
||||
const columnSelection = options.get(EditorOption.columnSelection);
|
||||
if (data.middleButton && !selectionClipboardIsOn) {
|
||||
this._columnSelect(data.position, data.mouseColumn, data.inSelectionMode);
|
||||
} else if (data.startedOnLineNumbers) {
|
||||
@@ -196,7 +198,11 @@ export class ViewController {
|
||||
if (data.altKey) {
|
||||
this._columnSelect(data.position, data.mouseColumn, true);
|
||||
} else {
|
||||
this._moveToSelect(data.position);
|
||||
if (columnSelection) {
|
||||
this._columnSelect(data.position, data.mouseColumn, true);
|
||||
} else {
|
||||
this._moveToSelect(data.position);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.moveTo(data.position);
|
||||
|
||||
@@ -1666,6 +1666,7 @@ class EditorContextKeysManager extends Disposable {
|
||||
private readonly _editorTextFocus: IContextKey<boolean>;
|
||||
private readonly _editorTabMovesFocus: IContextKey<boolean>;
|
||||
private readonly _editorReadonly: IContextKey<boolean>;
|
||||
private readonly _editorColumnSelection: IContextKey<boolean>;
|
||||
private readonly _hasMultipleSelections: IContextKey<boolean>;
|
||||
private readonly _hasNonEmptySelection: IContextKey<boolean>;
|
||||
private readonly _canUndo: IContextKey<boolean>;
|
||||
@@ -1687,6 +1688,7 @@ class EditorContextKeysManager extends Disposable {
|
||||
this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService);
|
||||
this._editorTabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService);
|
||||
this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService);
|
||||
this._editorColumnSelection = EditorContextKeys.columnSelection.bindTo(contextKeyService);
|
||||
this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);
|
||||
this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);
|
||||
this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);
|
||||
@@ -1714,6 +1716,7 @@ class EditorContextKeysManager extends Disposable {
|
||||
|
||||
this._editorTabMovesFocus.set(options.get(EditorOption.tabFocusMode));
|
||||
this._editorReadonly.set(options.get(EditorOption.readOnly));
|
||||
this._editorColumnSelection.set(options.get(EditorOption.columnSelection));
|
||||
}
|
||||
|
||||
private _updateFromSelection(): void {
|
||||
|
||||
@@ -324,6 +324,11 @@ export interface IEditorOptions {
|
||||
* Defaults to true.
|
||||
*/
|
||||
scrollPredominantAxis?: boolean;
|
||||
/**
|
||||
* Enable that the selection with the mouse and keys is doing column selection.
|
||||
* Defaults to false.
|
||||
*/
|
||||
columnSelection?: boolean;
|
||||
/**
|
||||
* The modifier to be used to add multiple cursors with the mouse.
|
||||
* Defaults to 'alt'
|
||||
@@ -3302,6 +3307,7 @@ export const enum EditorOption {
|
||||
autoSurround,
|
||||
codeLens,
|
||||
colorDecorators,
|
||||
columnSelection,
|
||||
comments,
|
||||
contextmenu,
|
||||
copyWithSyntaxHighlighting,
|
||||
@@ -3526,6 +3532,10 @@ export const EditorOptions = {
|
||||
EditorOption.colorDecorators, 'colorDecorators', true,
|
||||
{ description: nls.localize('colorDecorators', "Controls whether the editor should render the inline color decorators and color picker.") }
|
||||
)),
|
||||
columnSelection: register(new EditorBooleanOption(
|
||||
EditorOption.columnSelection, 'columnSelection', false,
|
||||
{ description: nls.localize('columnSelection', "Enable that the selection with the mouse and keys is doing column selection.") }
|
||||
)),
|
||||
comments: register(new EditorComments()),
|
||||
contextmenu: register(new EditorBooleanOption(
|
||||
EditorOption.contextmenu, 'contextmenu', true,
|
||||
|
||||
@@ -23,6 +23,7 @@ export namespace EditorContextKeys {
|
||||
export const textInputFocus = new RawContextKey<boolean>('textInputFocus', false);
|
||||
|
||||
export const readOnly = new RawContextKey<boolean>('editorReadonly', false);
|
||||
export const columnSelection = new RawContextKey<boolean>('editorColumnSelection', false);
|
||||
export const writable: ContextKeyExpr = readOnly.toNegated();
|
||||
export const hasNonEmptySelection = new RawContextKey<boolean>('editorHasSelection', false);
|
||||
export const hasOnlyEmptySelection: ContextKeyExpr = hasNonEmptySelection.toNegated();
|
||||
|
||||
@@ -1077,7 +1077,7 @@ export interface ITextModel {
|
||||
* @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed.
|
||||
* @return The cursor state returned by the `cursorStateComputer`.
|
||||
*/
|
||||
pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;
|
||||
pushEditOperations(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;
|
||||
|
||||
/**
|
||||
* Change the end of line sequence. This is the preferred way of
|
||||
@@ -1093,11 +1093,6 @@ export interface ITextModel {
|
||||
*/
|
||||
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_applyEdits(edits: IValidEditOperations[], isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): IValidEditOperations[];
|
||||
|
||||
/**
|
||||
* Change the end of line sequence without recording in the undo stack.
|
||||
* This can have dire consequences on the undo stack! See @pushEOL for the preferred way.
|
||||
@@ -1107,7 +1102,7 @@ export interface ITextModel {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_setEOL(eol: EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;
|
||||
_applyUndoRedoEdits(edits: IValidEditOperations[], eol: EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): IValidEditOperations[];
|
||||
|
||||
/**
|
||||
* Undo edit operations until the first previous stop point created by `pushStackElement`.
|
||||
|
||||
@@ -8,41 +8,50 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel, IValidEditOperations } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IUndoRedoService, IUndoRedoElement, IUndoRedoContext } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { IUndoRedoService, IResourceUndoRedoElement, UndoRedoElementType, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getComparisonKey as uriGetComparisonKey } from 'vs/base/common/resources';
|
||||
|
||||
class EditStackElement implements IUndoRedoElement {
|
||||
export class EditStackElement implements IResourceUndoRedoElement {
|
||||
|
||||
public readonly type = UndoRedoElementType.Resource;
|
||||
public readonly label: string;
|
||||
private _isOpen: boolean;
|
||||
private readonly _model: TextModel;
|
||||
public readonly model: ITextModel;
|
||||
private readonly _beforeVersionId: number;
|
||||
private readonly _beforeCursorState: Selection[];
|
||||
private readonly _beforeEOL: EndOfLineSequence;
|
||||
private readonly _beforeCursorState: Selection[] | null;
|
||||
private _afterVersionId: number;
|
||||
private _afterEOL: EndOfLineSequence;
|
||||
private _afterCursorState: Selection[] | null;
|
||||
private _edits: IValidEditOperations[];
|
||||
|
||||
public get resources(): readonly URI[] {
|
||||
return [this._model.uri];
|
||||
public get resource(): URI {
|
||||
return this.model.uri;
|
||||
}
|
||||
|
||||
constructor(model: TextModel, beforeVersionId: number, beforeCursorState: Selection[], afterVersionId: number, afterCursorState: Selection[] | null, operations: IValidEditOperation[]) {
|
||||
constructor(model: ITextModel, beforeCursorState: Selection[] | null) {
|
||||
this.label = nls.localize('edit', "Typing");
|
||||
this._isOpen = true;
|
||||
this._model = model;
|
||||
this._beforeVersionId = beforeVersionId;
|
||||
this.model = model;
|
||||
this._beforeVersionId = this.model.getAlternativeVersionId();
|
||||
this._beforeEOL = getModelEOL(this.model);
|
||||
this._beforeCursorState = beforeCursorState;
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._afterCursorState = afterCursorState;
|
||||
this._edits = [{ operations: operations }];
|
||||
this._afterVersionId = this._beforeVersionId;
|
||||
this._afterEOL = this._beforeEOL;
|
||||
this._afterCursorState = this._beforeCursorState;
|
||||
this._edits = [];
|
||||
}
|
||||
|
||||
public isOpen(): boolean {
|
||||
return this._isOpen;
|
||||
public canAppend(model: ITextModel): boolean {
|
||||
return (this._isOpen && this.model === model);
|
||||
}
|
||||
|
||||
public append(operations: IValidEditOperation[], afterVersionId: number, afterCursorState: Selection[] | null): void {
|
||||
this._edits.push({ operations: operations });
|
||||
public append(model: ITextModel, operations: IValidEditOperation[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void {
|
||||
if (operations.length > 0) {
|
||||
this._edits.push({ operations: operations });
|
||||
}
|
||||
this._afterEOL = afterEOL;
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._afterCursorState = afterCursorState;
|
||||
}
|
||||
@@ -51,20 +60,83 @@ class EditStackElement implements IUndoRedoElement {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
undo(ctx: IUndoRedoContext): void {
|
||||
public undo(): void {
|
||||
this._isOpen = false;
|
||||
this._edits.reverse();
|
||||
this._edits = this._model._applyEdits(this._edits, true, false, this._beforeVersionId, this._beforeCursorState);
|
||||
this._edits = this.model._applyUndoRedoEdits(this._edits, this._beforeEOL, true, false, this._beforeVersionId, this._beforeCursorState);
|
||||
}
|
||||
|
||||
redo(ctx: IUndoRedoContext): void {
|
||||
this._isOpen = false;
|
||||
public redo(): void {
|
||||
this._edits.reverse();
|
||||
this._edits = this._model._applyEdits(this._edits, false, true, this._afterVersionId, this._afterCursorState);
|
||||
this._edits = this.model._applyUndoRedoEdits(this._edits, this._afterEOL, false, true, this._afterVersionId, this._afterCursorState);
|
||||
}
|
||||
}
|
||||
|
||||
export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement {
|
||||
|
||||
public readonly type = UndoRedoElementType.Workspace;
|
||||
public readonly label: string;
|
||||
private _isOpen: boolean;
|
||||
|
||||
private readonly _editStackElementsArr: EditStackElement[];
|
||||
private readonly _editStackElementsMap: Map<string, EditStackElement>;
|
||||
|
||||
public get resources(): readonly URI[] {
|
||||
return this._editStackElementsArr.map(editStackElement => editStackElement.model.uri);
|
||||
}
|
||||
|
||||
invalidate(resource: URI): void {
|
||||
// nothing to do
|
||||
constructor(
|
||||
label: string,
|
||||
editStackElements: EditStackElement[]
|
||||
) {
|
||||
this.label = label;
|
||||
this._isOpen = true;
|
||||
this._editStackElementsArr = editStackElements.slice(0);
|
||||
this._editStackElementsMap = new Map<string, EditStackElement>();
|
||||
for (const editStackElement of this._editStackElementsArr) {
|
||||
const key = uriGetComparisonKey(editStackElement.model.uri);
|
||||
this._editStackElementsMap.set(key, editStackElement);
|
||||
}
|
||||
}
|
||||
|
||||
public canAppend(model: ITextModel): boolean {
|
||||
if (!this._isOpen) {
|
||||
return false;
|
||||
}
|
||||
const key = uriGetComparisonKey(model.uri);
|
||||
if (this._editStackElementsMap.has(key)) {
|
||||
const editStackElement = this._editStackElementsMap.get(key)!;
|
||||
return editStackElement.canAppend(model);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public append(model: ITextModel, operations: IValidEditOperation[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void {
|
||||
const key = uriGetComparisonKey(model.uri);
|
||||
const editStackElement = this._editStackElementsMap.get(key)!;
|
||||
editStackElement.append(model, operations, afterEOL, afterVersionId, afterCursorState);
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
public undo(): void {
|
||||
this._isOpen = false;
|
||||
|
||||
for (const editStackElement of this._editStackElementsArr) {
|
||||
editStackElement.undo();
|
||||
}
|
||||
}
|
||||
|
||||
public redo(): void {
|
||||
for (const editStackElement of this._editStackElementsArr) {
|
||||
editStackElement.redo();
|
||||
}
|
||||
}
|
||||
|
||||
public split(): IResourceUndoRedoElement[] {
|
||||
return this._editStackElementsArr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,46 +149,11 @@ function getModelEOL(model: ITextModel): EndOfLineSequence {
|
||||
}
|
||||
}
|
||||
|
||||
class EOLStackElement implements IUndoRedoElement {
|
||||
|
||||
public readonly label: string;
|
||||
private readonly _model: TextModel;
|
||||
private readonly _beforeVersionId: number;
|
||||
private readonly _afterVersionId: number;
|
||||
private _eol: EndOfLineSequence;
|
||||
|
||||
public get resources(): readonly URI[] {
|
||||
return [this._model.uri];
|
||||
function isKnownStackElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null): element is EditStackElement | MultiModelEditStackElement {
|
||||
if (!element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
constructor(model: TextModel, beforeVersionId: number, afterVersionId: number, eol: EndOfLineSequence) {
|
||||
this.label = nls.localize('eol', "Change End Of Line Sequence");
|
||||
this._model = model;
|
||||
this._beforeVersionId = beforeVersionId;
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._eol = eol;
|
||||
}
|
||||
|
||||
undo(ctx: IUndoRedoContext): void {
|
||||
const redoEOL = getModelEOL(this._model);
|
||||
this._model._setEOL(this._eol, true, false, this._beforeVersionId, null);
|
||||
this._eol = redoEOL;
|
||||
}
|
||||
|
||||
redo(ctx: IUndoRedoContext): void {
|
||||
const undoEOL = getModelEOL(this._model);
|
||||
this._model._setEOL(this._eol, false, true, this._afterVersionId, null);
|
||||
this._eol = undoEOL;
|
||||
}
|
||||
|
||||
invalidate(resource: URI): void {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
export interface IUndoRedoResult {
|
||||
selections: Selection[] | null;
|
||||
recordedVersionId: number;
|
||||
return ((element instanceof EditStackElement) || (element instanceof MultiModelEditStackElement));
|
||||
}
|
||||
|
||||
export class EditStack {
|
||||
@@ -131,7 +168,7 @@ export class EditStack {
|
||||
|
||||
public pushStackElement(): void {
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement) {
|
||||
if (isKnownStackElement(lastElement)) {
|
||||
lastElement.close();
|
||||
}
|
||||
}
|
||||
@@ -140,32 +177,27 @@ export class EditStack {
|
||||
this._undoRedoService.removeElements(this._model.uri);
|
||||
}
|
||||
|
||||
public pushEOL(eol: EndOfLineSequence): void {
|
||||
const beforeVersionId = this._model.getAlternativeVersionId();
|
||||
const inverseEOL = getModelEOL(this._model);
|
||||
this._model.setEOL(eol);
|
||||
const afterVersionId = this._model.getAlternativeVersionId();
|
||||
|
||||
private _getOrCreateEditStackElement(beforeCursorState: Selection[] | null): EditStackElement | MultiModelEditStackElement {
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement) {
|
||||
lastElement.close();
|
||||
if (isKnownStackElement(lastElement) && lastElement.canAppend(this._model)) {
|
||||
return lastElement;
|
||||
}
|
||||
this._undoRedoService.pushElement(new EOLStackElement(this._model, inverseEOL, beforeVersionId, afterVersionId));
|
||||
const newElement = new EditStackElement(this._model, beforeCursorState);
|
||||
this._undoRedoService.pushElement(newElement);
|
||||
return newElement;
|
||||
}
|
||||
|
||||
public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
|
||||
const beforeVersionId = this._model.getAlternativeVersionId();
|
||||
public pushEOL(eol: EndOfLineSequence): void {
|
||||
const editStackElement = this._getOrCreateEditStackElement(null);
|
||||
this._model.setEOL(eol);
|
||||
editStackElement.append(this._model, [], getModelEOL(this._model), this._model.getAlternativeVersionId(), null);
|
||||
}
|
||||
|
||||
public pushEditOperation(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
|
||||
const editStackElement = this._getOrCreateEditStackElement(beforeCursorState);
|
||||
const inverseEditOperations = this._model.applyEdits(editOperations);
|
||||
const afterVersionId = this._model.getAlternativeVersionId();
|
||||
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
|
||||
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement && lastElement.isOpen()) {
|
||||
lastElement.append(inverseEditOperations, afterVersionId, afterCursorState);
|
||||
} else {
|
||||
this._undoRedoService.pushElement(new EditStackElement(this._model, beforeVersionId, beforeCursorState, afterVersionId, afterCursorState, inverseEditOperations));
|
||||
}
|
||||
|
||||
editStackElement.append(this._model, inverseEditOperations, getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState);
|
||||
return afterCursorState;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import { Color } from 'vs/base/common/color';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
import { EditorTheme } from 'vs/editor/common/view/viewContext';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
|
||||
function createTextBufferBuilder() {
|
||||
return new PieceTreeTextBufferBuilder();
|
||||
@@ -189,10 +188,6 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
|
||||
};
|
||||
|
||||
public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel {
|
||||
return new TextModel(text, options, languageIdentifier, uri, new UndoRedoService());
|
||||
}
|
||||
|
||||
public static resolveOptions(textBuffer: model.ITextBuffer, options: model.ITextModelCreationOptions): model.TextModelResolvedOptions {
|
||||
if (options.detectIndentation) {
|
||||
const guessedIndentation = guessIndentation(textBuffer, options.tabSize, options.insertSpaces);
|
||||
@@ -494,21 +489,6 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
);
|
||||
}
|
||||
|
||||
_setEOL(eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
this._isUndoing = isUndoing;
|
||||
this._isRedoing = isRedoing;
|
||||
this.setEOL(eol);
|
||||
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
|
||||
} finally {
|
||||
this._isUndoing = false;
|
||||
this._eventEmitter.endDeferredEmit(resultingSelection);
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
private _onBeforeEOLChange(): void {
|
||||
// Ensure all decorations get their `range` set.
|
||||
const versionId = this.getVersionId();
|
||||
@@ -1202,7 +1182,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return result;
|
||||
}
|
||||
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
public pushEditOperations(beforeCursorState: Selection[] | null, editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1213,7 +1193,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.ValidAnnotatedEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
private _pushEditOperations(beforeCursorState: Selection[] | null, editOperations: model.ValidAnnotatedEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
|
||||
// Go through each saved line number and insert a trim whitespace edit
|
||||
// if it is safe to do so (no conflicts with other edits).
|
||||
@@ -1228,22 +1208,24 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
// Sometimes, auto-formatters change ranges automatically which can cause undesired auto whitespace trimming near the cursor
|
||||
// We'll use the following heuristic: if the edits occur near the cursor, then it's ok to trim auto whitespace
|
||||
let editsAreNearCursors = true;
|
||||
for (let i = 0, len = beforeCursorState.length; i < len; i++) {
|
||||
let sel = beforeCursorState[i];
|
||||
let foundEditNearSel = false;
|
||||
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
|
||||
let editRange = incomingEdits[j].range;
|
||||
let selIsAbove = editRange.startLineNumber > sel.endLineNumber;
|
||||
let selIsBelow = sel.startLineNumber > editRange.endLineNumber;
|
||||
if (!selIsAbove && !selIsBelow) {
|
||||
foundEditNearSel = true;
|
||||
if (beforeCursorState) {
|
||||
for (let i = 0, len = beforeCursorState.length; i < len; i++) {
|
||||
let sel = beforeCursorState[i];
|
||||
let foundEditNearSel = false;
|
||||
for (let j = 0, lenJ = incomingEdits.length; j < lenJ; j++) {
|
||||
let editRange = incomingEdits[j].range;
|
||||
let selIsAbove = editRange.startLineNumber > sel.endLineNumber;
|
||||
let selIsBelow = sel.startLineNumber > editRange.endLineNumber;
|
||||
if (!selIsAbove && !selIsBelow) {
|
||||
foundEditNearSel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundEditNearSel) {
|
||||
editsAreNearCursors = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundEditNearSel) {
|
||||
editsAreNearCursors = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (editsAreNearCursors) {
|
||||
@@ -1298,7 +1280,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);
|
||||
}
|
||||
|
||||
_applyEdits(edits: model.IValidEditOperations[], isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): model.IValidEditOperations[] {
|
||||
_applyUndoRedoEdits(edits: model.IValidEditOperations[], eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): model.IValidEditOperations[] {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1308,10 +1290,12 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
for (let i = 0, len = edits.length; i < len; i++) {
|
||||
reverseEdits[i] = { operations: this.applyEdits(edits[i].operations) };
|
||||
}
|
||||
this.setEOL(eol);
|
||||
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
|
||||
return reverseEdits;
|
||||
} finally {
|
||||
this._isUndoing = false;
|
||||
this._isRedoing = false;
|
||||
this._eventEmitter.endDeferredEmit(resultingSelection);
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
|
||||
@@ -635,6 +635,9 @@ export interface CodeActionList extends IDisposable {
|
||||
* @internal
|
||||
*/
|
||||
export interface CodeActionProvider {
|
||||
|
||||
displayName?: string
|
||||
|
||||
/**
|
||||
* Provide commands for the given document and range.
|
||||
*/
|
||||
|
||||
@@ -178,105 +178,106 @@ export enum EditorOption {
|
||||
autoSurround = 10,
|
||||
codeLens = 11,
|
||||
colorDecorators = 12,
|
||||
comments = 13,
|
||||
contextmenu = 14,
|
||||
copyWithSyntaxHighlighting = 15,
|
||||
cursorBlinking = 16,
|
||||
cursorSmoothCaretAnimation = 17,
|
||||
cursorStyle = 18,
|
||||
cursorSurroundingLines = 19,
|
||||
cursorSurroundingLinesStyle = 20,
|
||||
cursorWidth = 21,
|
||||
disableLayerHinting = 22,
|
||||
disableMonospaceOptimizations = 23,
|
||||
dragAndDrop = 24,
|
||||
emptySelectionClipboard = 25,
|
||||
extraEditorClassName = 26,
|
||||
fastScrollSensitivity = 27,
|
||||
find = 28,
|
||||
fixedOverflowWidgets = 29,
|
||||
folding = 30,
|
||||
foldingStrategy = 31,
|
||||
foldingHighlight = 32,
|
||||
fontFamily = 33,
|
||||
fontInfo = 34,
|
||||
fontLigatures = 35,
|
||||
fontSize = 36,
|
||||
fontWeight = 37,
|
||||
formatOnPaste = 38,
|
||||
formatOnType = 39,
|
||||
glyphMargin = 40,
|
||||
gotoLocation = 41,
|
||||
hideCursorInOverviewRuler = 42,
|
||||
highlightActiveIndentGuide = 43,
|
||||
hover = 44,
|
||||
inDiffEditor = 45,
|
||||
letterSpacing = 46,
|
||||
lightbulb = 47,
|
||||
lineDecorationsWidth = 48,
|
||||
lineHeight = 49,
|
||||
lineNumbers = 50,
|
||||
lineNumbersMinChars = 51,
|
||||
links = 52,
|
||||
matchBrackets = 53,
|
||||
minimap = 54,
|
||||
mouseStyle = 55,
|
||||
mouseWheelScrollSensitivity = 56,
|
||||
mouseWheelZoom = 57,
|
||||
multiCursorMergeOverlapping = 58,
|
||||
multiCursorModifier = 59,
|
||||
multiCursorPaste = 60,
|
||||
occurrencesHighlight = 61,
|
||||
overviewRulerBorder = 62,
|
||||
overviewRulerLanes = 63,
|
||||
padding = 64,
|
||||
parameterHints = 65,
|
||||
peekWidgetDefaultFocus = 66,
|
||||
definitionLinkOpensInPeek = 67,
|
||||
quickSuggestions = 68,
|
||||
quickSuggestionsDelay = 69,
|
||||
readOnly = 70,
|
||||
renderControlCharacters = 71,
|
||||
renderIndentGuides = 72,
|
||||
renderFinalNewline = 73,
|
||||
renderLineHighlight = 74,
|
||||
renderValidationDecorations = 75,
|
||||
renderWhitespace = 76,
|
||||
revealHorizontalRightPadding = 77,
|
||||
roundedSelection = 78,
|
||||
rulers = 79,
|
||||
scrollbar = 80,
|
||||
scrollBeyondLastColumn = 81,
|
||||
scrollBeyondLastLine = 82,
|
||||
scrollPredominantAxis = 83,
|
||||
selectionClipboard = 84,
|
||||
selectionHighlight = 85,
|
||||
selectOnLineNumbers = 86,
|
||||
showFoldingControls = 87,
|
||||
showUnused = 88,
|
||||
snippetSuggestions = 89,
|
||||
smoothScrolling = 90,
|
||||
stopRenderingLineAfter = 91,
|
||||
suggest = 92,
|
||||
suggestFontSize = 93,
|
||||
suggestLineHeight = 94,
|
||||
suggestOnTriggerCharacters = 95,
|
||||
suggestSelection = 96,
|
||||
tabCompletion = 97,
|
||||
useTabStops = 98,
|
||||
wordSeparators = 99,
|
||||
wordWrap = 100,
|
||||
wordWrapBreakAfterCharacters = 101,
|
||||
wordWrapBreakBeforeCharacters = 102,
|
||||
wordWrapColumn = 103,
|
||||
wordWrapMinified = 104,
|
||||
wrappingIndent = 105,
|
||||
wrappingStrategy = 106,
|
||||
editorClassName = 107,
|
||||
pixelRatio = 108,
|
||||
tabFocusMode = 109,
|
||||
layoutInfo = 110,
|
||||
wrappingInfo = 111
|
||||
columnSelection = 13,
|
||||
comments = 14,
|
||||
contextmenu = 15,
|
||||
copyWithSyntaxHighlighting = 16,
|
||||
cursorBlinking = 17,
|
||||
cursorSmoothCaretAnimation = 18,
|
||||
cursorStyle = 19,
|
||||
cursorSurroundingLines = 20,
|
||||
cursorSurroundingLinesStyle = 21,
|
||||
cursorWidth = 22,
|
||||
disableLayerHinting = 23,
|
||||
disableMonospaceOptimizations = 24,
|
||||
dragAndDrop = 25,
|
||||
emptySelectionClipboard = 26,
|
||||
extraEditorClassName = 27,
|
||||
fastScrollSensitivity = 28,
|
||||
find = 29,
|
||||
fixedOverflowWidgets = 30,
|
||||
folding = 31,
|
||||
foldingStrategy = 32,
|
||||
foldingHighlight = 33,
|
||||
fontFamily = 34,
|
||||
fontInfo = 35,
|
||||
fontLigatures = 36,
|
||||
fontSize = 37,
|
||||
fontWeight = 38,
|
||||
formatOnPaste = 39,
|
||||
formatOnType = 40,
|
||||
glyphMargin = 41,
|
||||
gotoLocation = 42,
|
||||
hideCursorInOverviewRuler = 43,
|
||||
highlightActiveIndentGuide = 44,
|
||||
hover = 45,
|
||||
inDiffEditor = 46,
|
||||
letterSpacing = 47,
|
||||
lightbulb = 48,
|
||||
lineDecorationsWidth = 49,
|
||||
lineHeight = 50,
|
||||
lineNumbers = 51,
|
||||
lineNumbersMinChars = 52,
|
||||
links = 53,
|
||||
matchBrackets = 54,
|
||||
minimap = 55,
|
||||
mouseStyle = 56,
|
||||
mouseWheelScrollSensitivity = 57,
|
||||
mouseWheelZoom = 58,
|
||||
multiCursorMergeOverlapping = 59,
|
||||
multiCursorModifier = 60,
|
||||
multiCursorPaste = 61,
|
||||
occurrencesHighlight = 62,
|
||||
overviewRulerBorder = 63,
|
||||
overviewRulerLanes = 64,
|
||||
padding = 65,
|
||||
parameterHints = 66,
|
||||
peekWidgetDefaultFocus = 67,
|
||||
definitionLinkOpensInPeek = 68,
|
||||
quickSuggestions = 69,
|
||||
quickSuggestionsDelay = 70,
|
||||
readOnly = 71,
|
||||
renderControlCharacters = 72,
|
||||
renderIndentGuides = 73,
|
||||
renderFinalNewline = 74,
|
||||
renderLineHighlight = 75,
|
||||
renderValidationDecorations = 76,
|
||||
renderWhitespace = 77,
|
||||
revealHorizontalRightPadding = 78,
|
||||
roundedSelection = 79,
|
||||
rulers = 80,
|
||||
scrollbar = 81,
|
||||
scrollBeyondLastColumn = 82,
|
||||
scrollBeyondLastLine = 83,
|
||||
scrollPredominantAxis = 84,
|
||||
selectionClipboard = 85,
|
||||
selectionHighlight = 86,
|
||||
selectOnLineNumbers = 87,
|
||||
showFoldingControls = 88,
|
||||
showUnused = 89,
|
||||
snippetSuggestions = 90,
|
||||
smoothScrolling = 91,
|
||||
stopRenderingLineAfter = 92,
|
||||
suggest = 93,
|
||||
suggestFontSize = 94,
|
||||
suggestLineHeight = 95,
|
||||
suggestOnTriggerCharacters = 96,
|
||||
suggestSelection = 97,
|
||||
tabCompletion = 98,
|
||||
useTabStops = 99,
|
||||
wordSeparators = 100,
|
||||
wordWrap = 101,
|
||||
wordWrapBreakAfterCharacters = 102,
|
||||
wordWrapBreakBeforeCharacters = 103,
|
||||
wordWrapColumn = 104,
|
||||
wordWrapMinified = 105,
|
||||
wrappingIndent = 106,
|
||||
wrappingStrategy = 107,
|
||||
editorClassName = 108,
|
||||
pixelRatio = 109,
|
||||
tabFocusMode = 110,
|
||||
layoutInfo = 111,
|
||||
wrappingInfo = 112
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { BracketMatchingController } from 'vs/editor/contrib/bracketMatching/bracketMatching';
|
||||
@@ -31,7 +31,7 @@ suite('bracket matching', () => {
|
||||
|
||||
test('issue #183: jump to matching bracket position', () => {
|
||||
let mode = new BracketMode();
|
||||
let model = TextModel.createFromString('var x = (3 + (5-7)) + ((5+3)+5);', undefined, mode.getLanguageIdentifier());
|
||||
let model = createTextModel('var x = (3 + (5-7)) + ((5+3)+5);', undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
let bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
@@ -63,7 +63,7 @@ suite('bracket matching', () => {
|
||||
|
||||
test('Jump to next bracket', () => {
|
||||
let mode = new BracketMode();
|
||||
let model = TextModel.createFromString('var x = (3 + (5-7)); y();', undefined, mode.getLanguageIdentifier());
|
||||
let model = createTextModel('var x = (3 + (5-7)); y();', undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
let bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
@@ -100,7 +100,7 @@ suite('bracket matching', () => {
|
||||
|
||||
test('Select to next bracket', () => {
|
||||
let mode = new BracketMode();
|
||||
let model = TextModel.createFromString('var x = (3 + (5-7)); y();', undefined, mode.getLanguageIdentifier());
|
||||
let model = createTextModel('var x = (3 + (5-7)); y();', undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
let bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
@@ -152,7 +152,7 @@ suite('bracket matching', () => {
|
||||
'};',
|
||||
].join('\n');
|
||||
const mode = new BracketMode();
|
||||
const model = TextModel.createFromString(text, undefined, mode.getLanguageIdentifier());
|
||||
const model = createTextModel(text, undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
const bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
@@ -177,7 +177,7 @@ suite('bracket matching', () => {
|
||||
'};',
|
||||
].join('\n');
|
||||
const mode = new BracketMode();
|
||||
const model = TextModel.createFromString(text, undefined, mode.getLanguageIdentifier());
|
||||
const model = createTextModel(text, undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
const bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
@@ -195,7 +195,7 @@ suite('bracket matching', () => {
|
||||
|
||||
test('issue #45369: Select to Bracket with multicursor', () => {
|
||||
let mode = new BracketMode();
|
||||
let model = TextModel.createFromString('{ } { } { }', undefined, mode.getLanguageIdentifier());
|
||||
let model = createTextModel('{ } { } { }', undefined, mode.getLanguageIdentifier());
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
let bracketMatchingController = editor.registerAndInstantiateContribution<BracketMatchingController>(BracketMatchingController.ID, BracketMatchingController);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { ITextModel } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, filtersAction, mayIncludeActionsOfKind } from './types';
|
||||
import { IProgress, Progress } from 'vs/platform/progress/common/progress';
|
||||
|
||||
export const codeActionCommandId = 'editor.action.codeAction';
|
||||
export const refactorCommandId = 'editor.action.refactor';
|
||||
@@ -70,7 +71,8 @@ export function getCodeActions(
|
||||
model: ITextModel,
|
||||
rangeOrSelection: Range | Selection,
|
||||
trigger: CodeActionTrigger,
|
||||
token: CancellationToken
|
||||
progress: IProgress<modes.CodeActionProvider>,
|
||||
token: CancellationToken,
|
||||
): Promise<CodeActionSet> {
|
||||
const filter = trigger.filter || {};
|
||||
|
||||
@@ -85,6 +87,7 @@ export function getCodeActions(
|
||||
const disposables = new DisposableStore();
|
||||
const promises = providers.map(async provider => {
|
||||
try {
|
||||
progress.report(provider);
|
||||
const providedCodeActions = await provider.provideCodeActions(model, rangeOrSelection, codeActionContext, cts.token);
|
||||
if (providedCodeActions) {
|
||||
disposables.add(providedCodeActions);
|
||||
@@ -210,6 +213,7 @@ registerLanguageCommand('_executeCodeActionProvider', async function (accessor,
|
||||
model,
|
||||
validatedRangeOrSelection,
|
||||
{ type: modes.CodeActionTriggerType.Manual, filter: { includeSourceActions: true, include: kind && kind.value ? new CodeActionKind(kind.value) : undefined } },
|
||||
Progress.None,
|
||||
CancellationToken.None);
|
||||
|
||||
setTimeout(() => codeActionSet.dispose(), 100);
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { CodeActionProviderRegistry, CodeActionTriggerType } from 'vs/editor/common/modes';
|
||||
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { IEditorProgressService, Progress } from 'vs/platform/progress/common/progress';
|
||||
import { getCodeActions, CodeActionSet } from './codeAction';
|
||||
import { CodeActionTrigger } from './types';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -213,7 +213,7 @@ export class CodeActionModel extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const actions = createCancelablePromise(token => getCodeActions(model, trigger.selection, trigger.trigger, token));
|
||||
const actions = createCancelablePromise(token => getCodeActions(model, trigger.selection, trigger.trigger, Progress.None, token));
|
||||
if (this._progressService && trigger.trigger.type === CodeActionTriggerType.Manual) {
|
||||
this._progressService.showWhile(actions, 250);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
|
||||
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
function staticCodeActionProvider(...actions: modes.CodeAction[]): modes.CodeActionProvider {
|
||||
return new class implements modes.CodeActionProvider {
|
||||
@@ -92,7 +94,7 @@ suite('CodeAction', () => {
|
||||
|
||||
setup(function () {
|
||||
disposables.clear();
|
||||
model = TextModel.createFromString('test1\ntest2\ntest3', undefined, langId, uri);
|
||||
model = createTextModel('test1\ntest2\ntest3', undefined, langId, uri);
|
||||
disposables.add(model);
|
||||
});
|
||||
|
||||
@@ -125,7 +127,7 @@ suite('CodeAction', () => {
|
||||
testData.tsLint.abc
|
||||
];
|
||||
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Manual }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 6);
|
||||
assert.deepEqual(actions, expected);
|
||||
});
|
||||
@@ -140,20 +142,20 @@ suite('CodeAction', () => {
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 2);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
assert.strictEqual(actions[1].title, 'a.b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b') } }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a.b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b.c') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b.c') } }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 0);
|
||||
}
|
||||
});
|
||||
@@ -172,7 +174,7 @@ suite('CodeAction', () => {
|
||||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
});
|
||||
@@ -186,13 +188,13 @@ suite('CodeAction', () => {
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: modes.CodeActionTriggerType.Auto, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
}
|
||||
@@ -214,7 +216,7 @@ suite('CodeAction', () => {
|
||||
excludes: [CodeActionKind.Source],
|
||||
includeSourceActions: true,
|
||||
}
|
||||
}, CancellationToken.None);
|
||||
}, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'b');
|
||||
}
|
||||
@@ -250,7 +252,7 @@ suite('CodeAction', () => {
|
||||
include: baseType,
|
||||
excludes: [subType],
|
||||
}
|
||||
}, CancellationToken.None);
|
||||
}, Progress.None, CancellationToken.None);
|
||||
assert.strictEqual(didInvoke, false);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
@@ -275,7 +277,7 @@ suite('CodeAction', () => {
|
||||
filter: {
|
||||
include: CodeActionKind.QuickFix
|
||||
}
|
||||
}, CancellationToken.None);
|
||||
}, Progress.None, CancellationToken.None);
|
||||
assert.strictEqual(actions.length, 0);
|
||||
assert.strictEqual(wasInvoked, false);
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ import { CodeActionModel, CodeActionsState } from 'vs/editor/contrib/codeAction/
|
||||
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';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
const testProvider = {
|
||||
provideCodeActions(): modes.CodeActionList {
|
||||
@@ -38,7 +39,7 @@ suite('CodeActionModel', () => {
|
||||
setup(() => {
|
||||
disposables.clear();
|
||||
markerService = new MarkerService();
|
||||
model = TextModel.createFromString('foobar foo bar\nfarboo far boo', undefined, languageIdentifier, uri);
|
||||
model = createTextModel('foobar foo bar\nfarboo far boo', undefined, languageIdentifier, uri);
|
||||
editor = createTestCodeEditor({ model: model });
|
||||
editor.setPosition({ lineNumber: 1, column: 1 });
|
||||
});
|
||||
|
||||
@@ -68,7 +68,7 @@ export class DragAndDropController extends Disposable implements IEditorContribu
|
||||
}
|
||||
|
||||
private onEditorKeyDown(e: IKeyboardEvent): void {
|
||||
if (!this._editor.getOption(EditorOption.dragAndDrop)) {
|
||||
if (!this._editor.getOption(EditorOption.dragAndDrop) || this._editor.getOption(EditorOption.columnSelection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ export class DragAndDropController extends Disposable implements IEditorContribu
|
||||
}
|
||||
|
||||
private onEditorKeyUp(e: IKeyboardEvent): void {
|
||||
if (!this._editor.getOption(EditorOption.dragAndDrop)) {
|
||||
if (!this._editor.getOption(EditorOption.dragAndDrop) || this._editor.getOption(EditorOption.columnSelection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { OutlineElement, OutlineGroup, OutlineModel } from '../outlineModel';
|
||||
import { SymbolKind, DocumentSymbol, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
|
||||
@@ -16,7 +16,7 @@ suite('OutlineModel', function () {
|
||||
|
||||
test('OutlineModel#create, cached', async function () {
|
||||
|
||||
let model = TextModel.createFromString('foo', undefined, undefined, URI.file('/fome/path.foo'));
|
||||
let model = createTextModel('foo', undefined, undefined, URI.file('/fome/path.foo'));
|
||||
let count = 0;
|
||||
let reg = DocumentSymbolProviderRegistry.register({ pattern: '**/path.foo' }, {
|
||||
provideDocumentSymbols() {
|
||||
@@ -42,7 +42,7 @@ suite('OutlineModel', function () {
|
||||
|
||||
test('OutlineModel#create, cached/cancel', async function () {
|
||||
|
||||
let model = TextModel.createFromString('foo', undefined, undefined, URI.file('/fome/path.foo'));
|
||||
let model = createTextModel('foo', undefined, undefined, URI.file('/fome/path.foo'));
|
||||
let isCancelled = false;
|
||||
|
||||
let reg = DocumentSymbolProviderRegistry.register({ pattern: '**/path.foo' }, {
|
||||
|
||||
@@ -16,6 +16,8 @@ import { FindModelBoundToEditorModel } from 'vs/editor/contrib/find/findModel';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
|
||||
suite('FindModel', () => {
|
||||
|
||||
@@ -45,7 +47,7 @@ suite('FindModel', () => {
|
||||
const factory = ptBuilder.finish();
|
||||
withTestCodeEditor([],
|
||||
{
|
||||
model: new TextModel(factory, TextModel.DEFAULT_CREATION_OPTIONS, null, null, new UndoRedoService())
|
||||
model: new TextModel(factory, TextModel.DEFAULT_CREATION_OPTIONS, null, null, new UndoRedoService(new TestDialogService(), new TestNotificationService()))
|
||||
},
|
||||
(editor, cursor) => callback(editor as unknown as IActiveCodeEditor, cursor)
|
||||
);
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { FoldingModel, setCollapseStateAtLevel, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateUp } from 'vs/editor/contrib/folding/foldingModel';
|
||||
import { TextModel, ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { TrackedRangeStickiness, IModelDeltaDecoration, ITextModel, IModelDecorationsChangeAccessor } from 'vs/editor/common/model';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
@@ -92,7 +93,7 @@ suite('Folding Model', () => {
|
||||
/* 7*/ ' }',
|
||||
/* 8*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -131,7 +132,7 @@ suite('Folding Model', () => {
|
||||
/* 7*/ ' }',
|
||||
/* 8*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -177,7 +178,7 @@ suite('Folding Model', () => {
|
||||
/* 7*/ ' }',
|
||||
/* 8*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -217,7 +218,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -254,7 +255,7 @@ suite('Folding Model', () => {
|
||||
/* 7*/ ' }',
|
||||
/* 8*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -295,7 +296,7 @@ suite('Folding Model', () => {
|
||||
/* 11*/ ' }',
|
||||
/* 12*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
@@ -346,7 +347,7 @@ suite('Folding Model', () => {
|
||||
/* 10*/ '//#endregion',
|
||||
/* 11*/ ''];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -392,7 +393,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -448,7 +449,7 @@ suite('Folding Model', () => {
|
||||
/* 15*/ ' //#endregion',
|
||||
/* 16*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -504,7 +505,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -556,7 +557,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -603,7 +604,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
@@ -648,7 +649,7 @@ suite('Folding Model', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { FoldingMarkers } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { MAX_FOLDING_REGIONS } from 'vs/editor/contrib/folding/foldingRanges';
|
||||
@@ -26,7 +26,7 @@ suite('FoldingRanges', () => {
|
||||
for (let i = 0; i < nRegions; i++) {
|
||||
lines.push('#endregion');
|
||||
}
|
||||
let model = TextModel.createFromString(lines.join('\n'));
|
||||
let model = createTextModel(lines.join('\n'));
|
||||
let actual = computeRanges(model, false, markers, MAX_FOLDING_REGIONS);
|
||||
assert.equal(actual.length, nRegions, 'len');
|
||||
for (let i = 0; i < nRegions; i++) {
|
||||
@@ -53,7 +53,7 @@ suite('FoldingRanges', () => {
|
||||
/* 12*/ ' }',
|
||||
/* 13*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
try {
|
||||
let actual = computeRanges(textModel, false, markers);
|
||||
// let r0 = r(1, 2);
|
||||
@@ -91,7 +91,7 @@ suite('FoldingRanges', () => {
|
||||
for (let i = 0; i < nRegions; i++) {
|
||||
lines.push('#endregion');
|
||||
}
|
||||
let model = TextModel.createFromString(lines.join('\n'));
|
||||
let model = createTextModel(lines.join('\n'));
|
||||
let actual = computeRanges(model, false, markers, MAX_FOLDING_REGIONS);
|
||||
assert.equal(actual.length, nRegions, 'len');
|
||||
for (let i = 0; i < nRegions; i++) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { FoldingModel } from 'vs/editor/contrib/folding/foldingModel';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { TestDecorationProvider } from './foldingModel.test';
|
||||
import { HiddenRangeModel } from 'vs/editor/contrib/folding/hiddenRangeModel';
|
||||
@@ -38,7 +38,7 @@ suite('Hidden Range Model', () => {
|
||||
/* 9*/ ' }',
|
||||
/* 10*/ '}'];
|
||||
|
||||
let textModel = TextModel.createFromString(lines.join('\n'));
|
||||
let textModel = createTextModel(lines.join('\n'));
|
||||
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
|
||||
let hiddenRangeModel = new HiddenRangeModel(foldingModel);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
interface IndentRange {
|
||||
start: number;
|
||||
@@ -47,7 +47,7 @@ suite('Indentation Folding', () => {
|
||||
let r8 = r(13, 14);//4
|
||||
let r9 = r(15, 16);//0
|
||||
|
||||
let model = TextModel.createFromString(lines.join('\n'));
|
||||
let model = createTextModel(lines.join('\n'));
|
||||
|
||||
function assertLimit(maxEntries: number, expectedRanges: IndentRange[], message: string) {
|
||||
let indentRanges = computeRanges(model, true, undefined, maxEntries);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
|
||||
import { FoldingMarkers } from 'vs/editor/common/modes/languageConfiguration';
|
||||
|
||||
@@ -15,7 +15,7 @@ interface ExpectedIndentRange {
|
||||
}
|
||||
|
||||
function assertRanges(lines: string[], expected: ExpectedIndentRange[], offside: boolean, markers?: FoldingMarkers): void {
|
||||
let model = TextModel.createFromString(lines.join('\n'));
|
||||
let model = createTextModel(lines.join('\n'));
|
||||
let actual = computeRanges(model, offside, markers);
|
||||
|
||||
let actualRanges: ExpectedIndentRange[] = [];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { SyntaxRangeProvider } from 'vs/editor/contrib/folding/syntaxRangeProvider';
|
||||
import { FoldingRangeProvider, FoldingRange, FoldingContext, ProviderResult } from 'vs/editor/common/modes';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -69,7 +69,7 @@ suite('Syntax folding', () => {
|
||||
let r8 = r(14, 15); //6
|
||||
let r9 = r(22, 23); //0
|
||||
|
||||
let model = TextModel.createFromString(lines.join('\n'));
|
||||
let model = createTextModel(lines.join('\n'));
|
||||
let ranges = [r1, r2, r3, r4, r5, r6, r7, r8, r9];
|
||||
let providers = [new TestFoldingRangeProvider(model, ranges)];
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { assertType } from 'vs/base/common/types';
|
||||
import { IProgress } from 'vs/platform/progress/common/progress';
|
||||
|
||||
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
|
||||
|
||||
@@ -209,6 +210,7 @@ export async function formatDocumentWithSelectedProvider(
|
||||
accessor: ServicesAccessor,
|
||||
editorOrModel: ITextModel | IActiveCodeEditor,
|
||||
mode: FormattingMode,
|
||||
progress: IProgress<DocumentFormattingEditProvider>,
|
||||
token: CancellationToken
|
||||
): Promise<void> {
|
||||
|
||||
@@ -217,6 +219,7 @@ export async function formatDocumentWithSelectedProvider(
|
||||
const provider = getRealAndSyntheticDocumentFormattersOrdered(model);
|
||||
const selected = await FormattingConflicts.select(provider, model, mode);
|
||||
if (selected) {
|
||||
progress.report(selected);
|
||||
await instaService.invokeFunction(formatDocumentWithProvider, selected, editorOrModel, mode, token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
|
||||
class FormatOnType implements IEditorContribution {
|
||||
|
||||
@@ -230,7 +231,7 @@ class FormatDocumentAction extends EditorAction {
|
||||
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
|
||||
if (editor.hasModel()) {
|
||||
const instaService = accessor.get(IInstantiationService);
|
||||
await instaService.invokeFunction(formatDocumentWithSelectedProvider, editor, FormattingMode.Explicit, CancellationToken.None);
|
||||
await instaService.invokeFunction(formatDocumentWithSelectedProvider, editor, FormattingMode.Explicit, Progress.None, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import * as peekView from 'vs/editor/contrib/peekView/peekView';
|
||||
import { FileReferences, OneReference, ReferencesModel } from '../referencesModel';
|
||||
import { FuzzyScore } from 'vs/base/common/filters';
|
||||
import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
|
||||
|
||||
class DecorationsManager implements IDisposable {
|
||||
@@ -215,7 +216,8 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
||||
@ITextModelService private readonly _textModelResolverService: ITextModelService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@peekView.IPeekViewService private readonly _peekViewService: peekView.IPeekViewService,
|
||||
@ILabelService private readonly _uriLabel: ILabelService
|
||||
@ILabelService private readonly _uriLabel: ILabelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
) {
|
||||
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true });
|
||||
|
||||
@@ -304,7 +306,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
||||
};
|
||||
this._preview = this._instantiationService.createInstance(EmbeddedCodeEditorWidget, this._previewContainer, options, this.editor);
|
||||
dom.hide(this._previewContainer);
|
||||
this._previewNotAvailableMessage = TextModel.createFromString(nls.localize('missingPreviewMessage', "no preview available"));
|
||||
this._previewNotAvailableMessage = new TextModel(nls.localize('missingPreviewMessage', "no preview available"), TextModel.DEFAULT_CREATION_OPTIONS, null, null, this._undoRedoService);
|
||||
|
||||
// tree
|
||||
this._treeContainer = dom.append(containerElement, dom.$('div.ref-tree.inline'));
|
||||
|
||||
@@ -40,6 +40,7 @@ import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
import { textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -626,6 +627,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
this._editor.getModel()!,
|
||||
new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn),
|
||||
markerCodeActionTrigger,
|
||||
Progress.None,
|
||||
cancellationToken);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Handler } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
@@ -49,7 +49,7 @@ suite('ParameterHintsModel', () => {
|
||||
});
|
||||
|
||||
function createMockEditor(fileContents: string) {
|
||||
const textModel = TextModel.createFromString(fileContents, undefined, undefined, mockFile);
|
||||
const textModel = createTextModel(fileContents, undefined, undefined, mockFile);
|
||||
const editor = createTestCodeEditor({
|
||||
model: textModel,
|
||||
serviceCollection: new ServiceCollection(
|
||||
|
||||
@@ -20,6 +20,8 @@ import { TestTextResourcePropertiesService } from 'vs/editor/test/common/service
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
|
||||
class MockJSMode extends MockMode {
|
||||
|
||||
@@ -48,7 +50,7 @@ suite('SmartSelect', () => {
|
||||
|
||||
setup(() => {
|
||||
const configurationService = new TestConfigurationService();
|
||||
modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService(), new NullLogService(), new UndoRedoService());
|
||||
modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService(), new NullLogService(), new UndoRedoService(new TestDialogService(), new TestNotificationService()));
|
||||
mode = new MockJSMode();
|
||||
});
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { Handler } from 'vs/editor/common/editorCommon';
|
||||
import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('SnippetController2', function () {
|
||||
|
||||
@@ -36,7 +37,7 @@ suite('SnippetController2', function () {
|
||||
|
||||
setup(function () {
|
||||
contextKeys = new MockContextKeyService();
|
||||
model = TextModel.createFromString('if\n $state\nfi');
|
||||
model = createTextModel('if\n $state\nfi');
|
||||
editor = createTestCodeEditor({ model: model });
|
||||
editor.setSelections([new Selection(1, 1, 1, 1), new Selection(2, 5, 2, 5)]);
|
||||
assert.equal(model.getEOL(), '\n');
|
||||
|
||||
@@ -11,6 +11,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { SnippetParser } from 'vs/editor/contrib/snippet/snippetParser';
|
||||
import { SnippetSession } from 'vs/editor/contrib/snippet/snippetSession';
|
||||
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('SnippetSession', function () {
|
||||
|
||||
@@ -26,7 +27,7 @@ suite('SnippetSession', function () {
|
||||
}
|
||||
|
||||
setup(function () {
|
||||
model = TextModel.createFromString('function foo() {\n console.log(a);\n}');
|
||||
model = createTextModel('function foo() {\n console.log(a);\n}');
|
||||
editor = createTestCodeEditor({ model: model }) as IActiveCodeEditor;
|
||||
editor.setSelections([new Selection(1, 1, 1, 1), new Selection(2, 5, 2, 5)]);
|
||||
assert.equal(model.getEOL(), '\n');
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { Workspace, toWorkspaceFolders, IWorkspace, IWorkspaceContextService, toWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { mock } from 'vs/editor/contrib/suggest/test/suggestModel.test';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('Snippet Variables Resolver', function () {
|
||||
|
||||
@@ -25,7 +26,7 @@ suite('Snippet Variables Resolver', function () {
|
||||
let resolver: VariableResolver;
|
||||
|
||||
setup(function () {
|
||||
model = TextModel.createFromString([
|
||||
model = createTextModel([
|
||||
'this is line one',
|
||||
'this is line two',
|
||||
' this is line three'
|
||||
@@ -67,7 +68,7 @@ suite('Snippet Variables Resolver', function () {
|
||||
|
||||
resolver = new ModelBasedVariableResolver(
|
||||
labelService,
|
||||
TextModel.createFromString('', undefined, undefined, URI.parse('http://www.pb.o/abc/def/ghi'))
|
||||
createTextModel('', undefined, undefined, URI.parse('http://www.pb.o/abc/def/ghi'))
|
||||
);
|
||||
assertVariableResolve(resolver, 'TM_FILENAME', 'ghi');
|
||||
if (!isWindows) {
|
||||
@@ -77,7 +78,7 @@ suite('Snippet Variables Resolver', function () {
|
||||
|
||||
resolver = new ModelBasedVariableResolver(
|
||||
labelService,
|
||||
TextModel.createFromString('', undefined, undefined, URI.parse('mem:fff.ts'))
|
||||
createTextModel('', undefined, undefined, URI.parse('mem:fff.ts'))
|
||||
);
|
||||
assertVariableResolve(resolver, 'TM_DIRECTORY', '');
|
||||
assertVariableResolve(resolver, 'TM_FILEPATH', 'fff.ts');
|
||||
@@ -92,7 +93,7 @@ suite('Snippet Variables Resolver', function () {
|
||||
}
|
||||
};
|
||||
|
||||
const model = TextModel.createFromString([].join('\n'), undefined, undefined, URI.parse('foo:///foo/files/text.txt'));
|
||||
const model = createTextModel([].join('\n'), undefined, undefined, URI.parse('foo:///foo/files/text.txt'));
|
||||
|
||||
const resolver = new CompositeSnippetVariableResolver([new ModelBasedVariableResolver(labelService, model)]);
|
||||
|
||||
@@ -144,19 +145,19 @@ suite('Snippet Variables Resolver', function () {
|
||||
|
||||
resolver = new ModelBasedVariableResolver(
|
||||
labelService,
|
||||
TextModel.createFromString('', undefined, undefined, URI.parse('http://www.pb.o/abc/def/ghi'))
|
||||
createTextModel('', undefined, undefined, URI.parse('http://www.pb.o/abc/def/ghi'))
|
||||
);
|
||||
assertVariableResolve(resolver, 'TM_FILENAME_BASE', 'ghi');
|
||||
|
||||
resolver = new ModelBasedVariableResolver(
|
||||
labelService,
|
||||
TextModel.createFromString('', undefined, undefined, URI.parse('mem:.git'))
|
||||
createTextModel('', undefined, undefined, URI.parse('mem:.git'))
|
||||
);
|
||||
assertVariableResolve(resolver, 'TM_FILENAME_BASE', '.git');
|
||||
|
||||
resolver = new ModelBasedVariableResolver(
|
||||
labelService,
|
||||
TextModel.createFromString('', undefined, undefined, URI.parse('mem:foo.'))
|
||||
createTextModel('', undefined, undefined, URI.parse('mem:foo.'))
|
||||
);
|
||||
assertVariableResolve(resolver, 'TM_FILENAME_BASE', 'foo');
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { provideSuggestionItems, SnippetSortOrder, CompletionOptions } from 'vs/
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
|
||||
suite('Suggest', function () {
|
||||
@@ -19,7 +20,7 @@ suite('Suggest', function () {
|
||||
|
||||
setup(function () {
|
||||
|
||||
model = TextModel.createFromString('FOO\nbar\BAR\nfoo', undefined, undefined, URI.parse('foo:bar/path'));
|
||||
model = createTextModel('FOO\nbar\BAR\nfoo', undefined, undefined, URI.parse('foo:bar/path'));
|
||||
registration = CompletionProviderRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, {
|
||||
provideCompletionItems(_doc, pos) {
|
||||
return {
|
||||
|
||||
@@ -23,6 +23,7 @@ import { CompletionProviderRegistry, CompletionItemKind, CompletionItemInsertTex
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
|
||||
import { IMenuService, IMenu } from 'vs/platform/actions/common/actions';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('SuggestController', function () {
|
||||
|
||||
@@ -57,7 +58,7 @@ suite('SuggestController', function () {
|
||||
}]
|
||||
);
|
||||
|
||||
model = TextModel.createFromString('', undefined, undefined, URI.from({ scheme: 'test-ctrl', path: '/path.tst' }));
|
||||
model = createTextModel('', undefined, undefined, URI.from({ scheme: 'test-ctrl', path: '/path.tst' }));
|
||||
editor = createTestCodeEditor({
|
||||
model,
|
||||
serviceCollection,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { LRUMemory, NoMemory, PrefixMemory, Memory } from 'vs/editor/contrib/suggest/suggestMemory';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { createSuggestItem } from 'vs/editor/contrib/suggest/test/completionModel.test';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { CompletionItem } from 'vs/editor/contrib/suggest/suggest';
|
||||
@@ -19,7 +19,7 @@ suite('SuggestMemories', function () {
|
||||
|
||||
setup(function () {
|
||||
pos = { lineNumber: 1, column: 1 };
|
||||
buffer = TextModel.createFromString('This is some text.\nthis.\nfoo: ,');
|
||||
buffer = createTextModel('This is some text.\nthis.\nfoo: ,');
|
||||
items = [
|
||||
createSuggestItem('foo', 0),
|
||||
createSuggestItem('bar', 0)
|
||||
|
||||
@@ -32,6 +32,7 @@ import { ISuggestMemoryService } from 'vs/editor/contrib/suggest/suggestMemory';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { MockKeybindingService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
export interface Ctor<T> {
|
||||
new(): T;
|
||||
@@ -124,7 +125,7 @@ suite('SuggestModel - Context', function () {
|
||||
});
|
||||
|
||||
test('Context - shouldAutoTrigger', function () {
|
||||
const model = TextModel.createFromString('Das Pferd frisst keinen Gurkensalat - Philipp Reis 1861.\nWer hat\'s erfunden?');
|
||||
const model = createTextModel('Das Pferd frisst keinen Gurkensalat - Philipp Reis 1861.\nWer hat\'s erfunden?');
|
||||
disposables.push(model);
|
||||
|
||||
assertAutoTrigger(model, 3, true, 'end of word, Das|');
|
||||
@@ -138,7 +139,7 @@ suite('SuggestModel - Context', function () {
|
||||
const innerMode = new InnerMode();
|
||||
disposables.push(outerMode, innerMode);
|
||||
|
||||
const model = TextModel.createFromString('a<xx>a<x>', undefined, outerMode.getLanguageIdentifier());
|
||||
const model = createTextModel('a<xx>a<x>', undefined, outerMode.getLanguageIdentifier());
|
||||
disposables.push(model);
|
||||
|
||||
assertAutoTrigger(model, 1, true, 'a|<x — should trigger at end of word');
|
||||
@@ -187,7 +188,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
|
||||
|
||||
setup(function () {
|
||||
disposables = dispose(disposables);
|
||||
model = TextModel.createFromString('abc def', undefined, undefined, URI.parse('test:somefile.ttt'));
|
||||
model = createTextModel('abc def', undefined, undefined, URI.parse('test:somefile.ttt'));
|
||||
disposables.push(model);
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker
|
||||
import { mock } from 'vs/editor/contrib/suggest/test/suggestModel.test';
|
||||
import { EditorWorkerHost, EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
@@ -48,7 +48,7 @@ suite('suggest, word distance', function () {
|
||||
|
||||
disposables.clear();
|
||||
let mode = new BracketMode();
|
||||
let model = TextModel.createFromString('function abc(aa, ab){\na\n}', undefined, mode.getLanguageIdentifier(), URI.parse('test:///some.path'));
|
||||
let model = createTextModel('function abc(aa, ab){\na\n}', undefined, mode.getLanguageIdentifier(), URI.parse('test:///some.path'));
|
||||
let editor = createTestCodeEditor({ model: model });
|
||||
editor.updateOptions({ suggest: { localityBonus: true } });
|
||||
editor.setPosition({ lineNumber: 2, column: 2 });
|
||||
|
||||
@@ -152,7 +152,7 @@ export module StaticServices {
|
||||
|
||||
export const logService = define(ILogService, () => new NullLogService());
|
||||
|
||||
export const undoRedoService = define(IUndoRedoService, () => new UndoRedoService());
|
||||
export const undoRedoService = define(IUndoRedoService, (o) => new UndoRedoService(dialogService.get(o), notificationService.get(o)));
|
||||
|
||||
export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o), logService.get(o), undoRedoService.get(o)));
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
@@ -199,7 +199,7 @@ suite('SideEditing', () => {
|
||||
];
|
||||
|
||||
function _runTest(selection: Selection, editRange: Range, editText: string, editForceMoveMarkers: boolean, expected: Selection, msg: string): void {
|
||||
const model = TextModel.createFromString(LINES.join('\n'));
|
||||
const model = createTextModel(LINES.join('\n'));
|
||||
const config = new TestConfiguration({});
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(config.options);
|
||||
const viewModel = new ViewModel(0, config, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
|
||||
@@ -5551,4 +5551,28 @@ suite('Undo stops', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('can undo typing and EOL change in one undo stop', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
'A line',
|
||||
'Another line',
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
withTestCodeEditor(null, { model: model }, (editor, cursor) => {
|
||||
cursor.setSelections('test', [new Selection(1, 3, 1, 3)]);
|
||||
cursorCommand(cursor, H.Type, { text: 'first' }, 'keyboard');
|
||||
assert.equal(model.getValue(), 'A first line\nAnother line');
|
||||
assertCursor(cursor, new Selection(1, 8, 1, 8));
|
||||
|
||||
model.pushEOL(EndOfLineSequence.CRLF);
|
||||
assert.equal(model.getValue(), 'A first line\r\nAnother line');
|
||||
assertCursor(cursor, new Selection(1, 8, 1, 8));
|
||||
|
||||
CoreEditingCommands.Undo.runEditorCommand(null, editor, null);
|
||||
assert.equal(model.getValue(), 'A line\nAnother line');
|
||||
assertCursor(cursor, new Selection(1, 3, 1, 3));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('Cursor move command test', () => {
|
||||
|
||||
@@ -31,7 +32,7 @@ suite('Cursor move command test', () => {
|
||||
'1'
|
||||
].join('\n');
|
||||
|
||||
thisModel = TextModel.createFromString(text);
|
||||
thisModel = createTextModel(text);
|
||||
thisConfiguration = new TestConfiguration({});
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(thisConfiguration.options);
|
||||
thisViewModel = new ViewModel(0, thisConfiguration, thisModel, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITextAreaWrapper, PagedScreenReaderStrategy, TextAreaState } from 'vs/editor/browser/controller/textAreaState';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
export class MockTextAreaWrapper extends Disposable implements ITextAreaWrapper {
|
||||
|
||||
@@ -506,7 +506,7 @@ suite('TextAreaState', () => {
|
||||
suite('PagedScreenReaderStrategy', () => {
|
||||
|
||||
function testPagedScreenReaderStrategy(lines: string[], selection: Selection, expected: TextAreaState): void {
|
||||
const model = TextModel.createFromString(lines.join('\n'));
|
||||
const model = createTextModel(lines.join('\n'));
|
||||
const actual = PagedScreenReaderStrategy.fromEditorSelection(TextAreaState.EMPTY, model, selection, 10, true);
|
||||
assert.ok(equalsTextAreaState(actual, expected));
|
||||
model.dispose();
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as editorOptions from 'vs/editor/common/config/editorOptions';
|
||||
import { Cursor } from 'vs/editor/common/controller/cursor';
|
||||
import { IConfiguration, IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { TestCodeEditorService, TestCommandService } from 'vs/editor/test/browser/editorTestServices';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
@@ -77,9 +77,9 @@ export function withTestCodeEditor(text: string | string[] | null, options: Test
|
||||
// create a model if necessary and remember it in order to dispose it.
|
||||
if (!options.model) {
|
||||
if (typeof text === 'string') {
|
||||
options.model = TextModel.createFromString(text);
|
||||
options.model = createTextModel(text);
|
||||
} else if (text) {
|
||||
options.model = TextModel.createFromString(text.join('\n'));
|
||||
options.model = createTextModel(text.join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IRange } from 'vs/editor/common/core/range';
|
||||
import { Selection, ISelection } from 'vs/editor/common/core/selection';
|
||||
import { ICommand, Handler, IEditOperationBuilder } from 'vs/editor/common/editorCommon';
|
||||
import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
|
||||
@@ -21,7 +21,7 @@ export function testCommand(
|
||||
expectedSelection: Selection,
|
||||
forceTokenization?: boolean
|
||||
): void {
|
||||
let model = TextModel.createFromString(lines.join('\n'), undefined, languageIdentifier);
|
||||
let model = createTextModel(lines.join('\n'), undefined, languageIdentifier);
|
||||
withTestCodeEditor('', { model: model }, (_editor, cursor) => {
|
||||
if (!cursor) {
|
||||
return;
|
||||
|
||||
@@ -7,9 +7,12 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { DefaultEndOfLine, ITextModelCreationOptions } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
|
||||
export function withEditorModel(text: string[], callback: (model: TextModel) => void): void {
|
||||
let model = TextModel.createFromString(text.join('\n'));
|
||||
let model = createTextModel(text.join('\n'));
|
||||
callback(model);
|
||||
model.dispose();
|
||||
}
|
||||
@@ -36,5 +39,8 @@ export function createTextModel(text: string, _options: IRelaxedTextModelCreatio
|
||||
isForSimpleWidget: (typeof _options.isForSimpleWidget === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.isForSimpleWidget : _options.isForSimpleWidget),
|
||||
largeFileOptimizations: (typeof _options.largeFileOptimizations === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.largeFileOptimizations : _options.largeFileOptimizations),
|
||||
};
|
||||
return TextModel.createFromString(text, options, languageIdentifier, uri);
|
||||
const dialogService = new TestDialogService();
|
||||
const notificationService = new TestNotificationService();
|
||||
const undoRedoService = new UndoRedoService(dialogService, notificationService);
|
||||
return new TextModel(text, options, languageIdentifier, uri, undoRedoService);
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import { MirrorTextModel } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { assertSyncedModels, testApplyEditsWithSyncedModels } from 'vs/editor/test/common/model/editableTextModelTestUtils';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
function createEditableTextModelFromString(text: string): TextModel {
|
||||
return TextModel.createFromString(text, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
return createTextModel(text, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
}
|
||||
|
||||
suite('EditorModel - EditableTextModel.applyEdits updates mightContainRTL', () => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation
|
||||
import { MirrorTextModel } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
export function testApplyEditsWithSyncedModels(original: string[], edits: IIdentifiedSingleEditOperation[], expected: string[], inputEditsAreInvalid: boolean = false): void {
|
||||
let originalStr = original.join('\n');
|
||||
@@ -88,7 +89,7 @@ function assertLineMapping(model: TextModel, msg: string): void {
|
||||
|
||||
|
||||
export function assertSyncedModels(text: string, callback: (model: TextModel, assertMirrorModels: () => void) => void, setup: ((model: TextModel) => void) | null = null): void {
|
||||
let model = TextModel.createFromString(text, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
let model = createTextModel(text, TextModel.DEFAULT_CREATION_OPTIONS, null);
|
||||
model.setEOL(EndOfLineSequence.LF);
|
||||
assertLineMapping(model, 'model');
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { LanguageIdentifier, MetadataConsts } from 'vs/editor/common/modes';
|
||||
import { ViewLineToken, ViewLineTokenFactory } from 'vs/editor/test/common/core/viewLineToken';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
interface ILineEdit {
|
||||
startColumn: number;
|
||||
@@ -106,7 +107,7 @@ suite('ModelLinesTokens', () => {
|
||||
|
||||
function testApplyEdits(initial: IBufferLineState[], edits: IEdit[], expected: IBufferLineState[]): void {
|
||||
const initialText = initial.map(el => el.text).join('\n');
|
||||
const model = TextModel.createFromString(initialText, TextModel.DEFAULT_CREATION_OPTIONS, new LanguageIdentifier('test', 0));
|
||||
const model = createTextModel(initialText, TextModel.DEFAULT_CREATION_OPTIONS, new LanguageIdentifier('test', 0));
|
||||
for (let lineIndex = 0; lineIndex < initial.length; lineIndex++) {
|
||||
const lineTokens = initial[lineIndex].tokens;
|
||||
const lineTextLength = model.getLineMaxColumn(lineIndex + 1) - 1;
|
||||
@@ -442,7 +443,7 @@ suite('ModelLinesTokens', () => {
|
||||
}
|
||||
|
||||
test('insertion on empty line', () => {
|
||||
const model = TextModel.createFromString('some text', TextModel.DEFAULT_CREATION_OPTIONS, new LanguageIdentifier('test', 0));
|
||||
const model = createTextModel('some text', TextModel.DEFAULT_CREATION_OPTIONS, new LanguageIdentifier('test', 0));
|
||||
const tokens = TestToken.toTokens([new TestToken(0, 1)]);
|
||||
LineTokens.convertToEndOffset(tokens, model.getLineMaxColumn(1) - 1);
|
||||
model.setLineTokens(1, tokens);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TokenizationResult2 } from 'vs/editor/common/core/token';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { NULL_STATE } from 'vs/editor/common/modes/nullMode';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
// --------- utils
|
||||
|
||||
@@ -46,7 +47,7 @@ suite('Editor Model - Model Modes 1', () => {
|
||||
const LANGUAGE_ID = 'modelModeTest1';
|
||||
calledFor = [];
|
||||
languageRegistration = modes.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
|
||||
thisModel = TextModel.createFromString(TEXT, undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
thisModel = createTextModel(TEXT, undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -199,7 +200,7 @@ suite('Editor Model - Model Modes 2', () => {
|
||||
'Line5';
|
||||
const LANGUAGE_ID = 'modelModeTest2';
|
||||
languageRegistration = modes.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
|
||||
thisModel = TextModel.createFromString(TEXT, undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
thisModel = createTextModel(TEXT, undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { IState, LanguageIdentifier, MetadataConsts, TokenizationRegistry } from
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { NULL_STATE } from 'vs/editor/common/modes/nullMode';
|
||||
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
// --------- utils
|
||||
|
||||
@@ -35,7 +36,7 @@ suite('Editor Model - Model', () => {
|
||||
LINE3 + '\n' +
|
||||
LINE4 + '\r\n' +
|
||||
LINE5;
|
||||
thisModel = TextModel.createFromString(text);
|
||||
thisModel = createTextModel(text);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -349,7 +350,7 @@ suite('Editor Model - Model Line Separators', () => {
|
||||
LINE3 + '\u2028' +
|
||||
LINE4 + '\r\n' +
|
||||
LINE5;
|
||||
thisModel = TextModel.createFromString(text);
|
||||
thisModel = createTextModel(text);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -365,7 +366,7 @@ suite('Editor Model - Model Line Separators', () => {
|
||||
});
|
||||
|
||||
test('Bug 13333:Model should line break on lonely CR too', () => {
|
||||
let model = TextModel.createFromString('Hello\rWorld!\r\nAnother line');
|
||||
let model = createTextModel('Hello\rWorld!\r\nAnother line');
|
||||
assert.equal(model.getLineCount(), 3);
|
||||
assert.equal(model.getValue(), 'Hello\r\nWorld!\r\nAnother line');
|
||||
model.dispose();
|
||||
@@ -430,7 +431,7 @@ suite('Editor Model - Words', () => {
|
||||
|
||||
test('Get word at position', () => {
|
||||
const text = ['This text has some words. '];
|
||||
const thisModel = TextModel.createFromString(text.join('\n'));
|
||||
const thisModel = createTextModel(text.join('\n'));
|
||||
disposables.push(thisModel);
|
||||
|
||||
assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: 'This', startColumn: 1, endColumn: 5 });
|
||||
@@ -451,7 +452,7 @@ suite('Editor Model - Words', () => {
|
||||
const innerMode = new InnerMode();
|
||||
disposables.push(outerMode, innerMode);
|
||||
|
||||
const model = TextModel.createFromString('ab<xx>ab<x>', undefined, outerMode.getLanguageIdentifier());
|
||||
const model = createTextModel('ab<xx>ab<x>', undefined, outerMode.getLanguageIdentifier());
|
||||
disposables.push(model);
|
||||
|
||||
assert.deepEqual(model.getWordAtPosition(new Position(1, 1)), { word: 'ab', startColumn: 1, endColumn: 3 });
|
||||
@@ -476,7 +477,7 @@ suite('Editor Model - Words', () => {
|
||||
};
|
||||
disposables.push(mode);
|
||||
|
||||
const thisModel = TextModel.createFromString('.🐷-a-b', undefined, MODE_ID);
|
||||
const thisModel = createTextModel('.🐷-a-b', undefined, MODE_ID);
|
||||
disposables.push(thisModel);
|
||||
|
||||
assert.deepEqual(thisModel.getWordAtPosition(new Position(1, 1)), { word: '.', startColumn: 1, endColumn: 2 });
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { EndOfLineSequence, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
// --------- utils
|
||||
|
||||
@@ -92,7 +93,7 @@ suite('Editor Model - Model Decorations', () => {
|
||||
LINE3 + '\n' +
|
||||
LINE4 + '\r\n' +
|
||||
LINE5;
|
||||
thisModel = TextModel.createFromString(text);
|
||||
thisModel = createTextModel(text);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -400,7 +401,7 @@ suite('Editor Model - Model Decorations', () => {
|
||||
});
|
||||
|
||||
test('removeAllDecorationsWithOwnerId can be called after model dispose', () => {
|
||||
let model = TextModel.createFromString('asd');
|
||||
let model = createTextModel('asd');
|
||||
model.dispose();
|
||||
model.removeAllDecorationsWithOwnerId(1);
|
||||
});
|
||||
@@ -415,7 +416,7 @@ suite('Editor Model - Model Decorations', () => {
|
||||
suite('Decorations and editing', () => {
|
||||
|
||||
function _runTest(decRange: Range, stickiness: TrackedRangeStickiness, editRange: Range, editText: string, editForceMoveMarkers: boolean, expectedDecRange: Range, msg: string): void {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'My First Line',
|
||||
'My Second Line',
|
||||
'Third Line'
|
||||
@@ -1148,7 +1149,7 @@ suite('deltaDecorations', () => {
|
||||
|
||||
function testDeltaDecorations(text: string[], decorations: ILightWeightDecoration[], newDecorations: ILightWeightDecoration[]): void {
|
||||
|
||||
let model = TextModel.createFromString(text.join('\n'));
|
||||
let model = createTextModel(text.join('\n'));
|
||||
|
||||
// Add initial decorations & assert they are added
|
||||
let initialIds = model.deltaDecorations([], decorations.map(toModelDeltaDecoration));
|
||||
@@ -1177,7 +1178,7 @@ suite('deltaDecorations', () => {
|
||||
}
|
||||
|
||||
test('result respects input', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'Hello world,',
|
||||
'How are you?'
|
||||
].join('\n'));
|
||||
@@ -1265,7 +1266,7 @@ suite('deltaDecorations', () => {
|
||||
|
||||
test('issue #4317: editor.setDecorations doesn\'t update the hover message', () => {
|
||||
|
||||
let model = TextModel.createFromString('Hello world!');
|
||||
let model = createTextModel('Hello world!');
|
||||
|
||||
let ids = model.deltaDecorations([], [{
|
||||
range: {
|
||||
@@ -1299,7 +1300,7 @@ suite('deltaDecorations', () => {
|
||||
});
|
||||
|
||||
test('model doesn\'t get confused with individual tracked ranges', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'Hello world,',
|
||||
'How are you?'
|
||||
].join('\n'));
|
||||
@@ -1340,7 +1341,7 @@ suite('deltaDecorations', () => {
|
||||
});
|
||||
|
||||
test('issue #16922: Clicking on link doesn\'t seem to do anything', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'Hello world,',
|
||||
'How are you?',
|
||||
'Fine.',
|
||||
@@ -1371,7 +1372,7 @@ suite('deltaDecorations', () => {
|
||||
|
||||
test('issue #41492: URL highlighting persists after pasting over url', () => {
|
||||
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'My First Line'
|
||||
].join('\n'));
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as assert from 'assert';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('Editor Model - Model Edit Operation', () => {
|
||||
const LINE1 = 'My First Line';
|
||||
@@ -23,7 +24,7 @@ suite('Editor Model - Model Edit Operation', () => {
|
||||
LINE3 + '\n' +
|
||||
LINE4 + '\r\n' +
|
||||
LINE5;
|
||||
model = TextModel.createFromString(text);
|
||||
model = createTextModel(text);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { PieceTreeBase } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceT
|
||||
import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer';
|
||||
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
|
||||
import { NodeColor, SENTINEL, TreeNode } from 'vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
import { SearchData } from 'vs/editor/common/model/textModelSearch';
|
||||
|
||||
const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n';
|
||||
@@ -1761,7 +1761,7 @@ function getValueInSnapshot(snapshot: ITextSnapshot) {
|
||||
}
|
||||
suite('snapshot', () => {
|
||||
test('bug #45564, piece tree pieces should be immutable', () => {
|
||||
const model = TextModel.createFromString('\n');
|
||||
const model = createTextModel('\n');
|
||||
model.applyEdits([
|
||||
{
|
||||
range: new Range(2, 1, 2, 1),
|
||||
@@ -1789,7 +1789,7 @@ suite('snapshot', () => {
|
||||
});
|
||||
|
||||
test('immutable snapshot 1', () => {
|
||||
const model = TextModel.createFromString('abc\ndef');
|
||||
const model = createTextModel('abc\ndef');
|
||||
const snapshot = model.createSnapshot();
|
||||
model.applyEdits([
|
||||
{
|
||||
@@ -1809,7 +1809,7 @@ suite('snapshot', () => {
|
||||
});
|
||||
|
||||
test('immutable snapshot 2', () => {
|
||||
const model = TextModel.createFromString('abc\ndef');
|
||||
const model = createTextModel('abc\ndef');
|
||||
const snapshot = model.createSnapshot();
|
||||
model.applyEdits([
|
||||
{
|
||||
@@ -1829,7 +1829,7 @@ suite('snapshot', () => {
|
||||
});
|
||||
|
||||
test('immutable snapshot 3', () => {
|
||||
const model = TextModel.createFromString('abc\ndef');
|
||||
const model = createTextModel('abc\ndef');
|
||||
model.applyEdits([
|
||||
{
|
||||
range: new Range(2, 4, 2, 4),
|
||||
@@ -1896,4 +1896,4 @@ suite('chunk based search', () => {
|
||||
assert.equal(ret.length, 1);
|
||||
assert.deepEqual(ret[0].range, new Range(2, 2, 2, 3));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -163,7 +163,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('getValueLengthInRange', () => {
|
||||
|
||||
let m = TextModel.createFromString('My First Line\r\nMy Second Line\r\nMy Third Line');
|
||||
let m = createTextModel('My First Line\r\nMy Second Line\r\nMy Third Line');
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length);
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length);
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length);
|
||||
@@ -176,7 +176,7 @@ suite('Editor Model - TextModel', () => {
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 2, 3, 1000)), 'y First Line\r\nMy Second Line\r\nMy Third Line'.length);
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 1, 1000, 1000)), 'My First Line\r\nMy Second Line\r\nMy Third Line'.length);
|
||||
|
||||
m = TextModel.createFromString('My First Line\nMy Second Line\nMy Third Line');
|
||||
m = createTextModel('My First Line\nMy Second Line\nMy Third Line');
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 1)), ''.length);
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 1, 1, 2)), 'M'.length);
|
||||
assert.equal(m.getValueLengthInRange(new Range(1, 2, 1, 3)), 'y'.length);
|
||||
@@ -662,7 +662,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validatePosition', () => {
|
||||
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
let m = createTextModel('line one\nline two');
|
||||
|
||||
assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1));
|
||||
assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1));
|
||||
@@ -691,7 +691,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validatePosition around high-low surrogate pairs 1', () => {
|
||||
|
||||
let m = TextModel.createFromString('a📚b');
|
||||
let m = createTextModel('a📚b');
|
||||
|
||||
assert.deepEqual(m.validatePosition(new Position(0, 0)), new Position(1, 1));
|
||||
assert.deepEqual(m.validatePosition(new Position(0, 1)), new Position(1, 1));
|
||||
@@ -718,7 +718,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validatePosition around high-low surrogate pairs 2', () => {
|
||||
|
||||
let m = TextModel.createFromString('a📚📚b');
|
||||
let m = createTextModel('a📚📚b');
|
||||
|
||||
assert.deepEqual(m.validatePosition(new Position(1, 1)), new Position(1, 1));
|
||||
assert.deepEqual(m.validatePosition(new Position(1, 2)), new Position(1, 2));
|
||||
@@ -732,7 +732,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validatePosition handle NaN.', () => {
|
||||
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
let m = createTextModel('line one\nline two');
|
||||
|
||||
assert.deepEqual(m.validatePosition(new Position(NaN, 1)), new Position(1, 1));
|
||||
assert.deepEqual(m.validatePosition(new Position(1, NaN)), new Position(1, 1));
|
||||
@@ -743,7 +743,7 @@ suite('Editor Model - TextModel', () => {
|
||||
});
|
||||
|
||||
test('issue #71480: validatePosition handle floats', () => {
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
let m = createTextModel('line one\nline two');
|
||||
|
||||
assert.deepEqual(m.validatePosition(new Position(0.2, 1)), new Position(1, 1), 'a');
|
||||
assert.deepEqual(m.validatePosition(new Position(1.2, 1)), new Position(1, 1), 'b');
|
||||
@@ -756,7 +756,7 @@ suite('Editor Model - TextModel', () => {
|
||||
});
|
||||
|
||||
test('issue #71480: validateRange handle floats', () => {
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
let m = createTextModel('line one\nline two');
|
||||
|
||||
assert.deepEqual(m.validateRange(new Range(0.2, 1.5, 0.8, 2.5)), new Range(1, 1, 1, 1));
|
||||
assert.deepEqual(m.validateRange(new Range(1.2, 1.7, 1.8, 2.2)), new Range(1, 1, 1, 2));
|
||||
@@ -764,7 +764,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validateRange around high-low surrogate pairs 1', () => {
|
||||
|
||||
let m = TextModel.createFromString('a📚b');
|
||||
let m = createTextModel('a📚b');
|
||||
|
||||
assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1));
|
||||
assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1));
|
||||
@@ -792,7 +792,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('validateRange around high-low surrogate pairs 2', () => {
|
||||
|
||||
let m = TextModel.createFromString('a📚📚b');
|
||||
let m = createTextModel('a📚📚b');
|
||||
|
||||
assert.deepEqual(m.validateRange(new Range(0, 0, 0, 1)), new Range(1, 1, 1, 1));
|
||||
assert.deepEqual(m.validateRange(new Range(0, 0, 0, 7)), new Range(1, 1, 1, 1));
|
||||
@@ -835,7 +835,7 @@ suite('Editor Model - TextModel', () => {
|
||||
|
||||
test('modifyPosition', () => {
|
||||
|
||||
let m = TextModel.createFromString('line one\nline two');
|
||||
let m = createTextModel('line one\nline two');
|
||||
assert.deepEqual(m.modifyPosition(new Position(1, 1), 0), new Position(1, 1));
|
||||
assert.deepEqual(m.modifyPosition(new Position(0, 0), 0), new Position(1, 1));
|
||||
assert.deepEqual(m.modifyPosition(new Position(30, 1), 0), new Position(2, 9));
|
||||
@@ -913,7 +913,7 @@ suite('Editor Model - TextModel', () => {
|
||||
});
|
||||
|
||||
test('getLineFirstNonWhitespaceColumn', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'asd',
|
||||
' asd',
|
||||
'\tasd',
|
||||
@@ -943,7 +943,7 @@ suite('Editor Model - TextModel', () => {
|
||||
});
|
||||
|
||||
test('getLineLastNonWhitespaceColumn', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'asd',
|
||||
'asd ',
|
||||
'asd\t',
|
||||
@@ -973,7 +973,7 @@ suite('Editor Model - TextModel', () => {
|
||||
});
|
||||
|
||||
test('#50471. getValueInRange with invalid range', () => {
|
||||
let m = TextModel.createFromString('My First Line\r\nMy Second Line\r\nMy Third Line');
|
||||
let m = createTextModel('My First Line\r\nMy Second Line\r\nMy Third Line');
|
||||
assert.equal(m.getValueInRange(new Range(1, NaN, 1, 3)), 'My');
|
||||
assert.equal(m.getValueInRange(new Range(NaN, NaN, NaN, NaN)), '');
|
||||
});
|
||||
@@ -982,24 +982,24 @@ suite('Editor Model - TextModel', () => {
|
||||
suite('TextModel.mightContainRTL', () => {
|
||||
|
||||
test('nope', () => {
|
||||
let model = TextModel.createFromString('hello world!');
|
||||
let model = createTextModel('hello world!');
|
||||
assert.equal(model.mightContainRTL(), false);
|
||||
});
|
||||
|
||||
test('yes', () => {
|
||||
let model = TextModel.createFromString('Hello,\nזוהי עובדה מבוססת שדעתו');
|
||||
let model = createTextModel('Hello,\nזוהי עובדה מבוססת שדעתו');
|
||||
assert.equal(model.mightContainRTL(), true);
|
||||
});
|
||||
|
||||
test('setValue resets 1', () => {
|
||||
let model = TextModel.createFromString('hello world!');
|
||||
let model = createTextModel('hello world!');
|
||||
assert.equal(model.mightContainRTL(), false);
|
||||
model.setValue('Hello,\nזוהי עובדה מבוססת שדעתו');
|
||||
assert.equal(model.mightContainRTL(), true);
|
||||
});
|
||||
|
||||
test('setValue resets 2', () => {
|
||||
let model = TextModel.createFromString('Hello,\nهناك حقيقة مثبتة منذ زمن طويل');
|
||||
let model = createTextModel('Hello,\nهناك حقيقة مثبتة منذ زمن طويل');
|
||||
assert.equal(model.mightContainRTL(), true);
|
||||
model.setValue('hello world!');
|
||||
assert.equal(model.mightContainRTL(), false);
|
||||
@@ -1010,14 +1010,14 @@ suite('TextModel.mightContainRTL', () => {
|
||||
suite('TextModel.createSnapshot', () => {
|
||||
|
||||
test('empty file', () => {
|
||||
let model = TextModel.createFromString('');
|
||||
let model = createTextModel('');
|
||||
let snapshot = model.createSnapshot();
|
||||
assert.equal(snapshot.read(), null);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('file with BOM', () => {
|
||||
let model = TextModel.createFromString(UTF8_BOM_CHARACTER + 'Hello');
|
||||
let model = createTextModel(UTF8_BOM_CHARACTER + 'Hello');
|
||||
assert.equal(model.getLineContent(1), 'Hello');
|
||||
let snapshot = model.createSnapshot(true);
|
||||
assert.equal(snapshot.read(), UTF8_BOM_CHARACTER + 'Hello');
|
||||
@@ -1026,7 +1026,7 @@ suite('TextModel.createSnapshot', () => {
|
||||
});
|
||||
|
||||
test('regular file', () => {
|
||||
let model = TextModel.createFromString('My First Line\n\t\tMy Second Line\n Third Line\n\n1');
|
||||
let model = createTextModel('My First Line\n\t\tMy Second Line\n Third Line\n\n1');
|
||||
let snapshot = model.createSnapshot();
|
||||
assert.equal(snapshot.read(), 'My First Line\n\t\tMy Second Line\n Third Line\n\n1');
|
||||
assert.equal(snapshot.read(), null);
|
||||
@@ -1040,7 +1040,7 @@ suite('TextModel.createSnapshot', () => {
|
||||
}
|
||||
const text = lines.join('\n');
|
||||
|
||||
let model = TextModel.createFromString(text);
|
||||
let model = createTextModel(text);
|
||||
let snapshot = model.createSnapshot();
|
||||
let actual = '';
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { EndOfLineSequence, FindMatch } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { SearchData, SearchParams, TextModelSearch, isMultilineRegexSource } from 'vs/editor/common/model/textModelSearch';
|
||||
import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
// --------- Find
|
||||
suite('TextModelSearch', () => {
|
||||
@@ -51,12 +52,12 @@ suite('TextModelSearch', () => {
|
||||
let expectedMatches = expectedRanges.map(entry => new FindMatch(entry, null));
|
||||
let searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
|
||||
|
||||
let model = TextModel.createFromString(text);
|
||||
let model = createTextModel(text);
|
||||
_assertFindMatches(model, searchParams, expectedMatches);
|
||||
model.dispose();
|
||||
|
||||
|
||||
let model2 = TextModel.createFromString(text);
|
||||
let model2 = createTextModel(text);
|
||||
model2.setEOL(EndOfLineSequence.CRLF);
|
||||
_assertFindMatches(model2, searchParams, expectedMatches);
|
||||
model2.dispose();
|
||||
@@ -380,7 +381,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch without regex', () => {
|
||||
let model = TextModel.createFromString('line line one\nline two\nthree');
|
||||
let model = createTextModel('line line one\nline two\nthree');
|
||||
|
||||
let searchParams = new SearchParams('line', false, false, null);
|
||||
|
||||
@@ -403,7 +404,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex', () => {
|
||||
let model = TextModel.createFromString('line one\nline two\nthree');
|
||||
let model = createTextModel('line one\nline two\nthree');
|
||||
|
||||
let searchParams = new SearchParams('^line', true, false, null);
|
||||
|
||||
@@ -423,7 +424,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex and line has repetitive beginnings', () => {
|
||||
let model = TextModel.createFromString('line line one\nline two\nthree');
|
||||
let model = createTextModel('line line one\nline two\nthree');
|
||||
|
||||
let searchParams = new SearchParams('^line', true, false, null);
|
||||
|
||||
@@ -443,7 +444,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary multiline regex and line has repetitive beginnings', () => {
|
||||
let model = TextModel.createFromString('line line one\nline two\nline three\nline four');
|
||||
let model = createTextModel('line line one\nline two\nline three\nline four');
|
||||
|
||||
let searchParams = new SearchParams('^line.*\\nline', true, false, null);
|
||||
|
||||
@@ -460,7 +461,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch with ending boundary regex', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('line$', true, false, null);
|
||||
|
||||
@@ -480,7 +481,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findMatches with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)', true, false, null);
|
||||
|
||||
@@ -495,7 +496,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findMatches multiline with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)\\n', true, false, null);
|
||||
|
||||
@@ -509,7 +510,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)', true, false, null);
|
||||
|
||||
@@ -520,7 +521,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findNextMatch multiline with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)\\n', true, false, null);
|
||||
|
||||
@@ -531,7 +532,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findPreviousMatch with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)', true, false, null);
|
||||
|
||||
@@ -542,7 +543,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('findPreviousMatch multiline with capturing matches', () => {
|
||||
let model = TextModel.createFromString('one line line\ntwo line\nthree');
|
||||
let model = createTextModel('one line line\ntwo line\nthree');
|
||||
|
||||
let searchParams = new SearchParams('(l(in)e)\\n', true, false, null);
|
||||
|
||||
@@ -553,7 +554,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('\\n matches \\r\\n', () => {
|
||||
let model = TextModel.createFromString('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni');
|
||||
let model = createTextModel('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni');
|
||||
|
||||
assert.equal(model.getEOL(), '\r\n');
|
||||
|
||||
@@ -576,7 +577,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('\\r can never be found', () => {
|
||||
let model = TextModel.createFromString('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni');
|
||||
let model = createTextModel('a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni');
|
||||
|
||||
assert.equal(model.getEOL(), '\r\n');
|
||||
|
||||
@@ -763,7 +764,7 @@ suite('TextModelSearch', () => {
|
||||
});
|
||||
|
||||
test('issue #74715. \\d* finds empty string and stops searching.', () => {
|
||||
let model = TextModel.createFromString('10.243.30.10');
|
||||
let model = createTextModel('10.243.30.10');
|
||||
|
||||
let searchParams = new SearchParams('\\d*', true, false, null);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { CharacterPair } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { NULL_STATE } from 'vs/editor/common/modes/nullMode';
|
||||
import { ViewLineToken } from 'vs/editor/test/common/core/viewLineToken';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('TextModelWithTokens', () => {
|
||||
|
||||
@@ -72,7 +73,7 @@ suite('TextModelWithTokens', () => {
|
||||
brackets: brackets
|
||||
});
|
||||
|
||||
let model = TextModel.createFromString(
|
||||
let model = createTextModel(
|
||||
contents.join('\n'),
|
||||
TextModel.DEFAULT_CREATION_OPTIONS,
|
||||
languageIdentifier
|
||||
@@ -178,7 +179,7 @@ suite('TextModelWithTokens - bracket matching', () => {
|
||||
let text =
|
||||
')]}{[(' + '\n' +
|
||||
')]}{[(';
|
||||
let model = TextModel.createFromString(text, undefined, languageIdentifier);
|
||||
let model = createTextModel(text, undefined, languageIdentifier);
|
||||
|
||||
assertIsNotBracket(model, 1, 1);
|
||||
assertIsNotBracket(model, 1, 2);
|
||||
@@ -206,7 +207,7 @@ suite('TextModelWithTokens - bracket matching', () => {
|
||||
'}, bar: {hallo: [{' + '\n' +
|
||||
'}, {' + '\n' +
|
||||
'}]}}';
|
||||
let model = TextModel.createFromString(text, undefined, languageIdentifier);
|
||||
let model = createTextModel(text, undefined, languageIdentifier);
|
||||
|
||||
let brackets: [Position, Range, Range][] = [
|
||||
[new Position(1, 11), new Range(1, 11, 1, 12), new Range(5, 4, 5, 5)],
|
||||
@@ -284,7 +285,7 @@ suite('TextModelWithTokens', () => {
|
||||
'end;',
|
||||
].join('\n');
|
||||
|
||||
const model = TextModel.createFromString(text, undefined, languageIdentifier);
|
||||
const model = createTextModel(text, undefined, languageIdentifier);
|
||||
|
||||
// <if> ... <end ifa> is not matched
|
||||
assertIsNotBracket(model, 10, 9);
|
||||
@@ -322,7 +323,7 @@ suite('TextModelWithTokens', () => {
|
||||
'endrecord',
|
||||
].join('\n');
|
||||
|
||||
const model = TextModel.createFromString(text, undefined, languageIdentifier);
|
||||
const model = createTextModel(text, undefined, languageIdentifier);
|
||||
|
||||
// <recordbegin> ... <endrecord> is matched
|
||||
assertIsBracket(model, new Position(1, 1), [new Range(1, 1, 1, 12), new Range(4, 1, 4, 10)]);
|
||||
@@ -388,7 +389,7 @@ suite('TextModelWithTokens', () => {
|
||||
],
|
||||
});
|
||||
|
||||
const model = TextModel.createFromString([
|
||||
const model = createTextModel([
|
||||
'function hello() {',
|
||||
' console.log(`${100}`);',
|
||||
'}'
|
||||
@@ -459,7 +460,7 @@ suite('TextModelWithTokens regression tests', () => {
|
||||
let registration1 = TokenizationRegistry.register(LANG_ID1, tokenizationSupport);
|
||||
let registration2 = TokenizationRegistry.register(LANG_ID2, tokenizationSupport);
|
||||
|
||||
let model = TextModel.createFromString('A model with\ntwo lines');
|
||||
let model = createTextModel('A model with\ntwo lines');
|
||||
|
||||
assertViewLineTokens(model, 1, true, [createViewLineToken(12, 1)]);
|
||||
assertViewLineTokens(model, 2, true, [createViewLineToken(9, 1)]);
|
||||
@@ -498,7 +499,7 @@ suite('TextModelWithTokens regression tests', () => {
|
||||
]
|
||||
});
|
||||
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'Imports System',
|
||||
'Imports System.Collections.Generic',
|
||||
'',
|
||||
@@ -528,7 +529,7 @@ suite('TextModelWithTokens regression tests', () => {
|
||||
]
|
||||
});
|
||||
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'sequence "outer"',
|
||||
' sequence "inner"',
|
||||
' endsequence',
|
||||
@@ -561,7 +562,7 @@ suite('TextModelWithTokens regression tests', () => {
|
||||
|
||||
let registration = TokenizationRegistry.register(outerMode.language, tokenizationSupport);
|
||||
|
||||
let model = TextModel.createFromString('A model with one line', undefined, outerMode);
|
||||
let model = createTextModel('A model with one line', undefined, outerMode);
|
||||
|
||||
model.forceTokenization(1);
|
||||
assert.equal(model.getLanguageIdAtPosition(1, 1), innerMode.id);
|
||||
@@ -574,7 +575,7 @@ suite('TextModelWithTokens regression tests', () => {
|
||||
suite('TextModel.getLineIndentGuide', () => {
|
||||
function assertIndentGuides(lines: [number, number, number, number, string][], tabSize: number): void {
|
||||
let text = lines.map(l => l[4]).join('\n');
|
||||
let model = TextModel.createFromString(text);
|
||||
let model = createTextModel(text);
|
||||
model.updateOptions({ tabSize: tabSize });
|
||||
|
||||
let actualIndents = model.getLinesIndentGuides(1, model.getLineCount());
|
||||
@@ -747,7 +748,7 @@ suite('TextModel.getLineIndentGuide', () => {
|
||||
});
|
||||
|
||||
test('issue #49173', () => {
|
||||
let model = TextModel.createFromString([
|
||||
let model = createTextModel([
|
||||
'class A {',
|
||||
' public m1(): void {',
|
||||
' }',
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { MetadataConsts, TokenMetadata } from 'vs/editor/common/modes';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('TokensStore', () => {
|
||||
|
||||
@@ -96,7 +97,7 @@ suite('TokensStore', () => {
|
||||
|
||||
function testTokensAdjustment(rawInitialState: string[], edits: IIdentifiedSingleEditOperation[], rawFinalState: string[]) {
|
||||
const initialState = parseTokensState(rawInitialState);
|
||||
const model = TextModel.createFromString(initialState.text);
|
||||
const model = createTextModel(initialState.text);
|
||||
model.setSemanticTokens([initialState.tokens]);
|
||||
|
||||
model.applyEdits(edits);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { createStringBuilder } from 'vs/editor/common/core/stringBuilder';
|
||||
import { DefaultEndOfLine } from 'vs/editor/common/model';
|
||||
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
|
||||
import { createTextBuffer } from 'vs/editor/common/model/textModel';
|
||||
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -19,6 +19,9 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
const GENERATE_TESTS = false;
|
||||
|
||||
@@ -30,7 +33,7 @@ suite('ModelService', () => {
|
||||
configService.setUserConfiguration('files', { 'eol': '\n' });
|
||||
configService.setUserConfiguration('files', { 'eol': '\r\n' }, URI.file(platform.isWindows ? 'c:\\myroot' : '/myroot'));
|
||||
|
||||
modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), new UndoRedoService());
|
||||
modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), new UndoRedoService(new TestDialogService(), new TestNotificationService()));
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
@@ -49,7 +52,7 @@ suite('ModelService', () => {
|
||||
|
||||
test('_computeEdits no change', function () {
|
||||
|
||||
const model = TextModel.createFromString(
|
||||
const model = createTextModel(
|
||||
[
|
||||
'This is line one', //16
|
||||
'and this is line number two', //27
|
||||
@@ -75,7 +78,7 @@ suite('ModelService', () => {
|
||||
|
||||
test('_computeEdits first line changed', function () {
|
||||
|
||||
const model = TextModel.createFromString(
|
||||
const model = createTextModel(
|
||||
[
|
||||
'This is line one', //16
|
||||
'and this is line number two', //27
|
||||
@@ -103,7 +106,7 @@ suite('ModelService', () => {
|
||||
|
||||
test('_computeEdits EOL changed', function () {
|
||||
|
||||
const model = TextModel.createFromString(
|
||||
const model = createTextModel(
|
||||
[
|
||||
'This is line one', //16
|
||||
'and this is line number two', //27
|
||||
@@ -129,7 +132,7 @@ suite('ModelService', () => {
|
||||
|
||||
test('_computeEdits EOL and other change 1', function () {
|
||||
|
||||
const model = TextModel.createFromString(
|
||||
const model = createTextModel(
|
||||
[
|
||||
'This is line one', //16
|
||||
'and this is line number two', //27
|
||||
@@ -165,7 +168,7 @@ suite('ModelService', () => {
|
||||
|
||||
test('_computeEdits EOL and other change 2', function () {
|
||||
|
||||
const model = TextModel.createFromString(
|
||||
const model = createTextModel(
|
||||
[
|
||||
'package main', // 1
|
||||
'func foo() {', // 2
|
||||
@@ -307,7 +310,7 @@ suite('ModelService', () => {
|
||||
});
|
||||
|
||||
function assertComputeEdits(lines1: string[], lines2: string[]): void {
|
||||
const model = TextModel.createFromString(lines1.join('\n'));
|
||||
const model = createTextModel(lines1.join('\n'));
|
||||
const textBuffer = createTextBuffer(lines2.join('\n'), DefaultEndOfLine.LF);
|
||||
|
||||
// compute required edits
|
||||
|
||||
@@ -18,6 +18,7 @@ import { LineBreakData, ISimpleModel, SplitLine, SplitLinesCollection } from 'vs
|
||||
import { ViewLineData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
test('SplitLine', () => {
|
||||
@@ -96,7 +97,7 @@ suite('Editor ViewModel - SplitLinesCollection', () => {
|
||||
|
||||
const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);
|
||||
|
||||
const model = TextModel.createFromString([
|
||||
const model = createTextModel([
|
||||
'int main() {',
|
||||
'\tprintf("Hello world!");',
|
||||
'}',
|
||||
@@ -347,7 +348,7 @@ suite('SplitLinesCollection', () => {
|
||||
};
|
||||
const LANGUAGE_ID = 'modelModeTest1';
|
||||
languageRegistration = modes.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);
|
||||
model = TextModel.createFromString(_text.join('\n'), undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
model = createTextModel(_text.join('\n'), undefined, new modes.LanguageIdentifier(LANGUAGE_ID, 0));
|
||||
// force tokenization
|
||||
model.forceTokenization(model.getLineCount());
|
||||
});
|
||||
|
||||
@@ -8,12 +8,13 @@ import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { TestConfiguration } from 'vs/editor/test/common/mocks/testConfiguration';
|
||||
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
|
||||
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
|
||||
|
||||
export function testViewModel(text: string[], options: IEditorOptions, callback: (viewModel: ViewModel, model: TextModel) => void): void {
|
||||
const EDITOR_ID = 1;
|
||||
|
||||
const configuration = new TestConfiguration(options);
|
||||
const model = TextModel.createFromString(text.join('\n'));
|
||||
const model = createTextModel(text.join('\n'));
|
||||
const monospaceLineBreaksComputerFactory = MonospaceLineBreaksComputerFactory.create(configuration.options);
|
||||
const viewModel = new ViewModel(EDITOR_ID, configuration, model, monospaceLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, null!);
|
||||
|
||||
|
||||
Vendored
+107
-100
@@ -1884,7 +1884,7 @@ declare namespace monaco.editor {
|
||||
* @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed.
|
||||
* @return The cursor state returned by the `cursorStateComputer`.
|
||||
*/
|
||||
pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;
|
||||
pushEditOperations(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null;
|
||||
/**
|
||||
* Change the end of line sequence. This is the preferred way of
|
||||
* changing the eol sequence. This will land on the undo stack.
|
||||
@@ -2849,6 +2849,11 @@ declare namespace monaco.editor {
|
||||
* Defaults to true.
|
||||
*/
|
||||
scrollPredominantAxis?: boolean;
|
||||
/**
|
||||
* Enable that the selection with the mouse and keys is doing column selection.
|
||||
* Defaults to false.
|
||||
*/
|
||||
columnSelection?: boolean;
|
||||
/**
|
||||
* The modifier to be used to add multiple cursors with the mouse.
|
||||
* Defaults to 'alt'
|
||||
@@ -3798,105 +3803,106 @@ declare namespace monaco.editor {
|
||||
autoSurround = 10,
|
||||
codeLens = 11,
|
||||
colorDecorators = 12,
|
||||
comments = 13,
|
||||
contextmenu = 14,
|
||||
copyWithSyntaxHighlighting = 15,
|
||||
cursorBlinking = 16,
|
||||
cursorSmoothCaretAnimation = 17,
|
||||
cursorStyle = 18,
|
||||
cursorSurroundingLines = 19,
|
||||
cursorSurroundingLinesStyle = 20,
|
||||
cursorWidth = 21,
|
||||
disableLayerHinting = 22,
|
||||
disableMonospaceOptimizations = 23,
|
||||
dragAndDrop = 24,
|
||||
emptySelectionClipboard = 25,
|
||||
extraEditorClassName = 26,
|
||||
fastScrollSensitivity = 27,
|
||||
find = 28,
|
||||
fixedOverflowWidgets = 29,
|
||||
folding = 30,
|
||||
foldingStrategy = 31,
|
||||
foldingHighlight = 32,
|
||||
fontFamily = 33,
|
||||
fontInfo = 34,
|
||||
fontLigatures = 35,
|
||||
fontSize = 36,
|
||||
fontWeight = 37,
|
||||
formatOnPaste = 38,
|
||||
formatOnType = 39,
|
||||
glyphMargin = 40,
|
||||
gotoLocation = 41,
|
||||
hideCursorInOverviewRuler = 42,
|
||||
highlightActiveIndentGuide = 43,
|
||||
hover = 44,
|
||||
inDiffEditor = 45,
|
||||
letterSpacing = 46,
|
||||
lightbulb = 47,
|
||||
lineDecorationsWidth = 48,
|
||||
lineHeight = 49,
|
||||
lineNumbers = 50,
|
||||
lineNumbersMinChars = 51,
|
||||
links = 52,
|
||||
matchBrackets = 53,
|
||||
minimap = 54,
|
||||
mouseStyle = 55,
|
||||
mouseWheelScrollSensitivity = 56,
|
||||
mouseWheelZoom = 57,
|
||||
multiCursorMergeOverlapping = 58,
|
||||
multiCursorModifier = 59,
|
||||
multiCursorPaste = 60,
|
||||
occurrencesHighlight = 61,
|
||||
overviewRulerBorder = 62,
|
||||
overviewRulerLanes = 63,
|
||||
padding = 64,
|
||||
parameterHints = 65,
|
||||
peekWidgetDefaultFocus = 66,
|
||||
definitionLinkOpensInPeek = 67,
|
||||
quickSuggestions = 68,
|
||||
quickSuggestionsDelay = 69,
|
||||
readOnly = 70,
|
||||
renderControlCharacters = 71,
|
||||
renderIndentGuides = 72,
|
||||
renderFinalNewline = 73,
|
||||
renderLineHighlight = 74,
|
||||
renderValidationDecorations = 75,
|
||||
renderWhitespace = 76,
|
||||
revealHorizontalRightPadding = 77,
|
||||
roundedSelection = 78,
|
||||
rulers = 79,
|
||||
scrollbar = 80,
|
||||
scrollBeyondLastColumn = 81,
|
||||
scrollBeyondLastLine = 82,
|
||||
scrollPredominantAxis = 83,
|
||||
selectionClipboard = 84,
|
||||
selectionHighlight = 85,
|
||||
selectOnLineNumbers = 86,
|
||||
showFoldingControls = 87,
|
||||
showUnused = 88,
|
||||
snippetSuggestions = 89,
|
||||
smoothScrolling = 90,
|
||||
stopRenderingLineAfter = 91,
|
||||
suggest = 92,
|
||||
suggestFontSize = 93,
|
||||
suggestLineHeight = 94,
|
||||
suggestOnTriggerCharacters = 95,
|
||||
suggestSelection = 96,
|
||||
tabCompletion = 97,
|
||||
useTabStops = 98,
|
||||
wordSeparators = 99,
|
||||
wordWrap = 100,
|
||||
wordWrapBreakAfterCharacters = 101,
|
||||
wordWrapBreakBeforeCharacters = 102,
|
||||
wordWrapColumn = 103,
|
||||
wordWrapMinified = 104,
|
||||
wrappingIndent = 105,
|
||||
wrappingStrategy = 106,
|
||||
editorClassName = 107,
|
||||
pixelRatio = 108,
|
||||
tabFocusMode = 109,
|
||||
layoutInfo = 110,
|
||||
wrappingInfo = 111
|
||||
columnSelection = 13,
|
||||
comments = 14,
|
||||
contextmenu = 15,
|
||||
copyWithSyntaxHighlighting = 16,
|
||||
cursorBlinking = 17,
|
||||
cursorSmoothCaretAnimation = 18,
|
||||
cursorStyle = 19,
|
||||
cursorSurroundingLines = 20,
|
||||
cursorSurroundingLinesStyle = 21,
|
||||
cursorWidth = 22,
|
||||
disableLayerHinting = 23,
|
||||
disableMonospaceOptimizations = 24,
|
||||
dragAndDrop = 25,
|
||||
emptySelectionClipboard = 26,
|
||||
extraEditorClassName = 27,
|
||||
fastScrollSensitivity = 28,
|
||||
find = 29,
|
||||
fixedOverflowWidgets = 30,
|
||||
folding = 31,
|
||||
foldingStrategy = 32,
|
||||
foldingHighlight = 33,
|
||||
fontFamily = 34,
|
||||
fontInfo = 35,
|
||||
fontLigatures = 36,
|
||||
fontSize = 37,
|
||||
fontWeight = 38,
|
||||
formatOnPaste = 39,
|
||||
formatOnType = 40,
|
||||
glyphMargin = 41,
|
||||
gotoLocation = 42,
|
||||
hideCursorInOverviewRuler = 43,
|
||||
highlightActiveIndentGuide = 44,
|
||||
hover = 45,
|
||||
inDiffEditor = 46,
|
||||
letterSpacing = 47,
|
||||
lightbulb = 48,
|
||||
lineDecorationsWidth = 49,
|
||||
lineHeight = 50,
|
||||
lineNumbers = 51,
|
||||
lineNumbersMinChars = 52,
|
||||
links = 53,
|
||||
matchBrackets = 54,
|
||||
minimap = 55,
|
||||
mouseStyle = 56,
|
||||
mouseWheelScrollSensitivity = 57,
|
||||
mouseWheelZoom = 58,
|
||||
multiCursorMergeOverlapping = 59,
|
||||
multiCursorModifier = 60,
|
||||
multiCursorPaste = 61,
|
||||
occurrencesHighlight = 62,
|
||||
overviewRulerBorder = 63,
|
||||
overviewRulerLanes = 64,
|
||||
padding = 65,
|
||||
parameterHints = 66,
|
||||
peekWidgetDefaultFocus = 67,
|
||||
definitionLinkOpensInPeek = 68,
|
||||
quickSuggestions = 69,
|
||||
quickSuggestionsDelay = 70,
|
||||
readOnly = 71,
|
||||
renderControlCharacters = 72,
|
||||
renderIndentGuides = 73,
|
||||
renderFinalNewline = 74,
|
||||
renderLineHighlight = 75,
|
||||
renderValidationDecorations = 76,
|
||||
renderWhitespace = 77,
|
||||
revealHorizontalRightPadding = 78,
|
||||
roundedSelection = 79,
|
||||
rulers = 80,
|
||||
scrollbar = 81,
|
||||
scrollBeyondLastColumn = 82,
|
||||
scrollBeyondLastLine = 83,
|
||||
scrollPredominantAxis = 84,
|
||||
selectionClipboard = 85,
|
||||
selectionHighlight = 86,
|
||||
selectOnLineNumbers = 87,
|
||||
showFoldingControls = 88,
|
||||
showUnused = 89,
|
||||
snippetSuggestions = 90,
|
||||
smoothScrolling = 91,
|
||||
stopRenderingLineAfter = 92,
|
||||
suggest = 93,
|
||||
suggestFontSize = 94,
|
||||
suggestLineHeight = 95,
|
||||
suggestOnTriggerCharacters = 96,
|
||||
suggestSelection = 97,
|
||||
tabCompletion = 98,
|
||||
useTabStops = 99,
|
||||
wordSeparators = 100,
|
||||
wordWrap = 101,
|
||||
wordWrapBreakAfterCharacters = 102,
|
||||
wordWrapBreakBeforeCharacters = 103,
|
||||
wordWrapColumn = 104,
|
||||
wordWrapMinified = 105,
|
||||
wrappingIndent = 106,
|
||||
wrappingStrategy = 107,
|
||||
editorClassName = 108,
|
||||
pixelRatio = 109,
|
||||
tabFocusMode = 110,
|
||||
layoutInfo = 111,
|
||||
wrappingInfo = 112
|
||||
}
|
||||
export const EditorOptions: {
|
||||
acceptSuggestionOnCommitCharacter: IEditorOption<EditorOption.acceptSuggestionOnCommitCharacter, boolean>;
|
||||
@@ -3912,6 +3918,7 @@ declare namespace monaco.editor {
|
||||
autoSurround: IEditorOption<EditorOption.autoSurround, EditorAutoSurroundStrategy>;
|
||||
codeLens: IEditorOption<EditorOption.codeLens, boolean>;
|
||||
colorDecorators: IEditorOption<EditorOption.colorDecorators, boolean>;
|
||||
columnSelection: IEditorOption<EditorOption.columnSelection, boolean>;
|
||||
comments: IEditorOption<EditorOption.comments, EditorCommentsOptions>;
|
||||
contextmenu: IEditorOption<EditorOption.contextmenu, boolean>;
|
||||
copyWithSyntaxHighlighting: IEditorOption<EditorOption.copyWithSyntaxHighlighting, boolean>;
|
||||
|
||||
@@ -11,8 +11,9 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo
|
||||
import { ICommandService, CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { UriDto } from 'vs/base/common/types';
|
||||
|
||||
export interface ILocalizedString {
|
||||
value: string;
|
||||
@@ -28,9 +29,7 @@ export interface ICommandAction {
|
||||
toggled?: ContextKeyExpr;
|
||||
}
|
||||
|
||||
type Serialized<T> = { [K in keyof T]: T[K] extends URI ? UriComponents : Serialized<T[K]> };
|
||||
|
||||
export type ISerializableCommandAction = Serialized<ICommandAction>;
|
||||
export type ISerializableCommandAction = UriDto<ICommandAction>;
|
||||
|
||||
export interface IMenuItem {
|
||||
command: ICommandAction;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions, IShowResult } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
||||
export class TestDialogService implements IDialogService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
confirm(_confirmation: IConfirmation): Promise<IConfirmationResult> { return Promise.resolve({ confirmed: false }); }
|
||||
show(_severity: Severity, _message: string, _buttons: string[], _options?: IDialogOptions): Promise<IShowResult> { return Promise.resolve({ choice: 0 }); }
|
||||
about(): Promise<void> { return Promise.resolve(); }
|
||||
}
|
||||
@@ -157,7 +157,7 @@ export class InstantiationService implements IInstantiationService {
|
||||
graph.lookupOrInsertNode(item);
|
||||
|
||||
// a weak but working heuristic for cycle checks
|
||||
if (cycleCount++ > 150) {
|
||||
if (cycleCount++ > 200) {
|
||||
throw new CyclicDependencyError(graph);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,8 +86,6 @@ export interface IProgressRunner {
|
||||
done(): void;
|
||||
}
|
||||
|
||||
export const emptyProgress: IProgress<IProgressStep> = { report: () => { } };
|
||||
|
||||
export const emptyProgressRunner: IProgressRunner = Object.freeze({
|
||||
total() { },
|
||||
worked() { },
|
||||
@@ -100,6 +98,8 @@ export interface IProgress<T> {
|
||||
|
||||
export class Progress<T> implements IProgress<T> {
|
||||
|
||||
static readonly None: IProgress<any> = Object.freeze({ report() { } });
|
||||
|
||||
private _value?: T;
|
||||
get value(): T | undefined { return this._value; }
|
||||
|
||||
|
||||
@@ -8,42 +8,26 @@ import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export const IUndoRedoService = createDecorator<IUndoRedoService>('undoRedoService');
|
||||
|
||||
export interface IUndoRedoContext {
|
||||
replaceCurrentElement(others: IUndoRedoElement[]): void;
|
||||
export const enum UndoRedoElementType {
|
||||
Resource,
|
||||
Workspace
|
||||
}
|
||||
|
||||
export interface IUndoRedoElement {
|
||||
/**
|
||||
* None, one or multiple resources that this undo/redo element impacts.
|
||||
*/
|
||||
readonly resources: readonly URI[];
|
||||
|
||||
/**
|
||||
* The label of the undo/redo element.
|
||||
*/
|
||||
export interface IResourceUndoRedoElement {
|
||||
readonly type: UndoRedoElementType.Resource;
|
||||
readonly resource: URI;
|
||||
readonly label: string;
|
||||
undo(): Promise<void> | void;
|
||||
redo(): Promise<void> | void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo.
|
||||
* Will always be called before `redo`.
|
||||
* Can be called multiple times.
|
||||
* e.g. `undo` -> `redo` -> `undo` -> `redo`
|
||||
*/
|
||||
undo(ctx: IUndoRedoContext): void;
|
||||
|
||||
/**
|
||||
* Redo.
|
||||
* Will always be called after `undo`.
|
||||
* Can be called multiple times.
|
||||
* e.g. `undo` -> `redo` -> `undo` -> `redo`
|
||||
*/
|
||||
redo(ctx: IUndoRedoContext): void;
|
||||
|
||||
/**
|
||||
* Invalidate the edits concerning `resource`.
|
||||
* i.e. the undo/redo stack for that particular resource has been destroyed.
|
||||
*/
|
||||
invalidate(resource: URI): void;
|
||||
export interface IWorkspaceUndoRedoElement {
|
||||
readonly type: UndoRedoElementType.Workspace;
|
||||
readonly resources: readonly URI[];
|
||||
readonly label: string;
|
||||
undo(): Promise<void> | void;
|
||||
redo(): Promise<void> | void;
|
||||
split(): IResourceUndoRedoElement[];
|
||||
}
|
||||
|
||||
export interface IUndoRedoService {
|
||||
@@ -53,12 +37,12 @@ export interface IUndoRedoService {
|
||||
* Add a new element to the `undo` stack.
|
||||
* This will destroy the `redo` stack.
|
||||
*/
|
||||
pushElement(element: IUndoRedoElement): void;
|
||||
pushElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement): void;
|
||||
|
||||
/**
|
||||
* Get the last pushed element. If the last pushed element has been undone, returns null.
|
||||
*/
|
||||
getLastElement(resource: URI): IUndoRedoElement | null;
|
||||
getLastElement(resource: URI): IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null;
|
||||
|
||||
/**
|
||||
* Remove elements that target `resource`.
|
||||
@@ -66,8 +50,8 @@ export interface IUndoRedoService {
|
||||
removeElements(resource: URI): void;
|
||||
|
||||
canUndo(resource: URI): boolean;
|
||||
undo(resource: URI): void;
|
||||
undo(resource: URI): Promise<void> | void;
|
||||
|
||||
redo(resource: URI): void;
|
||||
canRedo(resource: URI): boolean;
|
||||
redo(resource: URI): Promise<void> | void;
|
||||
}
|
||||
|
||||
@@ -3,31 +3,88 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IUndoRedoService, IUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IUndoRedoService, IResourceUndoRedoElement, IWorkspaceUndoRedoElement, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getComparisonKey as uriGetComparisonKey } from 'vs/base/common/resources';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
class StackElement {
|
||||
public readonly actual: IUndoRedoElement;
|
||||
class ResourceStackElement {
|
||||
public readonly type = UndoRedoElementType.Resource;
|
||||
public readonly actual: IResourceUndoRedoElement;
|
||||
public readonly label: string;
|
||||
public readonly resources: readonly URI[];
|
||||
|
||||
public readonly resource: URI;
|
||||
public readonly strResource: string;
|
||||
public readonly resources: URI[];
|
||||
public readonly strResources: string[];
|
||||
|
||||
constructor(actual: IUndoRedoElement) {
|
||||
constructor(actual: IResourceUndoRedoElement) {
|
||||
this.actual = actual;
|
||||
this.label = actual.label;
|
||||
this.resources = actual.resources;
|
||||
this.resource = actual.resource;
|
||||
this.strResource = uriGetComparisonKey(this.resource);
|
||||
this.resources = [this.resource];
|
||||
this.strResources = [this.strResource];
|
||||
}
|
||||
}
|
||||
|
||||
const enum RemovedResourceReason {
|
||||
ExternalRemoval = 0,
|
||||
NoParallelUniverses = 1
|
||||
}
|
||||
|
||||
class RemovedResources {
|
||||
public readonly set: Set<string> = new Set<string>();
|
||||
public readonly reason: [URI[], URI[]] = [[], []];
|
||||
|
||||
public createMessage(): string {
|
||||
let messages: string[] = [];
|
||||
if (this.reason[RemovedResourceReason.ExternalRemoval].length > 0) {
|
||||
const paths = this.reason[RemovedResourceReason.ExternalRemoval].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path);
|
||||
messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", paths.join(', ')));
|
||||
}
|
||||
if (this.reason[RemovedResourceReason.NoParallelUniverses].length > 0) {
|
||||
const paths = this.reason[RemovedResourceReason.NoParallelUniverses].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path);
|
||||
messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", paths.join(', ')));
|
||||
}
|
||||
return messages.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
class WorkspaceStackElement {
|
||||
public readonly type = UndoRedoElementType.Workspace;
|
||||
public readonly actual: IWorkspaceUndoRedoElement;
|
||||
public readonly label: string;
|
||||
|
||||
public readonly resources: URI[];
|
||||
public readonly strResources: string[];
|
||||
public removedResources: RemovedResources | null;
|
||||
|
||||
constructor(actual: IWorkspaceUndoRedoElement) {
|
||||
this.actual = actual;
|
||||
this.label = actual.label;
|
||||
this.resources = actual.resources.slice(0);
|
||||
this.strResources = this.resources.map(resource => uriGetComparisonKey(resource));
|
||||
this.removedResources = null;
|
||||
}
|
||||
|
||||
public invalidate(resource: URI): void {
|
||||
if (this.resources.length > 1) {
|
||||
this.actual.invalidate(resource);
|
||||
public removeResource(resource: URI, strResource: string, reason: RemovedResourceReason): void {
|
||||
if (!this.removedResources) {
|
||||
this.removedResources = new RemovedResources();
|
||||
}
|
||||
if (!this.removedResources.set.has(strResource)) {
|
||||
this.removedResources.set.add(strResource);
|
||||
this.removedResources.reason[reason].push(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
type StackElement = ResourceStackElement | WorkspaceStackElement;
|
||||
|
||||
class ResourceEditStack {
|
||||
public resource: URI;
|
||||
@@ -46,12 +103,15 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
|
||||
private readonly _editStacks: Map<string, ResourceEditStack>;
|
||||
|
||||
constructor() {
|
||||
constructor(
|
||||
@IDialogService private readonly _dialogService: IDialogService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
) {
|
||||
this._editStacks = new Map<string, ResourceEditStack>();
|
||||
}
|
||||
|
||||
public pushElement(_element: IUndoRedoElement): void {
|
||||
const element = new StackElement(_element);
|
||||
public pushElement(_element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement): void {
|
||||
const element: StackElement = (_element.type === UndoRedoElementType.Resource ? new ResourceStackElement(_element) : new WorkspaceStackElement(_element));
|
||||
for (let i = 0, len = element.resources.length; i < len; i++) {
|
||||
const resource = element.resources[i];
|
||||
const strResource = element.strResources[i];
|
||||
@@ -66,14 +126,16 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
|
||||
// remove the future
|
||||
for (const futureElement of editStack.future) {
|
||||
futureElement.invalidate(resource);
|
||||
if (futureElement.type === UndoRedoElementType.Workspace) {
|
||||
futureElement.removeResource(resource, strResource, RemovedResourceReason.NoParallelUniverses);
|
||||
}
|
||||
}
|
||||
editStack.future = [];
|
||||
editStack.past.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
public getLastElement(resource: URI): IUndoRedoElement | null {
|
||||
public getLastElement(resource: URI): IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null {
|
||||
const strResource = uriGetComparisonKey(resource);
|
||||
if (this._editStacks.has(strResource)) {
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
@@ -88,15 +150,75 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _splitPastWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set<string> | null): void {
|
||||
const individualArr = toRemove.actual.split();
|
||||
const individualMap = new Map<string, ResourceStackElement>();
|
||||
for (const _element of individualArr) {
|
||||
const element = new ResourceStackElement(_element);
|
||||
individualMap.set(element.strResource, element);
|
||||
}
|
||||
|
||||
for (const strResource of toRemove.strResources) {
|
||||
if (ignoreResources && ignoreResources.has(strResource)) {
|
||||
continue;
|
||||
}
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
for (let j = editStack.past.length - 1; j >= 0; j--) {
|
||||
if (editStack.past[j] === toRemove) {
|
||||
if (individualMap.has(strResource)) {
|
||||
// gets replaced
|
||||
editStack.past[j] = individualMap.get(strResource)!;
|
||||
} else {
|
||||
// gets deleted
|
||||
editStack.past.splice(j, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set<string> | null): void {
|
||||
const individualArr = toRemove.actual.split();
|
||||
const individualMap = new Map<string, ResourceStackElement>();
|
||||
for (const _element of individualArr) {
|
||||
const element = new ResourceStackElement(_element);
|
||||
individualMap.set(element.strResource, element);
|
||||
}
|
||||
|
||||
for (const strResource of toRemove.strResources) {
|
||||
if (ignoreResources && ignoreResources.has(strResource)) {
|
||||
continue;
|
||||
}
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
for (let j = editStack.future.length - 1; j >= 0; j--) {
|
||||
if (editStack.future[j] === toRemove) {
|
||||
if (individualMap.has(strResource)) {
|
||||
// gets replaced
|
||||
editStack.future[j] = individualMap.get(strResource)!;
|
||||
} else {
|
||||
// gets deleted
|
||||
editStack.future.splice(j, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public removeElements(resource: URI): void {
|
||||
const strResource = uriGetComparisonKey(resource);
|
||||
if (this._editStacks.has(strResource)) {
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
for (const pastElement of editStack.past) {
|
||||
pastElement.invalidate(resource);
|
||||
for (const element of editStack.past) {
|
||||
if (element.type === UndoRedoElementType.Workspace) {
|
||||
element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval);
|
||||
}
|
||||
}
|
||||
for (const futureElement of editStack.future) {
|
||||
futureElement.invalidate(resource);
|
||||
for (const element of editStack.future) {
|
||||
if (element.type === UndoRedoElementType.Workspace) {
|
||||
element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval);
|
||||
}
|
||||
}
|
||||
this._editStacks.delete(strResource);
|
||||
}
|
||||
@@ -111,7 +233,85 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
return false;
|
||||
}
|
||||
|
||||
public undo(resource: URI): void {
|
||||
private _onError(err: Error, element: StackElement): void {
|
||||
onUnexpectedError(err);
|
||||
// An error occured while undoing or redoing => drop the undo/redo stack for all affected resources
|
||||
for (const resource of element.resources) {
|
||||
this.removeElements(resource);
|
||||
}
|
||||
this._notificationService.error(err);
|
||||
}
|
||||
|
||||
private _safeInvoke(element: StackElement, invoke: () => Promise<void> | void): Promise<void> | void {
|
||||
let result: Promise<void> | void;
|
||||
try {
|
||||
result = invoke();
|
||||
} catch (err) {
|
||||
return this._onError(err, element);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return result.then(undefined, (err) => this._onError(err, element));
|
||||
}
|
||||
}
|
||||
|
||||
private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
|
||||
if (element.removedResources) {
|
||||
this._splitPastWorkspaceElement(element, element.removedResources.set);
|
||||
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
||||
this._notificationService.info(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// this must be the last past element in all the impacted resources!
|
||||
let affectedEditStacks: ResourceEditStack[] = [];
|
||||
for (const strResource of element.strResources) {
|
||||
affectedEditStacks.push(this._editStacks.get(strResource)!);
|
||||
}
|
||||
|
||||
let cannotUndoDueToResources: URI[] = [];
|
||||
for (const editStack of affectedEditStacks) {
|
||||
if (editStack.past.length === 0 || editStack.past[editStack.past.length - 1] !== element) {
|
||||
cannotUndoDueToResources.push(editStack.resource);
|
||||
}
|
||||
}
|
||||
|
||||
if (cannotUndoDueToResources.length > 0) {
|
||||
this._splitPastWorkspaceElement(element, null);
|
||||
const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
||||
const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
||||
this._notificationService.info(message);
|
||||
return;
|
||||
}
|
||||
|
||||
return this._dialogService.show(
|
||||
Severity.Info,
|
||||
nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label),
|
||||
[
|
||||
nls.localize('ok', "Yes, change {0} files.", affectedEditStacks.length),
|
||||
nls.localize('nok', "No, change only this file.")
|
||||
]
|
||||
).then((result) => {
|
||||
if (result.choice === 0) {
|
||||
for (const editStack of affectedEditStacks) {
|
||||
editStack.past.pop();
|
||||
editStack.future.push(element);
|
||||
}
|
||||
return this._safeInvoke(element, () => element.actual.undo());
|
||||
} else {
|
||||
this._splitPastWorkspaceElement(element, null);
|
||||
return this.undo(resource);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _resourceUndo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
|
||||
editStack.past.pop();
|
||||
editStack.future.push(element);
|
||||
return this._safeInvoke(element, () => element.actual.undo());
|
||||
}
|
||||
|
||||
public undo(resource: URI): Promise<void> | void {
|
||||
const strResource = uriGetComparisonKey(resource);
|
||||
if (!this._editStacks.has(strResource)) {
|
||||
return;
|
||||
@@ -123,51 +323,10 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
}
|
||||
|
||||
const element = editStack.past[editStack.past.length - 1];
|
||||
|
||||
let replaceCurrentElement: IUndoRedoElement[] | null = null as IUndoRedoElement[] | null;
|
||||
try {
|
||||
element.actual.undo({
|
||||
replaceCurrentElement: (others: IUndoRedoElement[]): void => {
|
||||
replaceCurrentElement = others;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
editStack.past.pop();
|
||||
editStack.future.push(element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (replaceCurrentElement === null) {
|
||||
// regular case
|
||||
editStack.past.pop();
|
||||
editStack.future.push(element);
|
||||
return;
|
||||
}
|
||||
|
||||
const replaceCurrentElementMap = new Map<string, StackElement>();
|
||||
for (const _replace of replaceCurrentElement) {
|
||||
const replace = new StackElement(_replace);
|
||||
for (const strResource of replace.strResources) {
|
||||
replaceCurrentElementMap.set(strResource, replace);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0, len = element.strResources.length; i < len; i++) {
|
||||
const strResource = element.strResources[i];
|
||||
if (this._editStacks.has(strResource)) {
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
for (let j = editStack.past.length - 1; j >= 0; j--) {
|
||||
if (editStack.past[j] === element) {
|
||||
if (replaceCurrentElementMap.has(strResource)) {
|
||||
editStack.past[j] = replaceCurrentElementMap.get(strResource)!;
|
||||
} else {
|
||||
editStack.past.splice(j, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element.type === UndoRedoElementType.Workspace) {
|
||||
return this._workspaceUndo(resource, element);
|
||||
} else {
|
||||
return this._resourceUndo(editStack, element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +339,49 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
return false;
|
||||
}
|
||||
|
||||
public redo(resource: URI): void {
|
||||
private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
|
||||
if (element.removedResources) {
|
||||
this._splitFutureWorkspaceElement(element, element.removedResources.set);
|
||||
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
||||
this._notificationService.info(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// this must be the last future element in all the impacted resources!
|
||||
let affectedEditStacks: ResourceEditStack[] = [];
|
||||
for (const strResource of element.strResources) {
|
||||
affectedEditStacks.push(this._editStacks.get(strResource)!);
|
||||
}
|
||||
|
||||
let cannotRedoDueToResources: URI[] = [];
|
||||
for (const editStack of affectedEditStacks) {
|
||||
if (editStack.future.length === 0 || editStack.future[editStack.future.length - 1] !== element) {
|
||||
cannotRedoDueToResources.push(editStack.resource);
|
||||
}
|
||||
}
|
||||
|
||||
if (cannotRedoDueToResources.length > 0) {
|
||||
this._splitFutureWorkspaceElement(element, null);
|
||||
const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
||||
const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
||||
this._notificationService.info(message);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const editStack of affectedEditStacks) {
|
||||
editStack.future.pop();
|
||||
editStack.past.push(element);
|
||||
}
|
||||
return this._safeInvoke(element, () => element.actual.redo());
|
||||
}
|
||||
|
||||
private _resourceRedo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
|
||||
editStack.future.pop();
|
||||
editStack.past.push(element);
|
||||
return this._safeInvoke(element, () => element.actual.redo());
|
||||
}
|
||||
|
||||
public redo(resource: URI): Promise<void> | void {
|
||||
const strResource = uriGetComparisonKey(resource);
|
||||
if (!this._editStacks.has(strResource)) {
|
||||
return;
|
||||
@@ -192,51 +393,10 @@ export class UndoRedoService implements IUndoRedoService {
|
||||
}
|
||||
|
||||
const element = editStack.future[editStack.future.length - 1];
|
||||
|
||||
let replaceCurrentElement: IUndoRedoElement[] | null = null as IUndoRedoElement[] | null;
|
||||
try {
|
||||
element.actual.redo({
|
||||
replaceCurrentElement: (others: IUndoRedoElement[]): void => {
|
||||
replaceCurrentElement = others;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
editStack.future.pop();
|
||||
editStack.past.push(element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (replaceCurrentElement === null) {
|
||||
// regular case
|
||||
editStack.future.pop();
|
||||
editStack.past.push(element);
|
||||
return;
|
||||
}
|
||||
|
||||
const replaceCurrentElementMap = new Map<string, StackElement>();
|
||||
for (const _replace of replaceCurrentElement) {
|
||||
const replace = new StackElement(_replace);
|
||||
for (const strResource of replace.strResources) {
|
||||
replaceCurrentElementMap.set(strResource, replace);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0, len = element.strResources.length; i < len; i++) {
|
||||
const strResource = element.strResources[i];
|
||||
if (this._editStacks.has(strResource)) {
|
||||
const editStack = this._editStacks.get(strResource)!;
|
||||
for (let j = editStack.future.length - 1; j >= 0; j--) {
|
||||
if (editStack.future[j] === element) {
|
||||
if (replaceCurrentElementMap.has(strResource)) {
|
||||
editStack.future[j] = replaceCurrentElementMap.get(strResource)!;
|
||||
} else {
|
||||
editStack.future.splice(j, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (element.type === UndoRedoElementType.Workspace) {
|
||||
return this._workspaceRedo(resource, element);
|
||||
} else {
|
||||
return this._resourceRedo(editStack, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ import { ParseError, parse } from 'vs/base/common/json';
|
||||
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
const BACK_UP_MAX_AGE = 1000 * 60 * 60 * 24 * 30; /* 30 days */
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
type SyncSourceClassification = {
|
||||
source?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
@@ -65,6 +64,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
@IUserDataSyncEnablementService protected readonly userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService protected readonly logService: IUserDataSyncLogService,
|
||||
@IConfigurationService protected readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this.syncFolder = joinPath(environmentService.userDataSyncHome, source);
|
||||
@@ -91,7 +91,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
|
||||
protected get enabled(): boolean { return this.userDataSyncEnablementService.isResourceEnabled(this.resourceKey); }
|
||||
|
||||
async sync(ref?: string): Promise<void> {
|
||||
async sync(ref?: string, donotUseLastSyncUserData?: boolean): Promise<void> {
|
||||
if (!this.enabled) {
|
||||
this.logService.info(`${this.source}: Skipped synchronizing ${this.source.toLowerCase()} as it is disabled.`);
|
||||
return;
|
||||
@@ -108,7 +108,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
this.logService.trace(`${this.source}: Started synchronizing ${this.source.toLowerCase()}...`);
|
||||
this.setStatus(SyncStatus.Syncing);
|
||||
|
||||
const lastSyncUserData = await this.getLastSyncUserData();
|
||||
const lastSyncUserData = donotUseLastSyncUserData ? null : await this.getLastSyncUserData();
|
||||
const remoteUserData = ref && lastSyncUserData && lastSyncUserData.ref === ref ? lastSyncUserData : await this.getRemoteUserData(lastSyncUserData);
|
||||
|
||||
if (remoteUserData.syncData && remoteUserData.syncData.version > this.version) {
|
||||
@@ -117,7 +117,19 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
throw new UserDataSyncError(localize('incompatible', "Cannot sync {0} as its version {1} is not compatible with cloud {2}", this.source, this.version, remoteUserData.syncData.version), UserDataSyncErrorCode.Incompatible, this.source);
|
||||
}
|
||||
|
||||
return this.doSync(remoteUserData, lastSyncUserData);
|
||||
try {
|
||||
await this.doSync(remoteUserData, lastSyncUserData);
|
||||
} catch (e) {
|
||||
if (e instanceof UserDataSyncError) {
|
||||
switch (e.code) {
|
||||
case UserDataSyncErrorCode.RemotePreconditionFailed:
|
||||
// Rejected as there is a new remote version. Syncing again,
|
||||
this.logService.info(`${this.source}: Failed to synchronize as there is a new remote version available. Synchronizing again...`);
|
||||
return this.sync(undefined, true);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async hasPreviouslySynced(): Promise<boolean> {
|
||||
@@ -191,15 +203,21 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
|
||||
protected async backupLocal(content: VSBuffer): Promise<void> {
|
||||
const resource = joinPath(this.syncFolder, toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, ''));
|
||||
await this.fileService.writeFile(resource, content);
|
||||
try {
|
||||
await this.fileService.writeFile(resource, content);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
this.cleanUpDelayer.trigger(() => this.cleanUpBackup());
|
||||
}
|
||||
|
||||
private async cleanUpBackup(): Promise<void> {
|
||||
const stat = await this.fileService.resolve(this.syncFolder);
|
||||
if (stat.children) {
|
||||
const toDelete = stat.children.filter(stat => {
|
||||
if (stat.isFile && /^\d{8}T\d{6}$/.test(stat.name)) {
|
||||
try {
|
||||
const stat = await this.fileService.resolve(this.syncFolder);
|
||||
if (stat.children) {
|
||||
const all = stat.children.filter(stat => stat.isFile && /^\d{8}T\d{6}$/.test(stat.name)).sort();
|
||||
const backUpMaxAge = 1000 * 60 * 60 * 24 * (this.configurationService.getValue<number>('sync.localBackupDuration') || 30 /* Default 30 days */);
|
||||
let toDelete = all.filter(stat => {
|
||||
const ctime = stat.ctime || new Date(
|
||||
parseInt(stat.name.substring(0, 4)),
|
||||
parseInt(stat.name.substring(4, 6)) - 1,
|
||||
@@ -208,14 +226,19 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
parseInt(stat.name.substring(11, 13)),
|
||||
parseInt(stat.name.substring(13, 15))
|
||||
).getTime();
|
||||
return Date.now() - ctime > BACK_UP_MAX_AGE;
|
||||
return Date.now() - ctime > backUpMaxAge;
|
||||
});
|
||||
const remaining = all.length - toDelete.length;
|
||||
if (remaining < 10) {
|
||||
toDelete = toDelete.slice(10 - remaining);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
await Promise.all(toDelete.map(stat => {
|
||||
this.logService.info('Deleting from backup', stat.resource.path);
|
||||
this.fileService.del(stat.resource);
|
||||
}));
|
||||
await Promise.all(toDelete.map(stat => {
|
||||
this.logService.info('Deleting from backup', stat.resource.path);
|
||||
this.fileService.del(stat.resource);
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +270,9 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||
super(source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(this.fileService.watch(dirname(file)));
|
||||
this._register(this.fileService.onDidFilesChange(e => this.onFileChanges(e)));
|
||||
}
|
||||
@@ -346,8 +370,9 @@ export abstract class AbstractJsonFileSynchroniser extends AbstractFileSynchroni
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IUserDataSyncUtilService protected readonly userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(file, source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||
super(file, source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
}
|
||||
|
||||
protected hasErrors(content: string): boolean {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncSource, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
@@ -46,11 +46,11 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
||||
@IGlobalExtensionEnablementService private readonly extensionEnablementService: IGlobalExtensionEnablementService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(SyncSource.Extensions, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||
super(SyncSource.Extensions, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(
|
||||
Event.debounce(
|
||||
Event.any<any>(
|
||||
@@ -154,11 +154,6 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
||||
await this.apply(previewResult);
|
||||
} catch (e) {
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.RemotePreconditionFailed) {
|
||||
// Rejected as there is a new remote version. Syncing again,
|
||||
this.logService.info('Extensions: Failed to synchronize extensions as there is a new remote version available. Synchronizing again...');
|
||||
return this.sync();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncSource, IUserDataSynchroniser, ResourceKey, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
@@ -15,6 +15,7 @@ import { merge } from 'vs/platform/userDataSync/common/globalStateMerge';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
const argvProperties: string[] = ['locale'];
|
||||
|
||||
@@ -38,8 +39,9 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(SyncSource.GlobalState, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||
super(SyncSource.GlobalState, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService);
|
||||
this._register(this.fileService.watch(dirname(this.environmentService.argvResource)));
|
||||
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource))(() => this._onDidChangeLocal.fire()));
|
||||
}
|
||||
@@ -129,11 +131,6 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
||||
this.logService.trace('UI State: Finished synchronizing ui state.');
|
||||
} catch (e) {
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.RemotePreconditionFailed) {
|
||||
// Rejected as there is a new remote version. Syncing again,
|
||||
this.logService.info('UI State: Failed to synchronize ui state as there is a new remote version available. Synchronizing again...');
|
||||
return this.sync();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
|
||||
@@ -36,14 +36,14 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
||||
constructor(
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IUserDataSyncUtilService userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
) {
|
||||
super(environmentService.keybindingsResource, SyncSource.Keybindings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService);
|
||||
super(environmentService.keybindingsResource, SyncSource.Keybindings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
}
|
||||
|
||||
async pull(): Promise<void> {
|
||||
@@ -180,10 +180,6 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
if (e instanceof UserDataSyncError) {
|
||||
switch (e.code) {
|
||||
case UserDataSyncErrorCode.RemotePreconditionFailed:
|
||||
// Rejected as there is a new remote version. Syncing again,
|
||||
this.logService.info('Keybindings: Failed to synchronize keybindings as there is a new remote version available. Synchronizing again...');
|
||||
return this.sync();
|
||||
case UserDataSyncErrorCode.LocalPreconditionFailed:
|
||||
// Rejected as there is a new local version. Syncing again.
|
||||
this.logService.info('Keybindings: Failed to synchronize keybindings as there is a new local version available. Synchronizing again...');
|
||||
|
||||
@@ -10,8 +10,8 @@ import { values } from 'vs/base/common/map';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { FormattingOptions, Edit, getEOL } from 'vs/base/common/jsonFormatter';
|
||||
import * as contentUtil from 'vs/platform/userDataSync/common/content';
|
||||
import { IConflictSetting, CONFIGURATION_SYNC_STORE_KEY } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { IConflictSetting } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { firstIndex, distinct } from 'vs/base/common/arrays';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
|
||||
@@ -22,7 +22,7 @@ export interface IMergeResult {
|
||||
conflictsSettings: IConflictSetting[];
|
||||
}
|
||||
|
||||
export function getIgnoredSettings(configurationService: IConfigurationService, settingsContent?: string): string[] {
|
||||
export function getIgnoredSettings(defaultIgnoredSettings: string[], configurationService: IConfigurationService, settingsContent?: string): string[] {
|
||||
let value: string[] = [];
|
||||
if (settingsContent) {
|
||||
const setting = parse(settingsContent);
|
||||
@@ -42,7 +42,7 @@ export function getIgnoredSettings(configurationService: IConfigurationService,
|
||||
}
|
||||
}
|
||||
}
|
||||
return [CONFIGURATION_SYNC_STORE_KEY, ...added].filter(setting => removed.indexOf(setting) === -1);
|
||||
return distinct([...defaultIgnoredSettings, ...added,].filter(setting => removed.indexOf(setting) === -1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { edit } from 'vs/platform/userDataSync/common/content';
|
||||
import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
||||
interface ISettingsSyncContent {
|
||||
settings: string;
|
||||
@@ -51,11 +52,12 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
|
||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||
@IUserDataSyncUtilService userDataSyncUtilService: IUserDataSyncUtilService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
) {
|
||||
super(environmentService.settingsResource, SyncSource.Settings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService);
|
||||
super(environmentService.settingsResource, SyncSource.Settings, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService);
|
||||
}
|
||||
|
||||
protected setStatus(status: SyncStatus): void {
|
||||
@@ -94,7 +96,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
const fileContent = await this.getLocalFileContent();
|
||||
const formatUtils = await this.getFormattingOptions();
|
||||
// Update ignored settings from local file content
|
||||
const content = updateIgnoredSettings(remoteSettingsSyncContent.settings, fileContent ? fileContent.value.toString() : '{}', getIgnoredSettings(this.configurationService), formatUtils);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
const content = updateIgnoredSettings(remoteSettingsSyncContent.settings, fileContent ? fileContent.value.toString() : '{}', ignoredSettings, formatUtils);
|
||||
this.syncPreviewResultPromise = createCancelablePromise(() => Promise.resolve<IFileSyncPreviewResult>({
|
||||
fileContent,
|
||||
remoteUserData,
|
||||
@@ -136,7 +139,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
if (fileContent !== null) {
|
||||
const formatUtils = await this.getFormattingOptions();
|
||||
// Remove ignored settings
|
||||
const content = updateIgnoredSettings(fileContent.value.toString(), '{}', getIgnoredSettings(this.configurationService), formatUtils);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
const content = updateIgnoredSettings(fileContent.value.toString(), '{}', ignoredSettings, formatUtils);
|
||||
const lastSyncUserData = await this.getLastSyncUserData();
|
||||
const remoteUserData = await this.getRemoteUserData(lastSyncUserData);
|
||||
|
||||
@@ -192,7 +196,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
if (preview && content !== null) {
|
||||
const formatUtils = await this.getFormattingOptions();
|
||||
// remove ignored settings from the remote content for preview
|
||||
content = updateIgnoredSettings(content, '{}', getIgnoredSettings(this.configurationService), formatUtils);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
content = updateIgnoredSettings(content, '{}', ignoredSettings, formatUtils);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
@@ -203,7 +208,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
this.cancel();
|
||||
const formatUtils = await this.getFormattingOptions();
|
||||
// Add ignored settings from local file content
|
||||
content = updateIgnoredSettings(content, preview.fileContent ? preview.fileContent.value.toString() : '{}', getIgnoredSettings(this.configurationService), formatUtils);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
content = updateIgnoredSettings(content, preview.fileContent ? preview.fileContent.value.toString() : '{}', ignoredSettings, formatUtils);
|
||||
this.syncPreviewResultPromise = createCancelablePromise(async () => ({ ...preview, content }));
|
||||
await this.apply(true);
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
@@ -237,10 +243,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
if (e instanceof UserDataSyncError) {
|
||||
switch (e.code) {
|
||||
case UserDataSyncErrorCode.RemotePreconditionFailed:
|
||||
// Rejected as there is a new remote version. Syncing again,
|
||||
this.logService.info('Settings: Failed to synchronize settings as there is a new remote version available. Synchronizing again...');
|
||||
return this.sync();
|
||||
case UserDataSyncErrorCode.LocalPreconditionFailed:
|
||||
// Rejected as there is a new local version. Syncing again.
|
||||
this.logService.info('Settings: Failed to synchronize settings as there is a new local version available. Synchronizing again...');
|
||||
@@ -271,7 +273,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
const formatUtils = await this.getFormattingOptions();
|
||||
// Update ignored settings from remote
|
||||
const remoteSettingsSyncContent = this.getSettingsSyncContent(remoteUserData);
|
||||
content = updateIgnoredSettings(content, remoteSettingsSyncContent ? remoteSettingsSyncContent.settings : '{}', getIgnoredSettings(this.configurationService, content), formatUtils);
|
||||
const ignoredSettings = await this.getIgnoredSettings(content);
|
||||
content = updateIgnoredSettings(content, remoteSettingsSyncContent ? remoteSettingsSyncContent.settings : '{}', ignoredSettings, formatUtils);
|
||||
this.logService.trace('Settings: Updating remote settings...');
|
||||
remoteUserData = await this.updateRemoteUserData(JSON.stringify(<ISettingsSyncContent>{ settings: content }), forcePush ? null : remoteUserData.ref);
|
||||
this.logService.info('Settings: Updated remote settings');
|
||||
@@ -317,7 +320,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
const localContent: string = fileContent ? fileContent.value.toString() : '{}';
|
||||
this.validateContent(localContent);
|
||||
this.logService.trace('Settings: Merging remote settings with local settings...');
|
||||
const result = merge(localContent, remoteSettingsSyncContent.settings, lastSettingsSyncContent ? lastSettingsSyncContent.settings : null, getIgnoredSettings(this.configurationService), resolvedConflicts, formattingOptions);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
const result = merge(localContent, remoteSettingsSyncContent.settings, lastSettingsSyncContent ? lastSettingsSyncContent.settings : null, ignoredSettings, resolvedConflicts, formattingOptions);
|
||||
content = result.localContent || result.remoteContent;
|
||||
hasLocalChanged = result.localContent !== null;
|
||||
hasRemoteChanged = result.remoteContent !== null;
|
||||
@@ -334,7 +338,8 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
|
||||
if (content && !token.isCancellationRequested) {
|
||||
// Remove the ignored settings from the preview.
|
||||
const previewContent = updateIgnoredSettings(content, '{}', getIgnoredSettings(this.configurationService), formattingOptions);
|
||||
const ignoredSettings = await this.getIgnoredSettings();
|
||||
const previewContent = updateIgnoredSettings(content, '{}', ignoredSettings, formattingOptions);
|
||||
await this.fileService.writeFile(this.environmentService.settingsSyncPreviewResource, VSBuffer.fromString(previewContent));
|
||||
}
|
||||
|
||||
@@ -356,6 +361,21 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser implement
|
||||
return null;
|
||||
}
|
||||
|
||||
private _defaultIgnoredSettings: Promise<string[]> | undefined = undefined;
|
||||
protected async getIgnoredSettings(content?: string): Promise<string[]> {
|
||||
if (!this._defaultIgnoredSettings) {
|
||||
this._defaultIgnoredSettings = this.userDataSyncUtilService.resolveDefaultIgnoredSettings();
|
||||
const disposable = Event.any<any>(
|
||||
Event.filter(this.extensionManagementService.onDidInstallExtension, (e => !!e.gallery)),
|
||||
Event.filter(this.extensionManagementService.onDidUninstallExtension, (e => !e.error)))(() => {
|
||||
disposable.dispose();
|
||||
this._defaultIgnoredSettings = undefined;
|
||||
});
|
||||
}
|
||||
const defaultIgnoredSettings = await this._defaultIgnoredSettings;
|
||||
return getIgnoredSettings(defaultIgnoredSettings, this.configurationService, content);
|
||||
}
|
||||
|
||||
private validateContent(content: string): void {
|
||||
if (this.hasErrors(content)) {
|
||||
throw new UserDataSyncError(localize('errorInvalidSettings', "Unable to sync settings as there are errors/warning in settings file."), UserDataSyncErrorCode.LocalInvalidContent, this.source);
|
||||
|
||||
@@ -36,6 +36,12 @@ export interface ISyncConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
export function getDefaultIgnoredSettings(): string[] {
|
||||
const allSettings = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
|
||||
const machineSettings = Object.keys(allSettings).filter(setting => allSettings[setting].scope === ConfigurationScope.MACHINE || allSettings[setting].scope === ConfigurationScope.MACHINE_OVERRIDABLE);
|
||||
return [CONFIGURATION_SYNC_STORE_KEY, ...machineSettings];
|
||||
}
|
||||
|
||||
export function registerConfiguration(): IDisposable {
|
||||
const ignoredSettingsSchemaId = 'vscode://schemas/ignoredSettings';
|
||||
const ignoredExtensionsSchemaId = 'vscode://schemas/ignoredExtensions';
|
||||
@@ -105,11 +111,12 @@ export function registerConfiguration(): IDisposable {
|
||||
});
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
const registerIgnoredSettingsSchema = () => {
|
||||
const defaultIgnoreSettings = getDefaultIgnoredSettings().filter(s => s !== CONFIGURATION_SYNC_STORE_KEY);
|
||||
const ignoredSettingsSchema: IJSONSchema = {
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: Object.keys(allSettings.properties)
|
||||
}
|
||||
enum: [...Object.keys(allSettings.properties).filter(setting => defaultIgnoreSettings.indexOf(setting) === -1), ...defaultIgnoreSettings.map(setting => `-${setting}`)]
|
||||
},
|
||||
};
|
||||
jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema);
|
||||
};
|
||||
@@ -180,6 +187,7 @@ export enum UserDataSyncErrorCode {
|
||||
// Local Errors
|
||||
LocalPreconditionFailed = 'LocalPreconditionFailed',
|
||||
LocalInvalidContent = 'LocalInvalidContent',
|
||||
LocalError = 'LocalError',
|
||||
Incompatible = 'Incompatible',
|
||||
|
||||
Unknown = 'Unknown',
|
||||
@@ -286,6 +294,7 @@ export interface IUserDataSyncService {
|
||||
readonly onDidChangeConflicts: Event<SyncSource[]>;
|
||||
|
||||
readonly onDidChangeLocal: Event<void>;
|
||||
readonly onSyncErrors: Event<[SyncSource, UserDataSyncError][]>;
|
||||
|
||||
readonly lastSyncTime: number | undefined;
|
||||
readonly onDidChangeLastSyncTime: Event<number>;
|
||||
@@ -313,6 +322,7 @@ export interface IUserDataSyncUtilService {
|
||||
_serviceBrand: undefined;
|
||||
resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>>;
|
||||
resolveFormattingOptions(resource: URI): Promise<FormattingOptions>;
|
||||
resolveDefaultIgnoredSettings(): Promise<string[]>;
|
||||
}
|
||||
|
||||
export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');
|
||||
|
||||
@@ -20,6 +20,7 @@ export class UserDataSyncChannel implements IServerChannel {
|
||||
case 'onDidChangeConflicts': return this.service.onDidChangeConflicts;
|
||||
case 'onDidChangeLocal': return this.service.onDidChangeLocal;
|
||||
case 'onDidChangeLastSyncTime': return this.service.onDidChangeLastSyncTime;
|
||||
case 'onSyncErrors': return this.service.onSyncErrors;
|
||||
}
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
@@ -101,6 +102,7 @@ export class UserDataSycnUtilServiceChannel implements IServerChannel {
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'resolveDefaultIgnoredSettings': return this.service.resolveDefaultIgnoredSettings();
|
||||
case 'resolveUserKeybindings': return this.service.resolveUserBindings(args[0]);
|
||||
case 'resolveFormattingOptions': return this.service.resolveFormattingOptions(URI.revive(args[0]));
|
||||
}
|
||||
@@ -115,6 +117,10 @@ export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService {
|
||||
constructor(private readonly channel: IChannel) {
|
||||
}
|
||||
|
||||
async resolveDefaultIgnoredSettings(): Promise<string[]> {
|
||||
return this.channel.call('resolveDefaultIgnoredSettings');
|
||||
}
|
||||
|
||||
async resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>> {
|
||||
return this.channel.call('resolveUserKeybindings', [userbindings]);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
private _onDidChangeConflicts: Emitter<SyncSource[]> = this._register(new Emitter<SyncSource[]>());
|
||||
readonly onDidChangeConflicts: Event<SyncSource[]> = this._onDidChangeConflicts.event;
|
||||
|
||||
private _syncErrors: [SyncSource, UserDataSyncError][] = [];
|
||||
private _onSyncErrors: Emitter<[SyncSource, UserDataSyncError][]> = this._register(new Emitter<[SyncSource, UserDataSyncError][]>());
|
||||
readonly onSyncErrors: Event<[SyncSource, UserDataSyncError][]> = this._onSyncErrors.event;
|
||||
|
||||
private _lastSyncTime: number | undefined = undefined;
|
||||
get lastSyncTime(): number | undefined { return this._lastSyncTime; }
|
||||
private _onDidChangeLastSyncTime: Emitter<number> = this._register(new Emitter<number>());
|
||||
@@ -82,6 +86,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
this.handleSyncError(e, synchroniser.source);
|
||||
}
|
||||
}
|
||||
this.updateLastSyncTime();
|
||||
}
|
||||
|
||||
async push(): Promise<void> {
|
||||
@@ -93,12 +98,14 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
this.handleSyncError(e, synchroniser.source);
|
||||
}
|
||||
}
|
||||
this.updateLastSyncTime();
|
||||
}
|
||||
|
||||
async sync(): Promise<void> {
|
||||
await this.checkEnablement();
|
||||
|
||||
const startTime = new Date().getTime();
|
||||
this._syncErrors = [];
|
||||
try {
|
||||
this.logService.trace('Sync started.');
|
||||
if (this.status !== SyncStatus.HasConflicts) {
|
||||
@@ -124,6 +131,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
await synchroniser.sync(manifest && manifest.latest ? manifest.latest[synchroniser.resourceKey] : undefined);
|
||||
} catch (e) {
|
||||
this.handleSyncError(e, synchroniser.source);
|
||||
this._syncErrors.push([synchroniser.source, UserDataSyncError.toUserDataSyncError(e)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,9 +146,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
}
|
||||
|
||||
this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
|
||||
this.updateLastSyncTime();
|
||||
|
||||
} finally {
|
||||
this.updateStatus();
|
||||
this._onSyncErrors.fire(this._syncErrors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,8 +249,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
if (this._status !== status) {
|
||||
this._status = status;
|
||||
this._onDidChangeStatus.fire(status);
|
||||
if (oldStatus !== SyncStatus.Uninitialized && this.status === SyncStatus.Idle) {
|
||||
this.updateLastSyncTime(new Date().getTime());
|
||||
if (oldStatus === SyncStatus.HasConflicts) {
|
||||
this.updateLastSyncTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,11 +278,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
return SyncStatus.Idle;
|
||||
}
|
||||
|
||||
private updateLastSyncTime(lastSyncTime: number): void {
|
||||
if (this._lastSyncTime !== lastSyncTime) {
|
||||
this._lastSyncTime = lastSyncTime;
|
||||
this.storageService.store(LAST_SYNC_TIME_KEY, lastSyncTime, StorageScope.GLOBAL);
|
||||
this._onDidChangeLastSyncTime.fire(lastSyncTime);
|
||||
private updateLastSyncTime(): void {
|
||||
if (this.status === SyncStatus.Idle) {
|
||||
this._lastSyncTime = new Date().getTime();
|
||||
this.storageService.store(LAST_SYNC_TIME_KEY, this._lastSyncTime, StorageScope.GLOBAL);
|
||||
this._onDidChangeLastSyncTime.fire(this._lastSyncTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IUserData, ResourceKey, IUserDataManifest, ALL_RESOURCE_KEYS, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncEnablementService, ISettingsSyncService, IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserData, ResourceKey, IUserDataManifest, ALL_RESOURCE_KEYS, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncEnablementService, ISettingsSyncService, IUserDataSyncService, getDefaultIgnoredSettings } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { bufferToStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||
@@ -231,6 +231,10 @@ export class TestUserDataSyncUtilService implements IUserDataSyncUtilService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
async resolveDefaultIgnoredSettings(): Promise<string[]> {
|
||||
return getDefaultIgnoredSettings();
|
||||
}
|
||||
|
||||
async resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>> {
|
||||
const keys: IStringDictionary<string> = {};
|
||||
for (const keybinding of userbindings) {
|
||||
|
||||
Vendored
+149
-35
@@ -1187,65 +1187,77 @@ declare module 'vscode' {
|
||||
|
||||
//#region Custom editors: https://github.com/microsoft/vscode/issues/77131
|
||||
|
||||
// TODO:
|
||||
// - Naming!
|
||||
// - Think about where a rename would live.
|
||||
// - Think about handling go to line?
|
||||
// - Should we expose edits?
|
||||
// - More properties from `TextDocument`?
|
||||
|
||||
/**
|
||||
* Defines the editing functionality of a webview editor. This allows the webview editor to hook into standard
|
||||
* Defines the capabilities of a custom webview editor.
|
||||
*/
|
||||
interface WebviewCustomEditorCapabilities {
|
||||
/**
|
||||
* Defines the editing capability of a custom webview document.
|
||||
*
|
||||
* When not provided, the document is considered readonly.
|
||||
*/
|
||||
readonly editing?: WebviewCustomEditorEditingCapability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the editing capability of a custom webview editor. This allows the webview editor to hook into standard
|
||||
* editor events such as `undo` or `save`.
|
||||
*
|
||||
* @param EditType Type of edits.
|
||||
*/
|
||||
interface WebviewCustomEditorEditingDelegate<EditType> {
|
||||
interface WebviewCustomEditorEditingCapability<EditType = unknown> {
|
||||
/**
|
||||
* Save a resource.
|
||||
*
|
||||
* @param resource Resource being saved.
|
||||
* Save the resource.
|
||||
*
|
||||
* @return Thenable signaling that the save has completed.
|
||||
*/
|
||||
save(resource: Uri): Thenable<void>;
|
||||
save(): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Save an existing resource at a new path.
|
||||
* Save the existing resource at a new path.
|
||||
*
|
||||
* @param resource Resource being saved.
|
||||
* @param targetResource Location to save to.
|
||||
*
|
||||
* @return Thenable signaling that the save has completed.
|
||||
*/
|
||||
saveAs(resource: Uri, targetResource: Uri): Thenable<void>;
|
||||
saveAs(targetResource: Uri): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Event triggered by extensions to signal to VS Code that an edit has occurred.
|
||||
*/
|
||||
// TODO@matt
|
||||
// eslint-disable-next-line vscode-dts-event-naming
|
||||
readonly onEdit: Event<{ readonly resource: Uri, readonly edit: EditType }>;
|
||||
readonly onDidEdit: Event<EditType>;
|
||||
|
||||
/**
|
||||
* Apply a set of edits.
|
||||
*
|
||||
* Note that is not invoked when `onEdit` is called as `onEdit` implies also updating the view to reflect the edit.
|
||||
* Note that is not invoked when `onDidEdit` is called because `onDidEdit` implies also updating the view to reflect the edit.
|
||||
*
|
||||
* @param resource Resource being edited.
|
||||
* @param edit Array of edits. Sorted from oldest to most recent.
|
||||
*
|
||||
* @return Thenable signaling that the change has completed.
|
||||
*/
|
||||
applyEdits(resource: Uri, edits: readonly EditType[]): Thenable<void>;
|
||||
applyEdits(edits: readonly EditType[]): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Undo a set of edits.
|
||||
*
|
||||
* This is triggered when a user undoes an edit or when revert is called on a file.
|
||||
*
|
||||
* @param resource Resource being edited.
|
||||
* @param edit Array of edits. Sorted from most recent to oldest.
|
||||
*
|
||||
* @return Thenable signaling that the change has completed.
|
||||
*/
|
||||
undoEdits(resource: Uri, edits: readonly EditType[]): Thenable<void>;
|
||||
undoEdits(edits: readonly EditType[]): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Back up `resource` in its current state.
|
||||
* Back up the resource in its current state.
|
||||
*
|
||||
* Backups are used for hot exit and to prevent data loss. Your `backup` method should persist the resource in
|
||||
* its current state, i.e. with the edits applied. Most commonly this means saving the resource to disk in
|
||||
@@ -1257,57 +1269,159 @@ declare module 'vscode' {
|
||||
* made in quick succession, `backup` is only triggered after the last one. `backup` is not invoked when
|
||||
* `auto save` is enabled (since auto save already persists resource ).
|
||||
*
|
||||
* @param resource The resource to back up.
|
||||
* @param cancellation Token that signals the current backup since a new backup is coming in. It is up to your
|
||||
* extension to decided how to respond to cancellation. If for example your extension is backing up a large file
|
||||
* in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather
|
||||
* than cancelling it to ensure that VS Code has some valid backup.
|
||||
*/
|
||||
backup?(resource: Uri, cancellation: CancellationToken): Thenable<boolean>;
|
||||
backup(cancellation: CancellationToken): Thenable<boolean>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a custom document for a custom webview editor.
|
||||
*
|
||||
* Custom documents are only used within a given `WebviewCustomEditorProvider`. The lifecycle of a
|
||||
* `WebviewEditorCustomDocument` is managed by VS Code. When more more references remain to a given `WebviewEditorCustomDocument`
|
||||
* then it is disposed of.
|
||||
*
|
||||
* @param UserDataType Type of custom object that extensions can store on the document.
|
||||
*/
|
||||
interface WebviewEditorCustomDocument<UserDataType = unknown> {
|
||||
/**
|
||||
* The associated viewType for this document.
|
||||
*/
|
||||
readonly viewType: string;
|
||||
|
||||
/**
|
||||
* The associated uri for this document.
|
||||
*/
|
||||
readonly uri: Uri;
|
||||
|
||||
/**
|
||||
* Event fired when there are no more references to the `WebviewEditorCustomDocument`.
|
||||
*/
|
||||
readonly onDidDispose: Event<void>;
|
||||
|
||||
/**
|
||||
* Custom data that an extension can store on the document.
|
||||
*/
|
||||
readonly userData: UserDataType;
|
||||
|
||||
// TODO: Should we expose edits here?
|
||||
// This could be helpful for tracking the life cycle of edits
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for webview editors that use a custom data model.
|
||||
*
|
||||
* Custom webview editors use [`WebviewEditorCustomDocument`](#WebviewEditorCustomDocument) as their data model.
|
||||
* This gives extensions full control over actions such as edit, save, and backup.
|
||||
*
|
||||
* You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text
|
||||
* based documents, use [`WebviewTextEditorProvider`](#WebviewTextEditorProvider) instead.
|
||||
*/
|
||||
export interface WebviewCustomEditorProvider {
|
||||
/**
|
||||
* Create the model for a given
|
||||
*
|
||||
* @param document Resource being resolved.
|
||||
*/
|
||||
provideWebviewCustomEditorDocument(resource: Uri): Thenable<WebviewEditorCustomDocument>;
|
||||
|
||||
/**
|
||||
* Resolve a webview editor for a given resource.
|
||||
*
|
||||
* To resolve a webview editor, a provider must fill in its initial html content and hook up all
|
||||
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
||||
*
|
||||
* @param resource Resource being resolved.
|
||||
* @param document Document for resource being resolved.
|
||||
* @param webview Webview being resolved. The provider should take ownership of this webview.
|
||||
*
|
||||
* @return Thenable indicating that the webview editor has been resolved.
|
||||
*/
|
||||
resolveWebviewEditor(
|
||||
resource: Uri,
|
||||
webview: WebviewPanel,
|
||||
): Thenable<void>;
|
||||
resolveWebviewCustomEditor(document: WebviewEditorCustomDocument, webview: WebviewPanel): Thenable<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for text based webview editors.
|
||||
*
|
||||
* Text based webview editors use a [`TextDocument`](#TextDocument) as their data model. This considerably simplifies
|
||||
* implementing a webview editor as it allows VS Code to handle many common operations such as
|
||||
* undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`.
|
||||
*
|
||||
* You should use text based webview editors when dealing with text based file formats, such as `xml` or `json`.
|
||||
* For binary files or more specialized use cases, see [WebviewCustomEditorProvider](#WebviewCustomEditorProvider).
|
||||
*/
|
||||
export interface WebviewTextEditorProvider {
|
||||
/**
|
||||
* Controls the editing functionality of a webview editor. This allows the webview editor to hook into standard
|
||||
* editor events such as `undo` or `save`.
|
||||
* Resolve a webview editor for a given resource.
|
||||
*
|
||||
* WebviewEditors that do not have `editingCapability` are considered to be readonly. Users can still interact
|
||||
* with readonly editors, but these editors will not integrate with VS Code's standard editor functionality.
|
||||
* To resolve a webview editor, the provider must fill in its initial html content and hook up all
|
||||
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
||||
*
|
||||
* @param document Resource being resolved.
|
||||
* @param webview Webview being resolved. The provider should take ownership of this webview.
|
||||
*
|
||||
* @return Thenable indicating that the webview editor has been resolved.
|
||||
*/
|
||||
readonly editingDelegate?: WebviewCustomEditorEditingDelegate<unknown>;
|
||||
resolveWebviewTextEditor(document: TextDocument, webview: WebviewPanel): Thenable<void>;
|
||||
}
|
||||
|
||||
namespace window {
|
||||
/**
|
||||
* Register a new provider for webview editors of a given type.
|
||||
* Register a new provider for text based webview editors.
|
||||
*
|
||||
* @param viewType Type of the webview editor provider.
|
||||
* @param provider Resolves webview editors.
|
||||
* @param options Content settings for a webview panels the provider is given.
|
||||
* @param viewType Type of the webview editor provider. This should match the `viewType` from the
|
||||
* `package.json` contributions
|
||||
* @param provider Provider that resolves webview editors.
|
||||
* @param webviewOptions Content settings for the webview panels that provider is given.
|
||||
*
|
||||
* @return Disposable that unregisters the `WebviewTextEditorProvider`.
|
||||
*/
|
||||
export function registerWebviewTextEditorProvider(
|
||||
viewType: string,
|
||||
provider: WebviewTextEditorProvider,
|
||||
webviewOptions?: WebviewPanelOptions,
|
||||
): Disposable;
|
||||
|
||||
/**
|
||||
* Register a new provider for custom webview editors.
|
||||
*
|
||||
* @param viewType Type of the webview editor provider. This should match the `viewType` from the
|
||||
* `package.json` contributions.
|
||||
* @param provider Provider that resolves webview editors.
|
||||
* @param webviewOptions Content settings for the webview panels that provider is given.
|
||||
*
|
||||
* @return Disposable that unregisters the `WebviewCustomEditorProvider`.
|
||||
*/
|
||||
export function registerWebviewCustomEditorProvider(
|
||||
viewType: string,
|
||||
provider: WebviewCustomEditorProvider,
|
||||
options?: WebviewPanelOptions,
|
||||
webviewOptions?: WebviewPanelOptions,
|
||||
): Disposable;
|
||||
|
||||
/**
|
||||
* Create a new `WebviewEditorCustomDocument`.
|
||||
*
|
||||
* Note that this method only creates a custom document object. To have it be registered with VS Code, you
|
||||
* must return the document from `WebviewCustomEditorProvider.provideWebviewCustomEditorDocument`.
|
||||
*
|
||||
* @param viewType Type of the webview editor provider. This should match the `viewType` from the
|
||||
* `package.json` contributions.
|
||||
* @param uri The document's resource.
|
||||
* @param userData Custom data attached to the document.
|
||||
* @param capabilities Controls the editing functionality of a webview editor. This allows the webview
|
||||
* editor to hook into standard editor events such as `undo` or `save`.
|
||||
*
|
||||
* WebviewEditors that do not have `editingCapability` are considered to be readonly. Users can still interact
|
||||
* with readonly editors, but these editors will not integrate with VS Code's standard editor functionality.
|
||||
*/
|
||||
export function createWebviewEditorCustomDocument<UserDataType>(
|
||||
viewType: string,
|
||||
uri: Uri,
|
||||
userData: UserDataType,
|
||||
capabilities: WebviewCustomEditorCapabilities
|
||||
): WebviewEditorCustomDocument<UserDataType>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -19,7 +19,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import * as callh from 'vs/workbench/contrib/callHierarchy/browser/callHierarchy';
|
||||
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { decodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokens';
|
||||
|
||||
@@ -273,7 +273,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
|
||||
// --- quick fix
|
||||
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto): void {
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string): void {
|
||||
this._registrations.set(handle, modes.CodeActionProviderRegistry.register(selector, <modes.CodeActionProvider>{
|
||||
provideCodeActions: async (model: ITextModel, rangeOrSelection: EditorRange | Selection, context: modes.CodeActionContext, token: CancellationToken): Promise<modes.CodeActionList | undefined> => {
|
||||
const listDto = await this._proxy.$provideCodeActions(handle, model.uri, rangeOrSelection, context, token);
|
||||
@@ -290,7 +290,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
};
|
||||
},
|
||||
providedCodeActionKinds: metadata.providedKinds,
|
||||
documentation: metadata.documentation
|
||||
documentation: metadata.documentation,
|
||||
displayName
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
public $executeTask(value: TaskHandleDTO | TaskDTO): Promise<TaskExecutionDTO> {
|
||||
return new Promise<TaskExecutionDTO>((resolve, reject) => {
|
||||
if (TaskHandleDTO.is(value)) {
|
||||
const workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
|
||||
const workspaceFolder = typeof value.workspaceFolder === 'string' ? value.workspaceFolder : this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
|
||||
if (workspaceFolder) {
|
||||
this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task | undefined) => {
|
||||
if (!task) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/common/shared/editor';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||
import { CustomEditorInput, ModelType } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
|
||||
@@ -97,7 +97,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
private readonly _webviewInputs = new WebviewInputStore();
|
||||
private readonly _revivers = new Map<string, IDisposable>();
|
||||
private readonly _editorProviders = new Map<string, IDisposable>();
|
||||
private readonly _customEditorModels = new Map<ICustomEditorModel, { referenceCount: number }>();
|
||||
private readonly _customEditorModels = new Map<string, { referenceCount: number }>();
|
||||
|
||||
constructor(
|
||||
context: extHostProtocol.IExtHostContext,
|
||||
@@ -121,7 +121,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
// This should trigger the real reviver to be registered from the extension host side.
|
||||
this._register(_webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webview: WebviewInput) => {
|
||||
if (webview instanceof CustomFileEditorInput) {
|
||||
if (webview instanceof CustomEditorInput) {
|
||||
extensionService.activateByEvent(`onWebviewEditor:${webview.viewType}`);
|
||||
return false;
|
||||
}
|
||||
@@ -256,7 +256,20 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
this._revivers.delete(viewType);
|
||||
}
|
||||
|
||||
public $registerEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]): void {
|
||||
public $registerTextEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void {
|
||||
return this.registerEditorProvider(ModelType.Text, extensionData, viewType, options);
|
||||
}
|
||||
|
||||
public $registerCustomEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void {
|
||||
return this.registerEditorProvider(ModelType.Custom, extensionData, viewType, options);
|
||||
}
|
||||
|
||||
public registerEditorProvider(
|
||||
modelType: ModelType,
|
||||
extensionData: extHostProtocol.WebviewExtensionDescription,
|
||||
viewType: string,
|
||||
options: modes.IWebviewPanelOptions,
|
||||
): void {
|
||||
if (this._editorProviders.has(viewType)) {
|
||||
throw new Error(`Provider for ${viewType} already registered`);
|
||||
}
|
||||
@@ -265,21 +278,25 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
|
||||
this._editorProviders.set(viewType, this._webviewWorkbenchService.registerResolver({
|
||||
canResolve: (webviewInput) => {
|
||||
return webviewInput instanceof CustomFileEditorInput && webviewInput.viewType === viewType;
|
||||
return webviewInput instanceof CustomEditorInput && webviewInput.viewType === viewType;
|
||||
},
|
||||
resolveWebview: async (webviewInput: CustomFileEditorInput) => {
|
||||
resolveWebview: async (webviewInput: CustomEditorInput) => {
|
||||
const handle = webviewInput.id;
|
||||
this._webviewInputs.add(handle, webviewInput);
|
||||
this.hookupWebviewEventDelegate(handle, webviewInput);
|
||||
|
||||
webviewInput.webview.options = options;
|
||||
webviewInput.webview.extension = extension;
|
||||
webviewInput.modelType = modelType;
|
||||
|
||||
const resource = webviewInput.resource;
|
||||
|
||||
const model = await this.retainCustomEditorModel(webviewInput, resource, viewType, capabilities);
|
||||
webviewInput.onDisposeWebview(() => {
|
||||
this.releaseCustomEditorModel(model);
|
||||
});
|
||||
if (modelType === ModelType.Custom) {
|
||||
const model = await this.retainCustomEditorModel(webviewInput, resource, viewType);
|
||||
webviewInput.onDisposeWebview(() => {
|
||||
this.releaseCustomEditorModel(model);
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await this._proxy.$resolveWebviewEditor(
|
||||
@@ -311,33 +328,26 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
this._customEditorService.models.disposeAllModelsForView(viewType);
|
||||
}
|
||||
|
||||
private async retainCustomEditorModel(webviewInput: WebviewInput, resource: URI, viewType: string, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]) {
|
||||
private async retainCustomEditorModel(webviewInput: WebviewInput, resource: URI, viewType: string) {
|
||||
const model = await this._customEditorService.models.resolve(webviewInput.resource, webviewInput.viewType);
|
||||
|
||||
const existingEntry = this._customEditorModels.get(model);
|
||||
const key = viewType + resource.toString();
|
||||
const existingEntry = this._customEditorModels.get(key);
|
||||
if (existingEntry) {
|
||||
++existingEntry.referenceCount;
|
||||
// no need to hook up listeners again
|
||||
return model;
|
||||
}
|
||||
this._customEditorModels.set(key, { referenceCount: 1 });
|
||||
const { editable } = await this._proxy.$createWebviewCustomEditorDocument(resource, viewType);
|
||||
|
||||
this._customEditorModels.set(model, { referenceCount: 1 });
|
||||
|
||||
const capabilitiesSet = new Set(capabilities);
|
||||
const isEditable = capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable);
|
||||
if (isEditable) {
|
||||
model.onUndo(e => {
|
||||
this._proxy.$undoEdits(resource, viewType, e.edits);
|
||||
if (editable) {
|
||||
model.onUndo(() => {
|
||||
this._proxy.$undo(resource, viewType);
|
||||
});
|
||||
|
||||
model.onDisposeEdits(e => {
|
||||
this._proxy.$disposeEdits(e.edits);
|
||||
});
|
||||
|
||||
model.onApplyEdit(e => {
|
||||
if (e.trigger !== model) {
|
||||
this._proxy.$applyEdits(resource, viewType, e.edits);
|
||||
}
|
||||
model.onRedo(() => {
|
||||
this._proxy.$redo(resource, viewType);
|
||||
});
|
||||
|
||||
model.onWillSave(e => {
|
||||
@@ -347,7 +357,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
|
||||
// Save as should always be implemented even if the model is readonly
|
||||
model.onWillSaveAs(e => {
|
||||
if (isEditable) {
|
||||
if (editable) {
|
||||
e.waitUntil(this._proxy.$onSaveAs(e.resource.toJSON(), viewType, e.targetResource.toJSON()));
|
||||
} else {
|
||||
// Since the editor is readonly, just copy the file over
|
||||
@@ -355,36 +365,37 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
}
|
||||
});
|
||||
|
||||
if (capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.SupportsHotExit)) {
|
||||
model.onBackup(() => {
|
||||
return createCancelablePromise(token =>
|
||||
this._proxy.$backup(model.resource.toJSON(), viewType, token));
|
||||
});
|
||||
}
|
||||
model.onBackup(() => {
|
||||
return createCancelablePromise(token =>
|
||||
this._proxy.$backup(model.resource.toJSON(), viewType, token));
|
||||
});
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private async releaseCustomEditorModel(model: ICustomEditorModel) {
|
||||
const entry = this._customEditorModels.get(model);
|
||||
const key = model.viewType + model.resource;
|
||||
const entry = this._customEditorModels.get(key);
|
||||
if (!entry) {
|
||||
return;
|
||||
throw new Error('Model not found');
|
||||
}
|
||||
|
||||
--entry.referenceCount;
|
||||
if (entry.referenceCount <= 0) {
|
||||
this._proxy.$disposeWebviewCustomEditorDocument(model.resource, model.viewType);
|
||||
this._customEditorService.models.disposeModel(model);
|
||||
this._customEditorModels.delete(model);
|
||||
this._customEditorModels.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
public $onEdit(resource: UriComponents, viewType: string, editId: number): void {
|
||||
|
||||
|
||||
public $onDidChangeCustomDocumentState(resource: UriComponents, viewType: string, state: { dirty: boolean }) {
|
||||
const model = this._customEditorService.models.get(URI.revive(resource), viewType);
|
||||
if (!model) {
|
||||
throw new Error('Could not find model for webview editor');
|
||||
}
|
||||
|
||||
model.pushEdit(editId, model);
|
||||
model.setDirty(state.dirty);
|
||||
}
|
||||
|
||||
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewPanelHandle, input: WebviewInput) {
|
||||
|
||||
@@ -114,7 +114,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, accessor.get(IExtHostOutputService));
|
||||
|
||||
// manually create and register addressable instances
|
||||
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment, extHostWorkspace, extHostLogService));
|
||||
const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol));
|
||||
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
|
||||
@@ -135,6 +134,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
|
||||
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
|
||||
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));
|
||||
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.environment, extHostWorkspace, extHostLogService, extHostApiDeprecation, extHostDocuments));
|
||||
|
||||
// Check that no named customers are missing
|
||||
// {{SQL CARBON EDIT}} filter out the services we don't expose
|
||||
@@ -564,10 +564,18 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
|
||||
return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer);
|
||||
},
|
||||
registerWebviewTextEditorProvider: (viewType: string, provider: vscode.WebviewTextEditorProvider, options?: vscode.WebviewPanelOptions) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.registerWebviewTextEditorProvider(extension, viewType, provider, options);
|
||||
},
|
||||
registerWebviewCustomEditorProvider: (viewType: string, provider: vscode.WebviewCustomEditorProvider, options?: vscode.WebviewPanelOptions) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.registerWebviewCustomEditorProvider(extension, viewType, provider, options);
|
||||
},
|
||||
createWebviewEditorCustomDocument: <UserDataType>(viewType: string, resource: vscode.Uri, userData: UserDataType, capabilities: vscode.WebviewCustomEditorCapabilities) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.createWebviewEditorCustomDocument<UserDataType>(viewType, resource, userData, capabilities);
|
||||
},
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostDecorations.registerDecorationProvider(provider, extension.identifier);
|
||||
|
||||
@@ -51,6 +51,8 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
import { Timeline, TimelineChangeEvent, TimelineCursor, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { Dto } from 'vs/base/common/types';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
|
||||
@@ -363,7 +365,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$registerEvaluatableExpressionProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto): void;
|
||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string): void;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
|
||||
@@ -574,11 +576,6 @@ export interface WebviewExtensionDescription {
|
||||
readonly location: UriComponents;
|
||||
}
|
||||
|
||||
export enum WebviewEditorCapabilities {
|
||||
Editable,
|
||||
SupportsHotExit,
|
||||
}
|
||||
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$createWebviewPanel(extension: WebviewExtensionDescription, handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: modes.IWebviewPanelOptions & modes.IWebviewOptions): void;
|
||||
$disposeWebview(handle: WebviewPanelHandle): void;
|
||||
@@ -594,10 +591,11 @@ export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$registerSerializer(viewType: string): void;
|
||||
$unregisterSerializer(viewType: string): void;
|
||||
|
||||
$registerEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: readonly WebviewEditorCapabilities[]): void;
|
||||
$registerTextEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void;
|
||||
$registerCustomEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void;
|
||||
$unregisterEditorProvider(viewType: string): void;
|
||||
|
||||
$onEdit(resource: UriComponents, viewType: string, editId: number): void;
|
||||
$onDidChangeCustomDocumentState(resource: UriComponents, viewType: string, state: { dirty: boolean }): void;
|
||||
}
|
||||
|
||||
export interface WebviewPanelViewStateData {
|
||||
@@ -615,12 +613,14 @@ export interface ExtHostWebviewsShape {
|
||||
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise<void>;
|
||||
|
||||
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
|
||||
$resolveWebviewEditor(resource: UriComponents, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
$createWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise<{ editable: boolean }>;
|
||||
$disposeWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise<void>;
|
||||
|
||||
$undoEdits(resource: UriComponents, viewType: string, editIds: readonly number[]): void;
|
||||
$applyEdits(resource: UriComponents, viewType: string, editIds: readonly number[]): void;
|
||||
$disposeEdits(editIds: readonly number[]): void;
|
||||
|
||||
$undo(resource: UriComponents, viewType: string): void;
|
||||
$redo(resource: UriComponents, viewType: string): void;
|
||||
$revert(resource: UriComponents, viewType: string): void;
|
||||
$onSave(resource: UriComponents, viewType: string): Promise<void>;
|
||||
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
|
||||
|
||||
@@ -1194,16 +1194,7 @@ export interface ICodeLensDto {
|
||||
command?: ICommandDto;
|
||||
}
|
||||
|
||||
export interface ICallHierarchyItemDto {
|
||||
_sessionId: string;
|
||||
_itemId: string;
|
||||
kind: modes.SymbolKind;
|
||||
name: string;
|
||||
detail?: string;
|
||||
uri: UriComponents;
|
||||
range: IRange;
|
||||
selectionRange: IRange;
|
||||
}
|
||||
export type ICallHierarchyItemDto = Dto<CallHierarchyItem>;
|
||||
|
||||
export interface IIncomingCallDto {
|
||||
from: ICallHierarchyItemDto;
|
||||
|
||||
@@ -1617,7 +1617,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
kind: x.kind.value,
|
||||
command: this._commands.converter.toInternal(x.command, store),
|
||||
}))
|
||||
});
|
||||
}, ExtHostLanguageFeatures._extLabel(extension));
|
||||
store.add(this._createDisposable(handle));
|
||||
return store;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import * as Platform from 'vs/base/common/platform';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
import { USER_TASKS_GROUP_KEY } from 'vs/workbench/contrib/tasks/common/taskService';
|
||||
|
||||
export interface IExtHostTask extends ExtHostTaskShape {
|
||||
|
||||
@@ -192,9 +193,11 @@ export namespace CustomExecutionDTO {
|
||||
|
||||
export namespace TaskHandleDTO {
|
||||
export function from(value: types.Task): tasks.TaskHandleDTO {
|
||||
let folder: UriComponents | undefined;
|
||||
let folder: UriComponents | string;
|
||||
if (value.scope !== undefined && typeof value.scope !== 'number') {
|
||||
folder = value.scope.uri;
|
||||
} else if (value.scope !== undefined && typeof value.scope === 'number') {
|
||||
folder = USER_TASKS_GROUP_KEY;
|
||||
}
|
||||
return {
|
||||
id: value._id!,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user