don't leak proxies in editor land, also remove indentSize property which isn't API

This commit is contained in:
Johannes Rieken
2021-02-01 11:24:30 +01:00
parent 82c629eb3a
commit a60beb9d7a
8 changed files with 258 additions and 446 deletions
@@ -79,7 +79,6 @@ export class MainThreadTextEditorProperties {
return {
insertSpaces: modelOptions.insertSpaces,
tabSize: modelOptions.tabSize,
indentSize: modelOptions.indentSize,
cursorStyle: cursorStyle,
lineNumbers: lineNumbers
};
@@ -146,7 +145,6 @@ export class MainThreadTextEditorProperties {
}
return (
a.tabSize === b.tabSize
&& a.indentSize === b.indentSize
&& a.insertSpaces === b.insertSpaces
&& a.cursorStyle === b.cursorStyle
&& a.lineNumbers === b.lineNumbers
@@ -377,13 +375,6 @@ export class MainThreadTextEditor {
if (typeof newConfiguration.tabSize !== 'undefined') {
newOpts.tabSize = newConfiguration.tabSize;
}
if (typeof newConfiguration.indentSize !== 'undefined') {
if (newConfiguration.indentSize === 'tabSize') {
newOpts.indentSize = newOpts.tabSize || creationOpts.tabSize;
} else {
newOpts.indentSize = newConfiguration.indentSize;
}
}
this._model.updateOptions(newOpts);
}
@@ -262,7 +262,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerDiffInformationCommand: (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
checkProposedApiEnabled(extension);
return extHostCommands.registerCommand(true, id, async (...args: any[]): Promise<any> => {
const activeTextEditor = extHostEditors.getActiveTextEditor();
const activeTextEditor = extHostDocumentsAndEditors.activeEditor(true);
if (!activeTextEditor) {
extHostLogService.warn('Cannot execute ' + id + ' because there is no active text editor.');
return undefined;
@@ -237,7 +237,6 @@ export interface MainThreadDocumentsShape extends IDisposable {
export interface ITextEditorConfigurationUpdate {
tabSize?: number | 'auto';
indentSize?: number | 'tabSize';
insertSpaces?: boolean | 'auto';
cursorStyle?: TextEditorCursorStyle;
lineNumbers?: RenderLineNumbersType;
@@ -245,7 +244,6 @@ export interface ITextEditorConfigurationUpdate {
export interface IResolvedTextEditorConfiguration {
tabSize: number;
indentSize: number;
insertSpaces: boolean;
cursorStyle: TextEditorCursorStyle;
lineNumbers: RenderLineNumbersType;
@@ -44,8 +44,8 @@ export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
createWebviewEditorInset(editor: vscode.TextEditor, line: number, height: number, options: vscode.WebviewOptions | undefined, extension: IExtensionDescription): vscode.WebviewEditorInset {
let apiEditor: ExtHostTextEditor | undefined;
for (const candidate of this._editors.getVisibleTextEditors()) {
if (candidate === editor) {
for (const candidate of this._editors.getVisibleTextEditors(true)) {
if (candidate.value === editor) {
apiEditor = <ExtHostTextEditor>candidate;
break;
}
@@ -121,7 +121,7 @@ export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {
}
};
this._proxy.$createEditorInset(handle, apiEditor.id, apiEditor.document.uri, line + 1, height, options || {}, extension.identifier, extension.extensionLocation);
this._proxy.$createEditorInset(handle, apiEditor.id, apiEditor.value.document.uri, line + 1, height, options || {}, extension.identifier, extension.extensionLocation);
this._insets.set(handle, { editor, inset, onDidReceiveMessage });
return inset;
@@ -18,6 +18,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { ResourceMap } from 'vs/base/common/map';
import { Schemas } from 'vs/base/common/network';
import { Iterable } from 'vs/base/common/iterator';
import { Lazy } from 'vs/base/common/lazy';
class Reference<T> {
private _count = 0;
@@ -49,13 +50,13 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
private readonly _onDidAddDocuments = new Emitter<ExtHostDocumentData[]>();
private readonly _onDidRemoveDocuments = new Emitter<ExtHostDocumentData[]>();
private readonly _onDidChangeVisibleTextEditors = new Emitter<ExtHostTextEditor[]>();
private readonly _onDidChangeActiveTextEditor = new Emitter<ExtHostTextEditor | undefined>();
private readonly _onDidChangeVisibleTextEditors = new Emitter<vscode.TextEditor[]>();
private readonly _onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor | undefined>();
readonly onDidAddDocuments: Event<ExtHostDocumentData[]> = this._onDidAddDocuments.event;
readonly onDidRemoveDocuments: Event<ExtHostDocumentData[]> = this._onDidRemoveDocuments.event;
readonly onDidChangeVisibleTextEditors: Event<ExtHostTextEditor[]> = this._onDidChangeVisibleTextEditors.event;
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor | undefined> = this._onDidChangeActiveTextEditor.event;
readonly onDidChangeVisibleTextEditors: Event<vscode.TextEditor[]> = this._onDidChangeVisibleTextEditors.event;
readonly onDidChangeActiveTextEditor: Event<vscode.TextEditor | undefined> = this._onDidChangeActiveTextEditor.event;
constructor(
@IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
@@ -135,7 +136,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
data.id,
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
this._logService,
documentData,
new Lazy(() => documentData.document),
data.selections.map(typeConverters.Selection.to),
data.options,
data.visibleRanges.map(range => typeConverters.Range.to(range)),
@@ -162,7 +163,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
}
if (delta.removedEditors || delta.addedEditors) {
this._onDidChangeVisibleTextEditors.fire(this.allEditors());
this._onDidChangeVisibleTextEditors.fire(this.allEditors().map(editor => editor.value));
}
if (delta.newActiveEditor !== undefined) {
this._onDidChangeActiveTextEditor.fire(this.activeEditor());
@@ -181,11 +182,17 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
return this._editors.get(id);
}
activeEditor(): ExtHostTextEditor | undefined {
activeEditor(): vscode.TextEditor | undefined;
activeEditor(internal: true): ExtHostTextEditor | undefined;
activeEditor(internal?: true): vscode.TextEditor | ExtHostTextEditor | undefined {
if (!this._activeEditorId) {
return undefined;
}
const editor = this._editors.get(this._activeEditorId);
if (internal) {
return editor;
} else {
return this._editors.get(this._activeEditorId);
return editor?.value;
}
}
+193 -239
View File
@@ -10,11 +10,11 @@ import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { IRange } from 'vs/editor/common/core/range';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate, MainThreadTextEditorsShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNumbersStyle, TextEditorRevealType } from 'vs/workbench/api/common/extHostTypes';
import type * as vscode from 'vscode';
import { ILogService } from 'vs/platform/log/common/log';
import { Lazy } from 'vs/base/common/lazy';
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
@@ -134,36 +134,63 @@ export class TextEditorEdit {
}
}
export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
export class ExtHostTextEditorOptions {
private _proxy: MainThreadTextEditorsShape;
private _id: string;
private _logService: ILogService;
private _tabSize!: number;
private _indentSize!: number;
private _insertSpaces!: boolean;
private _cursorStyle!: TextEditorCursorStyle;
private _lineNumbers!: TextEditorLineNumbersStyle;
readonly value: vscode.TextEditorOptions;
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration, logService: ILogService) {
this._proxy = proxy;
this._id = id;
this._accept(source);
this._logService = logService;
const that = this;
this.value = {
get tabSize(): number | string {
return that._tabSize;
},
set tabSize(value: number | string) {
that._setTabSize(value);
},
get insertSpaces(): boolean | string {
return that._insertSpaces;
},
set insertSpaces(value: boolean | string) {
that._setInsertSpaces(value);
},
get cursorStyle(): TextEditorCursorStyle {
return that._cursorStyle;
},
set cursorStyle(value: TextEditorCursorStyle) {
that._setCursorStyle(value);
},
get lineNumbers(): TextEditorLineNumbersStyle {
return that._lineNumbers;
},
set lineNumbers(value: TextEditorLineNumbersStyle) {
that._setLineNumbers(value);
}
};
}
public _accept(source: IResolvedTextEditorConfiguration): void {
this._tabSize = source.tabSize;
this._indentSize = source.indentSize;
this._insertSpaces = source.insertSpaces;
this._cursorStyle = source.cursorStyle;
this._lineNumbers = TypeConverters.TextEditorLineNumbersStyle.to(source.lineNumbers);
}
public get tabSize(): number | string {
return this._tabSize;
}
// --- internal: tabSize
private _validateTabSize(value: number | string): number | 'auto' | null {
if (value === 'auto') {
@@ -183,7 +210,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
return null;
}
public set tabSize(value: number | string) {
private _setTabSize(value: number | string) {
const tabSize = this._validateTabSize(value);
if (tabSize === null) {
// ignore invalid call
@@ -202,50 +229,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}));
}
public get indentSize(): number | string {
return this._indentSize;
}
private _validateIndentSize(value: number | string): number | 'tabSize' | null {
if (value === 'tabSize') {
return 'tabSize';
}
if (typeof value === 'number') {
const r = Math.floor(value);
return (r > 0 ? r : null);
}
if (typeof value === 'string') {
const r = parseInt(value, 10);
if (isNaN(r)) {
return null;
}
return (r > 0 ? r : null);
}
return null;
}
public set indentSize(value: number | string) {
const indentSize = this._validateIndentSize(value);
if (indentSize === null) {
// ignore invalid call
return;
}
if (typeof indentSize === 'number') {
if (this._indentSize === indentSize) {
// nothing to do
return;
}
// reflect the new indentSize value immediately
this._indentSize = indentSize;
}
this._warnOnError(this._proxy.$trySetOptions(this._id, {
indentSize: indentSize
}));
}
public get insertSpaces(): boolean | string {
return this._insertSpaces;
}
// --- internal: insert spaces
private _validateInsertSpaces(value: boolean | string): boolean | 'auto' {
if (value === 'auto') {
@@ -254,7 +238,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
return (value === 'false' ? false : Boolean(value));
}
public set insertSpaces(value: boolean | string) {
private _setInsertSpaces(value: boolean | string) {
const insertSpaces = this._validateInsertSpaces(value);
if (typeof insertSpaces === 'boolean') {
if (this._insertSpaces === insertSpaces) {
@@ -269,11 +253,9 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}));
}
public get cursorStyle(): TextEditorCursorStyle {
return this._cursorStyle;
}
// --- internal: cursor style
public set cursorStyle(value: TextEditorCursorStyle) {
private _setCursorStyle(value: TextEditorCursorStyle) {
if (this._cursorStyle === value) {
// nothing to do
return;
@@ -284,11 +266,9 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}));
}
public get lineNumbers(): TextEditorLineNumbersStyle {
return this._lineNumbers;
}
// --- internal: line number
public set lineNumbers(value: TextEditorLineNumbersStyle) {
private _setLineNumbers(value: TextEditorLineNumbersStyle) {
if (this._lineNumbers === value) {
// nothing to do
return;
@@ -368,31 +348,170 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
}
}
export class ExtHostTextEditor implements vscode.TextEditor {
private readonly _documentData: ExtHostDocumentData;
export class ExtHostTextEditor {
private _selections: Selection[];
private _options: ExtHostTextEditorOptions;
private _visibleRanges: Range[];
private _viewColumn: vscode.ViewColumn | undefined;
private _disposed: boolean = false;
private _hasDecorationsForKey: { [key: string]: boolean; };
private _hasDecorationsForKey = new Set<string>();
readonly value: vscode.TextEditor;
constructor(
readonly id: string,
private readonly _proxy: MainThreadTextEditorsShape,
private readonly _logService: ILogService,
document: ExtHostDocumentData,
document: Lazy<vscode.TextDocument>,
selections: Selection[], options: IResolvedTextEditorConfiguration,
visibleRanges: Range[], viewColumn: vscode.ViewColumn | undefined
) {
this._documentData = document;
this._selections = selections;
this._options = new ExtHostTextEditorOptions(this._proxy, this.id, options, _logService);
this._visibleRanges = visibleRanges;
this._viewColumn = viewColumn;
this._hasDecorationsForKey = Object.create(null);
const that = this;
this.value = Object.freeze({
get document(): vscode.TextDocument {
return document.getValue();
},
set document(_value) {
throw readonly('document');
},
// --- selection
get selection(): Selection {
return that._selections && that._selections[0];
},
set selection(value: Selection) {
if (!(value instanceof Selection)) {
throw illegalArgument('selection');
}
that._selections = [value];
that._trySetSelection();
},
get selections(): Selection[] {
return that._selections;
},
set selections(value: Selection[]) {
if (!Array.isArray(value) || value.some(a => !(a instanceof Selection))) {
throw illegalArgument('selections');
}
that._selections = value;
that._trySetSelection();
},
// --- visible ranges
get visibleRanges(): Range[] {
return that._visibleRanges;
},
set visibleRanges(_value: Range[]) {
throw readonly('visibleRanges');
},
// --- options
get options(): vscode.TextEditorOptions {
return that._options.value;
},
set options(value: vscode.TextEditorOptions) {
if (!that._disposed) {
that._options.assign(value);
}
},
// --- view column
get viewColumn(): vscode.ViewColumn | undefined {
return that._viewColumn;
},
set viewColumn(_value) {
throw readonly('viewColumn');
},
// --- edit
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (that._disposed) {
return Promise.reject(new Error('TextEditor#edit not possible on closed editors'));
}
const edit = new TextEditorEdit(document.getValue(), options);
callback(edit);
return that._applyEdit(edit);
},
// --- snippet edit
insertSnippet(snippet: SnippetString, where?: Position | readonly Position[] | Range | readonly Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (that._disposed) {
return Promise.reject(new Error('TextEditor#insertSnippet not possible on closed editors'));
}
let ranges: IRange[];
if (!where || (Array.isArray(where) && where.length === 0)) {
ranges = that._selections.map(range => TypeConverters.Range.from(range));
} else if (where instanceof Position) {
const { lineNumber, column } = TypeConverters.Position.from(where);
ranges = [{ startLineNumber: lineNumber, startColumn: column, endLineNumber: lineNumber, endColumn: column }];
} else if (where instanceof Range) {
ranges = [TypeConverters.Range.from(where)];
} else {
ranges = [];
for (const posOrRange of where) {
if (posOrRange instanceof Range) {
ranges.push(TypeConverters.Range.from(posOrRange));
} else {
const { lineNumber, column } = TypeConverters.Position.from(posOrRange);
ranges.push({ startLineNumber: lineNumber, startColumn: column, endLineNumber: lineNumber, endColumn: column });
}
}
}
return _proxy.$tryInsertSnippet(id, snippet.value, ranges, options);
},
setDecorations(decorationType: vscode.TextEditorDecorationType, ranges: Range[] | vscode.DecorationOptions[]): void {
const willBeEmpty = (ranges.length === 0);
if (willBeEmpty && !that._hasDecorationsForKey.has(decorationType.key)) {
// avoid no-op call to the renderer
return;
}
if (willBeEmpty) {
that._hasDecorationsForKey.delete(decorationType.key);
} else {
that._hasDecorationsForKey.add(decorationType.key);
}
that._runOnProxy(() => {
if (TypeConverters.isDecorationOptionsArr(ranges)) {
return _proxy.$trySetDecorations(
id,
decorationType.key,
TypeConverters.fromRangeOrRangeWithMessage(ranges)
);
} else {
const _ranges: number[] = new Array<number>(4 * ranges.length);
for (let i = 0, len = ranges.length; i < len; i++) {
const range = ranges[i];
_ranges[4 * i] = range.start.line + 1;
_ranges[4 * i + 1] = range.start.character + 1;
_ranges[4 * i + 2] = range.end.line + 1;
_ranges[4 * i + 3] = range.end.character + 1;
}
return _proxy.$trySetDecorationsFast(
id,
decorationType.key,
_ranges
);
}
});
},
revealRange(range: Range, revealType: vscode.TextEditorRevealType): void {
that._runOnProxy(() => _proxy.$tryRevealRange(
id,
TypeConverters.Range.from(range),
(revealType || TextEditorRevealType.Default)
));
},
show(column: vscode.ViewColumn) {
_proxy.$tryShowEditor(id, TypeConverters.ViewColumn.from(column));
},
hide() {
_proxy.$tryHideEditor(id);
}
});
}
dispose() {
@@ -400,164 +519,32 @@ export class ExtHostTextEditor implements vscode.TextEditor {
this._disposed = true;
}
show(column: vscode.ViewColumn) {
this._proxy.$tryShowEditor(this.id, TypeConverters.ViewColumn.from(column));
}
hide() {
this._proxy.$tryHideEditor(this.id);
}
// ---- the document
get document(): vscode.TextDocument {
return this._documentData.document;
}
set document(value) {
throw readonly('document');
}
// ---- options
get options(): vscode.TextEditorOptions {
return this._options;
}
set options(value: vscode.TextEditorOptions) {
if (!this._disposed) {
this._options.assign(value);
}
}
// --- incoming: extension host MUST accept what the renderer says
_acceptOptions(options: IResolvedTextEditorConfiguration): void {
ok(!this._disposed);
this._options._accept(options);
}
// ---- visible ranges
get visibleRanges(): Range[] {
return this._visibleRanges;
}
set visibleRanges(value: Range[]) {
throw readonly('visibleRanges');
}
_acceptVisibleRanges(value: Range[]): void {
ok(!this._disposed);
this._visibleRanges = value;
}
// ---- view column
get viewColumn(): vscode.ViewColumn | undefined {
return this._viewColumn;
}
set viewColumn(value) {
throw readonly('viewColumn');
}
_acceptViewColumn(value: vscode.ViewColumn) {
ok(!this._disposed);
this._viewColumn = value;
}
// ---- selections
get selection(): Selection {
return this._selections && this._selections[0];
}
set selection(value: Selection) {
if (!(value instanceof Selection)) {
throw illegalArgument('selection');
}
this._selections = [value];
this._trySetSelection();
}
get selections(): Selection[] {
return this._selections;
}
set selections(value: Selection[]) {
if (!Array.isArray(value) || value.some(a => !(a instanceof Selection))) {
throw illegalArgument('selections');
}
this._selections = value;
this._trySetSelection();
}
setDecorations(decorationType: vscode.TextEditorDecorationType, ranges: Range[] | vscode.DecorationOptions[]): void {
const willBeEmpty = (ranges.length === 0);
if (willBeEmpty && !this._hasDecorationsForKey[decorationType.key]) {
// avoid no-op call to the renderer
return;
}
if (willBeEmpty) {
delete this._hasDecorationsForKey[decorationType.key];
} else {
this._hasDecorationsForKey[decorationType.key] = true;
}
this._runOnProxy(
() => {
if (TypeConverters.isDecorationOptionsArr(ranges)) {
return this._proxy.$trySetDecorations(
this.id,
decorationType.key,
TypeConverters.fromRangeOrRangeWithMessage(ranges)
);
} else {
const _ranges: number[] = new Array<number>(4 * ranges.length);
for (let i = 0, len = ranges.length; i < len; i++) {
const range = ranges[i];
_ranges[4 * i] = range.start.line + 1;
_ranges[4 * i + 1] = range.start.character + 1;
_ranges[4 * i + 2] = range.end.line + 1;
_ranges[4 * i + 3] = range.end.character + 1;
}
return this._proxy.$trySetDecorationsFast(
this.id,
decorationType.key,
_ranges
);
}
}
);
}
revealRange(range: Range, revealType: vscode.TextEditorRevealType): void {
this._runOnProxy(
() => this._proxy.$tryRevealRange(
this.id,
TypeConverters.Range.from(range),
(revealType || TextEditorRevealType.Default)
)
);
}
private _trySetSelection(): Promise<vscode.TextEditor | null | undefined> {
const selection = this._selections.map(TypeConverters.Selection.from);
return this._runOnProxy(() => this._proxy.$trySetSelections(this.id, selection));
}
_acceptSelections(selections: Selection[]): void {
ok(!this._disposed);
this._selections = selections;
}
// ---- editing
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (this._disposed) {
return Promise.reject(new Error('TextEditor#edit not possible on closed editors'));
}
const edit = new TextEditorEdit(this._documentData.document, options);
callback(edit);
return this._applyEdit(edit);
private async _trySetSelection(): Promise<vscode.TextEditor | null | undefined> {
const selection = this._selections.map(TypeConverters.Selection.from);
await this._runOnProxy(() => this._proxy.$trySetSelections(this.id, selection));
return this.value;
}
private _applyEdit(editBuilder: TextEditorEdit): Promise<boolean> {
@@ -613,44 +600,12 @@ export class ExtHostTextEditor implements vscode.TextEditor {
undoStopAfter: editData.undoStopAfter
});
}
insertSnippet(snippet: SnippetString, where?: Position | readonly Position[] | Range | readonly Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (this._disposed) {
return Promise.reject(new Error('TextEditor#insertSnippet not possible on closed editors'));
}
let ranges: IRange[];
if (!where || (Array.isArray(where) && where.length === 0)) {
ranges = this._selections.map(range => TypeConverters.Range.from(range));
} else if (where instanceof Position) {
const { lineNumber, column } = TypeConverters.Position.from(where);
ranges = [{ startLineNumber: lineNumber, startColumn: column, endLineNumber: lineNumber, endColumn: column }];
} else if (where instanceof Range) {
ranges = [TypeConverters.Range.from(where)];
} else {
ranges = [];
for (const posOrRange of where) {
if (posOrRange instanceof Range) {
ranges.push(TypeConverters.Range.from(posOrRange));
} else {
const { lineNumber, column } = TypeConverters.Position.from(posOrRange);
ranges.push({ startLineNumber: lineNumber, startColumn: column, endLineNumber: lineNumber, endColumn: column });
}
}
}
return this._proxy.$tryInsertSnippet(this.id, snippet.value, ranges, options);
}
// ---- util
private _runOnProxy(callback: () => Promise<any>): Promise<ExtHostTextEditor | undefined | null> {
if (this._disposed) {
this._logService.warn('TextEditor is closed/disposed');
return Promise.resolve(undefined);
}
return callback().then(() => this, err => {
if (!(err instanceof Error && err.name === 'DISPOSED')) {
this._logService.warn(err);
@@ -659,4 +614,3 @@ export class ExtHostTextEditor implements vscode.TextEditor {
});
}
}
@@ -41,12 +41,17 @@ export class ExtHostEditors implements ExtHostEditorsShape {
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(e => this._onDidChangeActiveTextEditor.fire(e));
}
getActiveTextEditor(): ExtHostTextEditor | undefined {
getActiveTextEditor(): vscode.TextEditor | undefined {
return this._extHostDocumentsAndEditors.activeEditor();
}
getVisibleTextEditors(): vscode.TextEditor[] {
return this._extHostDocumentsAndEditors.allEditors();
getVisibleTextEditors(): vscode.TextEditor[];
getVisibleTextEditors(internal: true): ExtHostTextEditor[];
getVisibleTextEditors(internal?: true): ExtHostTextEditor[] | vscode.TextEditor[] {
const editors = this._extHostDocumentsAndEditors.allEditors();
return internal
? editors
: editors.map(editor => editor.value);
}
showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): Promise<vscode.TextEditor>;
@@ -75,7 +80,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
const editorId = await this._proxy.$tryShowTextDocument(document.uri, options);
const editor = editorId && this._extHostDocumentsAndEditors.getEditor(editorId);
if (editor) {
return editor;
return editor.value;
}
// we have no editor... having an id means that we had an editor
// on the main side and that it isn't the current editor anymore...
@@ -114,7 +119,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
// (2) fire change events
if (data.options) {
this._onDidChangeTextEditorOptions.fire({
textEditor: textEditor,
textEditor: textEditor.value,
options: { ...data.options, lineNumbers: TypeConverters.TextEditorLineNumbersStyle.to(data.options.lineNumbers) }
});
}
@@ -122,7 +127,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
const kind = TextEditorSelectionChangeKind.fromValue(data.selections.source);
const selections = data.selections.selections.map(TypeConverters.Selection.to);
this._onDidChangeTextEditorSelection.fire({
textEditor,
textEditor: textEditor.value,
selections,
kind
});
@@ -130,7 +135,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
if (data.visibleRanges) {
const visibleRanges = arrays.coalesce(data.visibleRanges.map(TypeConverters.Range.to));
this._onDidChangeTextEditorVisibleRanges.fire({
textEditor,
textEditor: textEditor.value,
visibleRanges
});
}
@@ -143,9 +148,9 @@ export class ExtHostEditors implements ExtHostEditorsShape {
throw new Error('Unknown text editor');
}
const viewColumn = TypeConverters.ViewColumn.to(data[id]);
if (textEditor.viewColumn !== viewColumn) {
if (textEditor.value.viewColumn !== viewColumn) {
textEditor._acceptViewColumn(viewColumn);
this._onDidChangeTextEditorViewColumn.fire({ textEditor, viewColumn });
this._onDidChangeTextEditorViewColumn.fire({ textEditor: textEditor.value, viewColumn });
}
}
}
@@ -11,6 +11,7 @@ import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { NullLogService } from 'vs/platform/log/common/log';
import { Lazy } from 'vs/base/common/lazy';
suite('ExtHostTextEditor', () => {
@@ -20,21 +21,21 @@ suite('ExtHostTextEditor', () => {
], '\n', 1, 'text', false);
setup(() => {
editor = new ExtHostTextEditor('fake', null!, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1);
editor = new ExtHostTextEditor('fake', null!, new NullLogService(), new Lazy(() => doc.document), [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4 }, [], 1);
});
test('disposed editor', () => {
assert.ok(editor.document);
assert.ok(editor.value.document);
editor._acceptViewColumn(3);
assert.strictEqual(3, editor.viewColumn);
assert.strictEqual(3, editor.value.viewColumn);
editor.dispose();
assert.throws(() => editor._acceptViewColumn(2));
assert.strictEqual(3, editor.viewColumn);
assert.strictEqual(3, editor.value.viewColumn);
assert.ok(editor.document);
assert.ok(editor.value.document);
assert.throws(() => editor._acceptOptions(null!));
assert.throws(() => editor._acceptSelections([]));
});
@@ -47,15 +48,15 @@ suite('ExtHostTextEditor', () => {
applyCount += 1;
return Promise.resolve(true);
}
}, new NullLogService(), doc, [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4, indentSize: 4 }, [], 1);
}, new NullLogService(), new Lazy(() => doc.document), [], { cursorStyle: 0, insertSpaces: true, lineNumbers: 1, tabSize: 4 }, [], 1);
await editor.edit(edit => { });
await editor.value.edit(edit => { });
assert.strictEqual(applyCount, 0);
await editor.edit(edit => { edit.setEndOfLine(1); });
await editor.value.edit(edit => { edit.setEndOfLine(1); });
assert.strictEqual(applyCount, 1);
await editor.edit(edit => { edit.delete(new Range(0, 0, 1, 1)); });
await editor.value.edit(edit => { edit.delete(new Range(0, 0, 1, 1)); });
assert.strictEqual(applyCount, 2);
});
});
@@ -89,7 +90,6 @@ suite('ExtHostTextEditorOptions', () => {
};
opts = new ExtHostTextEditorOptions(mockProxy, '1', {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -103,20 +103,18 @@ suite('ExtHostTextEditorOptions', () => {
function assertState(opts: ExtHostTextEditorOptions, expected: IResolvedTextEditorConfiguration): void {
let actual = {
tabSize: opts.tabSize,
indentSize: opts.indentSize,
insertSpaces: opts.insertSpaces,
cursorStyle: opts.cursorStyle,
lineNumbers: opts.lineNumbers
tabSize: opts.value.tabSize,
insertSpaces: opts.value.insertSpaces,
cursorStyle: opts.value.cursorStyle,
lineNumbers: opts.value.lineNumbers
};
assert.deepStrictEqual(actual, expected);
}
test('can set tabSize to the same value', () => {
opts.tabSize = 4;
opts.value.tabSize = 4;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -125,10 +123,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can change tabSize to positive integer', () => {
opts.tabSize = 1;
opts.value.tabSize = 1;
assertState(opts, {
tabSize: 1,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -137,10 +134,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can change tabSize to positive float', () => {
opts.tabSize = 2.3;
opts.value.tabSize = 2.3;
assertState(opts, {
tabSize: 2,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -149,10 +145,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can change tabSize to a string number', () => {
opts.tabSize = '2';
opts.value.tabSize = '2';
assertState(opts, {
tabSize: 2,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -161,10 +156,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('tabSize can request indentation detection', () => {
opts.tabSize = 'auto';
opts.value.tabSize = 'auto';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -173,10 +167,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('ignores invalid tabSize 1', () => {
opts.tabSize = null!;
opts.value.tabSize = null!;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -185,10 +178,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('ignores invalid tabSize 2', () => {
opts.tabSize = -5;
opts.value.tabSize = -5;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -197,10 +189,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('ignores invalid tabSize 3', () => {
opts.tabSize = 'hello';
opts.value.tabSize = 'hello';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -209,130 +200,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('ignores invalid tabSize 4', () => {
opts.tabSize = '-17';
opts.value.tabSize = '-17';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('can set indentSize to the same value', () => {
opts.indentSize = 4;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('can change indentSize to positive integer', () => {
opts.indentSize = 1;
assertState(opts, {
tabSize: 4,
indentSize: 1,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, [{ indentSize: 1 }]);
});
test('can change indentSize to positive float', () => {
opts.indentSize = 2.3;
assertState(opts, {
tabSize: 4,
indentSize: 2,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, [{ indentSize: 2 }]);
});
test('can change indentSize to a string number', () => {
opts.indentSize = '2';
assertState(opts, {
tabSize: 4,
indentSize: 2,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, [{ indentSize: 2 }]);
});
test('indentSize can request to use tabSize', () => {
opts.indentSize = 'tabSize';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, [{ indentSize: 'tabSize' }]);
});
test('indentSize cannot request indentation detection', () => {
opts.indentSize = 'auto';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('ignores invalid indentSize 1', () => {
opts.indentSize = null!;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('ignores invalid indentSize 2', () => {
opts.indentSize = -5;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('ignores invalid indentSize 3', () => {
opts.indentSize = 'hello';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
});
assert.deepStrictEqual(calls, []);
});
test('ignores invalid indentSize 4', () => {
opts.indentSize = '-17';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -341,10 +211,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set insertSpaces to the same value', () => {
opts.insertSpaces = false;
opts.value.insertSpaces = false;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -353,10 +222,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set insertSpaces to boolean', () => {
opts.insertSpaces = true;
opts.value.insertSpaces = true;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -365,10 +233,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set insertSpaces to false string', () => {
opts.insertSpaces = 'false';
opts.value.insertSpaces = 'false';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -377,10 +244,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set insertSpaces to truey', () => {
opts.insertSpaces = 'hello';
opts.value.insertSpaces = 'hello';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -389,10 +255,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('insertSpaces can request indentation detection', () => {
opts.insertSpaces = 'auto';
opts.value.insertSpaces = 'auto';
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -401,10 +266,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set cursorStyle to same value', () => {
opts.cursorStyle = TextEditorCursorStyle.Line;
opts.value.cursorStyle = TextEditorCursorStyle.Line;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -413,10 +277,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can change cursorStyle', () => {
opts.cursorStyle = TextEditorCursorStyle.Block;
opts.value.cursorStyle = TextEditorCursorStyle.Block;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Block,
lineNumbers: RenderLineNumbersType.On
@@ -425,10 +288,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can set lineNumbers to same value', () => {
opts.lineNumbers = TextEditorLineNumbersStyle.On;
opts.value.lineNumbers = TextEditorLineNumbersStyle.On;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -437,10 +299,9 @@ suite('ExtHostTextEditorOptions', () => {
});
test('can change lineNumbers', () => {
opts.lineNumbers = TextEditorLineNumbersStyle.Off;
opts.value.lineNumbers = TextEditorLineNumbersStyle.Off;
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.Off
@@ -457,7 +318,6 @@ suite('ExtHostTextEditorOptions', () => {
});
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -472,7 +332,6 @@ suite('ExtHostTextEditorOptions', () => {
});
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: true,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -487,7 +346,6 @@ suite('ExtHostTextEditorOptions', () => {
});
assertState(opts, {
tabSize: 3,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Line,
lineNumbers: RenderLineNumbersType.On
@@ -502,7 +360,6 @@ suite('ExtHostTextEditorOptions', () => {
});
assertState(opts, {
tabSize: 4,
indentSize: 4,
insertSpaces: false,
cursorStyle: TextEditorCursorStyle.Block,
lineNumbers: RenderLineNumbersType.Relative