提交 80a33109 编写于 作者: J Johannes Rieken

add eol to IMainCellDto, no more attach/dettach text document but use the...

add eol to IMainCellDto, no more attach/dettach text document but use the actual (sync'd) document or a fallback cell document
上级 f3fed74a
......@@ -168,6 +168,7 @@ class DocumentAndEditorState {
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......@@ -573,6 +574,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......@@ -613,6 +615,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......
......@@ -13,7 +13,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
import { CellKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput, IMainCellDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
......@@ -57,61 +57,82 @@ interface INotebookEventEmitter {
const addIdToOutput = (output: IRawOutput, id = generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich
? ({ ...output, outputId: id }) : output;
class DettachedCellDocumentData extends ExtHostDocumentData {
private static readonly _fakeProxy = new class extends NotImplementedProxy<MainThreadDocumentsShape>('document') {
$trySaveDocument() {
return Promise.reject('Cell-document cannot be saved');
}
};
constructor(cell: IMainCellDto) {
super(DettachedCellDocumentData._fakeProxy,
URI.revive(cell.uri),
cell.source,
cell.eol,
cell.language,
0,
false
);
}
}
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
// private originalSource: string[];
private _outputs: any[];
private _onDidChangeOutputs = new Emitter<ISplice<IProcessedOutput>[]>();
onDidChangeOutputs: Event<ISplice<IProcessedOutput>[]> = this._onDidChangeOutputs.event;
// private _textDocument: vscode.TextDocument | undefined;
// private _initalVersion: number = -1;
readonly onDidChangeOutputs: Event<ISplice<IProcessedOutput>[]> = this._onDidChangeOutputs.event;
private _outputs: any[];
private _outputMapping = new WeakMap<vscode.CellOutput, string | undefined /* output ID */>();
private _metadata: vscode.NotebookCellMetadata;
private _metadata: vscode.NotebookCellMetadata;
private _metadataChangeListener: IDisposable;
private _documentData: ExtHostDocumentData;
readonly handle: number;
readonly uri: URI;
readonly cellKind: CellKind;
get document(): vscode.TextDocument {
return this._documentData.document;
}
get notebook(): vscode.NotebookDocument {
return this._notebook;
}
// todo@jrieken this is a little fish because we have
// vscode.TextDocument for which we never fired an onDidOpen
// event and which doesn't appear in the list of documents.
// this will change once the "real" document comes along. We
// should come up with a better approach here...
readonly defaultDocument: DettachedCellDocumentData;
constructor(
private readonly _notebook: ExtHostNotebookDocument,
readonly handle: number,
readonly uri: URI,
content: string,
public readonly cellKind: CellKind,
public language: string,
outputs: any[],
_metadata: vscode.NotebookCellMetadata | undefined,
private _proxy: MainThreadNotebookShape,
readonly notebook: ExtHostNotebookDocument,
private _extHostDocument: ExtHostDocumentsAndEditors,
cell: IMainCellDto,
) {
super();
this._documentData = new ExtHostDocumentData(
new class extends NotImplementedProxy<MainThreadDocumentsShape>('document') { },
uri,
content.split(/\r|\n|\r\n/g), '\n',
language, 0, false
);
this._outputs = outputs;
this.handle = cell.handle;
this.uri = URI.revive(cell.uri);
this.cellKind = cell.cellKind;
this.defaultDocument = new DettachedCellDocumentData(cell);
this._outputs = cell.outputs;
for (const output of this._outputs) {
this._outputMapping.set(output, output.outputId);
delete output.outputId;
}
const observableMetadata = getObservable(_metadata || {});
const observableMetadata = getObservable(cell.metadata ?? {});
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
this._updateMetadata();
}));
}
get document(): vscode.TextDocument {
return this._extHostDocument.getDocument(this.uri)?.document ?? this.defaultDocument.document;
}
get language(): string {
return this.document.languageId;
}
get outputs() {
return this._outputs;
}
......@@ -156,29 +177,14 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
const observableMetadata = getObservable(newMetadata);
this._metadata = observableMetadata.proxy;
this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
this.updateMetadata();
this._updateMetadata();
}));
this.updateMetadata();
}
private updateMetadata(): Promise<void> {
return this._proxy.$updateNotebookCellMetadata(this._notebook.viewType, this._notebook.uri, this.handle, this._metadata);
this._updateMetadata();
}
attachTextDocument(document: ExtHostDocumentData) {
this._documentData = document;
// this._initalVersion = this._documentData.version;
}
detachTextDocument() {
// no-op? keep stale document until new comes along?
// if (this._textDocument && this._textDocument.version !== this._initalVersion) {
// this.originalSource = this._textDocument.getText().split(/\r|\n|\r\n/g);
// }
// this._textDocument = undefined;
// this._initalVersion = -1;
private _updateMetadata(): Promise<void> {
return this._proxy.$updateNotebookCellMetadata(this.notebook.viewType, this.notebook.uri, this.handle, this._metadata);
}
}
......@@ -367,12 +373,8 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
splices.reverse().forEach(splice => {
let cellDtos = splice[2];
let newCells = cellDtos.map(cell => {
const extCell = new ExtHostCell(this, cell.handle, URI.revive(cell.uri), cell.source.join('\n'), cell.cellKind, cell.language, cell.outputs, cell.metadata, this._proxy);
const documentData = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
if (documentData) {
extCell.attachTextDocument(documentData);
}
const extCell = new ExtHostCell(this._proxy, this, this._documentsAndEditors, cell);
if (!this._cellDisposableMapping.has(extCell.handle)) {
this._cellDisposableMapping.set(extCell.handle, new DisposableStore());
......@@ -454,7 +456,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
private $changeCellLanguage(index: number, language: string): void {
const cell = this.cells[index];
cell.language = language;
cell.defaultDocument._acceptLanguageId(language);
const event: vscode.NotebookCellLanguageChangeEvent = { document: this, cell, language };
this._emitter.emitCellLanguageChange(event);
}
......@@ -480,20 +482,6 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
getCell2(cellUri: UriComponents) {
return this.cells.find(cell => cell.uri.fragment === cellUri.fragment);
}
attachCellTextDocument(textDocument: ExtHostDocumentData) {
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
if (cell) {
cell.attachTextDocument(textDocument);
}
}
detachCellTextDocument(textDocument: ExtHostDocumentData) {
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
if (cell) {
cell.detachTextDocument();
}
}
}
export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellEdit {
......@@ -641,31 +629,8 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
private _proxy: MainThreadNotebookShape,
private _webComm: vscode.NotebookCommunication,
public document: ExtHostNotebookDocument,
private _documentsAndEditors: ExtHostDocumentsAndEditors
) {
super();
this._register(this._documentsAndEditors.onDidAddDocuments(documents => {
for (const documentData of documents) {
let data = CellUri.parse(documentData.document.uri);
if (data) {
if (this.document.uri.fsPath === data.notebook.fsPath) {
document.attachCellTextDocument(documentData);
}
}
}
}));
this._register(this._documentsAndEditors.onDidRemoveDocuments(documents => {
for (const documentData of documents) {
let data = CellUri.parse(documentData.document.uri);
if (data) {
if (this.document.uri.fsPath === data.notebook.fsPath) {
document.detachCellTextDocument(documentData);
}
}
}
}));
this._register(this._webComm.onDidReceiveMessage(e => {
this._onDidReceiveMessage.fire(e);
}));
......@@ -1275,8 +1240,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
revivedUri,
this._proxy,
webComm.contentProviderComm,
document,
this._documentsAndEditors
document
);
const cells = editor.document.cells;
......
......@@ -241,6 +241,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......@@ -334,6 +335,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......@@ -375,6 +377,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
handle: cell.handle,
uri: cell.uri,
source: cell.textBuffer.getLinesContent(),
eol: cell.textBuffer.getEOL(),
language: cell.language,
cellKind: cell.cellKind,
outputs: cell.outputs,
......
......@@ -295,6 +295,7 @@ export interface IMainCellDto {
handle: number;
uri: UriComponents,
source: string[];
eol: string;
language: string;
cellKind: CellKind;
outputs: IProcessedOutput[];
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { NullLogService } from 'vs/platform/log/common/log';
import { mock } from 'vs/base/test/common/mock';
import { MainThreadNotebookShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostNotebookDocument, ExtHostCell } from 'vs/workbench/api/common/extHostNotebook';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { URI } from 'vs/base/common/uri';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
suite('NotebookCell', function () {
let rpcProtocol: TestRPCProtocol;
let extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
const disposables = new DisposableStore();
const fakeNotebookProxy = new class extends mock<MainThreadNotebookShape>() { };
const fakeNotebook = new class extends mock<ExtHostNotebookDocument>() { };
setup(async function () {
disposables.clear();
rpcProtocol = new TestRPCProtocol();
extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol, new NullLogService());
});
test('Document is real', function () {
const dto = {
cellKind: CellKind.Code,
eol: '\n',
source: ['aaaa', 'bbbb', 'cccc'],
handle: 0,
language: 'fooLang',
outputs: [],
uri: URI.parse('test:/path')
};
const cell = new ExtHostCell(fakeNotebookProxy, fakeNotebook, extHostDocumentsAndEditors, dto);
assert.ok(cell.document);
assert.strictEqual(cell.document.version, 0);
assert.strictEqual(cell.document.languageId, dto.language);
assert.strictEqual(cell.document.uri.toString(), dto.uri.toString());
assert.strictEqual(cell.uri.toString(), dto.uri.toString());
});
test('Document is uses actual document when possible', function () {
const dto = {
cellKind: CellKind.Code,
eol: '\n',
source: ['aaaa', 'bbbb', 'cccc'],
handle: 0,
language: 'fooLang',
outputs: [],
uri: URI.parse('test:/path')
};
const cell = new ExtHostCell(fakeNotebookProxy, fakeNotebook, extHostDocumentsAndEditors, dto);
// this is the "default document" which is used when the real
// document isn't open
const documentNow = cell.document;
extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
addedDocuments: [{
isDirty: false,
versionId: 12,
modeId: dto.language,
uri: dto.uri,
lines: dto.source,
EOL: dto.eol
}]
});
// the real document
assert.ok(documentNow !== cell.document);
assert.strictEqual(cell.document.languageId, dto.language);
assert.strictEqual(cell.document.uri.toString(), dto.uri.toString());
assert.strictEqual(cell.uri.toString(), dto.uri.toString());
// back to "default document"
extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({ removedDocuments: [dto.uri] });
assert.ok(documentNow === cell.document);
});
test('Document can change language (1/2)', function () {
const dto = {
cellKind: CellKind.Code,
eol: '\n',
source: ['aaaa', 'bbbb', 'cccc'],
handle: 0,
language: 'fooLang',
outputs: [],
uri: URI.parse('test:/path')
};
const cell = new ExtHostCell(fakeNotebookProxy, fakeNotebook, extHostDocumentsAndEditors, dto);
assert.strictEqual(cell.document.languageId, dto.language);
cell.defaultDocument._acceptLanguageId('barLang');
assert.strictEqual(cell.document.languageId, 'barLang');
});
test('Document can change language (1/2)', function () {
const dto = {
cellKind: CellKind.Code,
eol: '\n',
source: ['aaaa', 'bbbb', 'cccc'],
handle: 0,
language: 'fooLang',
outputs: [],
uri: URI.parse('test:/path')
};
extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
addedDocuments: [{
isDirty: false,
versionId: 12,
modeId: dto.language,
uri: dto.uri,
lines: dto.source,
EOL: dto.eol
}]
});
const extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
const cell = new ExtHostCell(fakeNotebookProxy, fakeNotebook, extHostDocumentsAndEditors, dto);
// a real document already exists and therefore
// the "default document" doesn't count
assert.strictEqual(cell.document.languageId, dto.language);
cell.defaultDocument._acceptLanguageId('barLang');
assert.strictEqual(cell.document.languageId, dto.language);
extHostDocuments.$acceptModelModeChanged(dto.uri, dto.language, 'barLang');
assert.strictEqual(cell.document.languageId, 'barLang');
});
});
......@@ -57,6 +57,7 @@ suite('NotebookConcatDocument', function () {
handle: 0,
uri: CellUri.generate(notebookUri, 0),
source: ['### Heading'],
eol: '\n',
language: 'markdown',
cellKind: CellKind.Markdown,
outputs: [],
......@@ -123,6 +124,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: cellUri1,
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -130,6 +132,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: cellUri2,
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -155,6 +158,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -162,6 +166,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -194,6 +199,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -216,6 +222,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -257,6 +264,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -264,6 +272,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -320,6 +329,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['fooLang-document'],
eol: '\n',
language: 'fooLang',
cellKind: CellKind.Code,
outputs: [],
......@@ -327,6 +337,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['barLang-document'],
eol: '\n',
language: 'barLang',
cellKind: CellKind.Code,
outputs: [],
......@@ -348,6 +359,7 @@ suite('NotebookConcatDocument', function () {
handle: 3,
uri: CellUri.generate(notebook.uri, 3),
source: ['barLang-document2'],
eol: '\n',
language: 'barLang',
cellKind: CellKind.Code,
outputs: [],
......@@ -381,6 +393,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -388,6 +401,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -432,6 +446,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -439,6 +454,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -467,6 +483,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -474,6 +491,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -499,6 +517,7 @@ suite('NotebookConcatDocument', function () {
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......@@ -506,6 +525,7 @@ suite('NotebookConcatDocument', function () {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
cellKind: CellKind.Code,
outputs: [],
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册