Fixes #16573: Ensure textEditor.options always contains all properties

This commit is contained in:
Alex Dima
2016-12-07 14:14:50 +01:00
parent 887f9c180b
commit 19291ef2c1
5 changed files with 544 additions and 36 deletions

View File

@@ -12,9 +12,9 @@ import Event, { Emitter } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostDocuments, ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocuments';
import { Selection, Range, Position, EditorOptions, EndOfLine, TextEditorRevealType, TextEditorSelectionChangeKind } from './extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
import { IResolvedTextEditorConfiguration, ISelectionChangeEvent } from 'vs/workbench/api/node/mainThreadEditorsTracker';
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorSelectionChangeKind, TextEditorLineNumbersStyle } from './extHostTypes';
import { ISingleEditOperation, TextEditorCursorStyle } from 'vs/editor/common/editorCommon';
import { IResolvedTextEditorConfiguration, ISelectionChangeEvent, ITextEditorConfigurationUpdate } from 'vs/workbench/api/node/mainThreadEditorsTracker';
import * as TypeConverters from './extHostTypeConverters';
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextEditorAddData, ITextEditorPositionData } from './extHost.protocol';
import * as vscode from 'vscode';
@@ -293,6 +293,180 @@ function deprecated(name: string, message: string = 'Refer to the documentation
};
}
export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
private _proxy: MainThreadEditorsShape;
private _id: string;
private _tabSize: number;
private _insertSpaces: boolean;
private _cursorStyle: TextEditorCursorStyle;
private _lineNumbers: TextEditorLineNumbersStyle;
constructor(proxy: MainThreadEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
this._proxy = proxy;
this._id = id;
this._accept(source);
}
public _accept(source: IResolvedTextEditorConfiguration): void {
this._tabSize = source.tabSize;
this._insertSpaces = source.insertSpaces;
this._cursorStyle = source.cursorStyle;
this._lineNumbers = source.lineNumbers;
}
public get tabSize(): number | string {
return this._tabSize;
}
private _validateTabSize(value: number | string): number | 'auto' | null {
if (value === 'auto') {
return 'auto';
}
if (typeof value === 'number') {
let r = Math.floor(value);
return (r > 0 ? r : null);
}
if (typeof value === 'string') {
let r = parseInt(value, 10);
if (isNaN(r)) {
return null;
}
return (r > 0 ? r : null);
}
return null;
}
public set tabSize(value: number | string) {
let tabSize = this._validateTabSize(value);
if (tabSize === null) {
// ignore invalid call
return;
}
if (typeof tabSize === 'number') {
if (this._tabSize === tabSize) {
// nothing to do
return;
}
// reflect the new tabSize value immediately
this._tabSize = tabSize;
}
warnOnError(this._proxy.$trySetOptions(this._id, {
tabSize: tabSize
}));
}
public get insertSpaces(): boolean | string {
return this._insertSpaces;
}
private _validateInsertSpaces(value: boolean | string): boolean | 'auto' {
if (value === 'auto') {
return 'auto';
}
return (value === 'false' ? false : Boolean(value));
}
public set insertSpaces(value: boolean | string) {
let insertSpaces = this._validateInsertSpaces(value);
if (typeof insertSpaces === 'boolean') {
if (this._insertSpaces === insertSpaces) {
// nothing to do
return;
}
// reflect the new insertSpaces value immediately
this._insertSpaces = insertSpaces;
}
warnOnError(this._proxy.$trySetOptions(this._id, {
insertSpaces: insertSpaces
}));
}
public get cursorStyle(): TextEditorCursorStyle {
return this._cursorStyle;
}
public set cursorStyle(value: TextEditorCursorStyle) {
if (this._cursorStyle === value) {
// nothing to do
return;
}
this._cursorStyle = value;
warnOnError(this._proxy.$trySetOptions(this._id, {
cursorStyle: value
}));
}
public get lineNumbers(): TextEditorLineNumbersStyle {
return this._lineNumbers;
}
public set lineNumbers(value: TextEditorLineNumbersStyle) {
if (this._lineNumbers === value) {
// nothing to do
return;
}
this._lineNumbers = value;
warnOnError(this._proxy.$trySetOptions(this._id, {
lineNumbers: value
}));
}
public assign(newOptions: vscode.TextEditorOptions) {
let bulkConfigurationUpdate: ITextEditorConfigurationUpdate = {};
let hasUpdate = false;
if (typeof newOptions.tabSize !== 'undefined') {
let tabSize = this._validateTabSize(newOptions.tabSize);
if (tabSize === 'auto') {
hasUpdate = true;
bulkConfigurationUpdate.tabSize = tabSize;
} else if (typeof tabSize === 'number' && this._tabSize !== tabSize) {
// reflect the new tabSize value immediately
this._tabSize = tabSize;
hasUpdate = true;
bulkConfigurationUpdate.tabSize = tabSize;
}
}
if (typeof newOptions.insertSpaces !== 'undefined') {
let insertSpaces = this._validateInsertSpaces(newOptions.insertSpaces);
if (insertSpaces === 'auto') {
hasUpdate = true;
bulkConfigurationUpdate.insertSpaces = insertSpaces;
} else if (this._insertSpaces !== insertSpaces) {
// reflect the new insertSpaces value immediately
this._insertSpaces = insertSpaces;
hasUpdate = true;
bulkConfigurationUpdate.insertSpaces = insertSpaces;
}
}
if (typeof newOptions.cursorStyle !== 'undefined') {
if (this._cursorStyle !== newOptions.cursorStyle) {
this._cursorStyle = newOptions.cursorStyle;
hasUpdate = true;
bulkConfigurationUpdate.cursorStyle = newOptions.cursorStyle;
}
}
if (typeof newOptions.lineNumbers !== 'undefined') {
if (this._lineNumbers !== newOptions.lineNumbers) {
this._lineNumbers = newOptions.lineNumbers;
hasUpdate = true;
bulkConfigurationUpdate.lineNumbers = newOptions.lineNumbers;
}
}
if (hasUpdate) {
warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
}
}
}
class ExtHostTextEditor implements vscode.TextEditor {
private _proxy: MainThreadEditorsShape;
@@ -300,15 +474,15 @@ class ExtHostTextEditor implements vscode.TextEditor {
private _documentData: ExtHostDocumentData;
private _selections: Selection[];
private _options: vscode.TextEditorOptions;
private _options: ExtHostTextEditorOptions;
private _viewColumn: vscode.ViewColumn;
constructor(proxy: MainThreadEditorsShape, id: string, document: ExtHostDocumentData, selections: Selection[], options: EditorOptions, viewColumn: vscode.ViewColumn) {
constructor(proxy: MainThreadEditorsShape, id: string, document: ExtHostDocumentData, selections: Selection[], options: IResolvedTextEditorConfiguration, viewColumn: vscode.ViewColumn) {
this._proxy = proxy;
this._id = id;
this._documentData = document;
this._selections = selections;
this._options = options;
this._options = new ExtHostTextEditorOptions(this._proxy, this._id, options);
this._viewColumn = viewColumn;
}
@@ -341,14 +515,11 @@ class ExtHostTextEditor implements vscode.TextEditor {
}
set options(value: vscode.TextEditorOptions) {
this._options = value;
this._runOnProxy(() => {
return this._proxy.$trySetOptions(this._id, this._options);
}, true);
this._options.assign(value);
}
_acceptOptions(options: EditorOptions): void {
this._options = options;
_acceptOptions(options: IResolvedTextEditorConfiguration): void {
this._options._accept(options);
}
// ---- view column
@@ -460,3 +631,9 @@ class ExtHostTextEditor implements vscode.TextEditor {
});
}
}
function warnOnError(promise: TPromise<any>): void {
promise.then(null, (err) => {
console.warn(err);
});
}

View File

@@ -37,11 +37,6 @@ export class Disposable {
}
}
export interface EditorOptions {
tabSize: number | string;
insertSpaces: boolean | string;
}
export class Position {
static Min(...positions: Position[]): Position {

View File

@@ -17,8 +17,8 @@ import { Selection } from 'vs/editor/common/core/selection';
import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes';
export interface ITextEditorConfigurationUpdate {
tabSize?: number | string;
insertSpaces?: boolean | string;
tabSize?: number | 'auto';
insertSpaces?: boolean | 'auto';
cursorStyle?: EditorCommon.TextEditorCursorStyle;
lineNumbers?: TextEditorLineNumbersStyle;
}
@@ -209,18 +209,12 @@ export class MainThreadTextEditor {
let insertSpaces = creationOpts.insertSpaces;
let tabSize = creationOpts.tabSize;
if (newConfiguration.insertSpaces !== 'auto') {
if (typeof newConfiguration.insertSpaces !== 'undefined') {
insertSpaces = (newConfiguration.insertSpaces === 'false' ? false : Boolean(newConfiguration.insertSpaces));
}
if (newConfiguration.insertSpaces !== 'auto' && typeof newConfiguration.insertSpaces !== 'undefined') {
insertSpaces = newConfiguration.insertSpaces;
}
if (newConfiguration.tabSize !== 'auto') {
if (typeof newConfiguration.tabSize !== 'undefined') {
let parsedTabSize = parseInt(<string>newConfiguration.tabSize, 10);
if (!isNaN(parsedTabSize)) {
tabSize = parsedTabSize;
}
}
if (newConfiguration.tabSize !== 'auto' && typeof newConfiguration.tabSize !== 'undefined') {
tabSize = newConfiguration.tabSize;
}
this._model.detectIndentation(insertSpaces, tabSize);
@@ -229,13 +223,10 @@ export class MainThreadTextEditor {
let newOpts: EditorCommon.ITextModelUpdateOptions = {};
if (typeof newConfiguration.insertSpaces !== 'undefined') {
newOpts.insertSpaces = (newConfiguration.insertSpaces === 'false' ? false : Boolean(newConfiguration.insertSpaces));
newOpts.insertSpaces = newConfiguration.insertSpaces;
}
if (typeof newConfiguration.tabSize !== 'undefined') {
let parsedTabSize = parseInt(<string>newConfiguration.tabSize, 10);
if (!isNaN(parsedTabSize)) {
newOpts.tabSize = parsedTabSize;
}
newOpts.tabSize = newConfiguration.tabSize;
}
this._model.updateOptions(newOpts);
}