mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 01:58:53 +01:00
Merge branch 'joh/concat-doc'
This commit is contained in:
@@ -181,6 +181,10 @@ export class ExtHostDocumentData extends MirrorTextModel {
|
||||
throw new Error('Invalid argument');
|
||||
}
|
||||
|
||||
if (this._lines.length === 0) {
|
||||
return position.with(0, 0);
|
||||
}
|
||||
|
||||
let { line, character } = position;
|
||||
let hasChanged = false;
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
|
||||
import { ISplice } from 'vs/base/common/sequence';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape } 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, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
import { NotImplementedProxy } from 'vs/base/common/types';
|
||||
|
||||
interface IObservable<T> {
|
||||
proxy: T;
|
||||
@@ -40,39 +42,48 @@ function getObservable<T extends Object>(obj: T): IObservable<T> {
|
||||
|
||||
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
|
||||
|
||||
private originalSource: string[];
|
||||
// private originalSource: string[];
|
||||
private _outputs: any[];
|
||||
private _onDidChangeOutputs = new Emitter<ISplice<vscode.CellOutput>[]>();
|
||||
onDidChangeOutputs: Event<ISplice<vscode.CellOutput>[]> = this._onDidChangeOutputs.event;
|
||||
private _textDocument: vscode.TextDocument | undefined;
|
||||
private _initalVersion: number = -1;
|
||||
// private _textDocument: vscode.TextDocument | undefined;
|
||||
// private _initalVersion: number = -1;
|
||||
private _outputMapping = new Set<vscode.CellOutput>();
|
||||
private _metadata: vscode.NotebookCellMetadata;
|
||||
|
||||
private _metadataChangeListener: IDisposable;
|
||||
|
||||
private _documentData: ExtHostDocumentData;
|
||||
|
||||
get document(): vscode.TextDocument {
|
||||
return this._documentData.document;
|
||||
}
|
||||
|
||||
get source() {
|
||||
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
|
||||
return this._textDocument.getText();
|
||||
} else {
|
||||
return this.originalSource.join('\n');
|
||||
}
|
||||
// todo@jrieken remove this
|
||||
return this._documentData.getText();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private viewType: string,
|
||||
private documentUri: URI,
|
||||
private readonly viewType: string,
|
||||
private readonly documentUri: URI,
|
||||
readonly handle: number,
|
||||
readonly uri: URI,
|
||||
private _content: string,
|
||||
content: string,
|
||||
public readonly cellKind: CellKind,
|
||||
public language: string,
|
||||
outputs: any[],
|
||||
_metadata: vscode.NotebookCellMetadata | undefined,
|
||||
private _proxy: MainThreadNotebookShape
|
||||
private _proxy: MainThreadNotebookShape,
|
||||
) {
|
||||
super();
|
||||
this.originalSource = this._content.split(/\r|\n|\r\n/g);
|
||||
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;
|
||||
|
||||
const observableMetadata = getObservable(_metadata || {});
|
||||
@@ -125,26 +136,19 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
|
||||
return this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, this._metadata);
|
||||
}
|
||||
|
||||
getContent(): string {
|
||||
if (this._textDocument && this._initalVersion !== this._textDocument?.version) {
|
||||
return this._textDocument.getText();
|
||||
} else {
|
||||
return this.originalSource.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
attachTextDocument(document: vscode.TextDocument) {
|
||||
this._textDocument = document;
|
||||
this._initalVersion = this._textDocument.version;
|
||||
attachTextDocument(document: ExtHostDocumentData) {
|
||||
this._documentData = document;
|
||||
// this._initalVersion = this._documentData.version;
|
||||
}
|
||||
|
||||
detachTextDocument() {
|
||||
if (this._textDocument && this._textDocument.version !== this._initalVersion) {
|
||||
this.originalSource = this._textDocument.getText().split(/\r|\n|\r\n/g);
|
||||
}
|
||||
// no-op? keep stale document until new comes along?
|
||||
|
||||
this._textDocument = undefined;
|
||||
this._initalVersion = -1;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,10 +260,10 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
let cellDtos = splice[2];
|
||||
let newCells = cellDtos.map(cell => {
|
||||
const extCell = new ExtHostCell(this.viewType, this.uri, cell.handle, URI.revive(cell.uri), cell.source.join('\n'), cell.cellKind, cell.language, cell.outputs, cell.metadata, this._proxy);
|
||||
const document = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
|
||||
const documentData = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
|
||||
|
||||
if (document) {
|
||||
extCell.attachTextDocument(document.document);
|
||||
if (documentData) {
|
||||
extCell.attachTextDocument(documentData);
|
||||
}
|
||||
|
||||
if (!this._cellDisposableMapping.has(extCell.handle)) {
|
||||
@@ -366,15 +370,15 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
return this.cells.find(cell => cell.handle === cellHandle);
|
||||
}
|
||||
|
||||
attachCellTextDocument(textDocument: vscode.TextDocument) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.uri.toString());
|
||||
attachCellTextDocument(textDocument: ExtHostDocumentData) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
|
||||
if (cell) {
|
||||
cell.attachTextDocument(textDocument);
|
||||
}
|
||||
}
|
||||
|
||||
detachCellTextDocument(textDocument: vscode.TextDocument) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.uri.toString());
|
||||
detachCellTextDocument(textDocument: ExtHostDocumentData) {
|
||||
let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
|
||||
if (cell) {
|
||||
cell.detachTextDocument();
|
||||
}
|
||||
@@ -468,22 +472,22 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
) {
|
||||
super();
|
||||
this._register(this._documentsAndEditors.onDidAddDocuments(documents => {
|
||||
for (const { document: textDocument } of documents) {
|
||||
let data = CellUri.parse(textDocument.uri);
|
||||
for (const documentData of documents) {
|
||||
let data = CellUri.parse(documentData.document.uri);
|
||||
if (data) {
|
||||
if (this.document.uri.toString() === data.notebook.toString()) {
|
||||
document.attachCellTextDocument(textDocument);
|
||||
document.attachCellTextDocument(documentData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._documentsAndEditors.onDidRemoveDocuments(documents => {
|
||||
for (const { document: textDocument } of documents) {
|
||||
let data = CellUri.parse(textDocument.uri);
|
||||
for (const documentData of documents) {
|
||||
let data = CellUri.parse(documentData.document.uri);
|
||||
if (data) {
|
||||
if (this.document.uri.toString() === data.notebook.toString()) {
|
||||
document.detachCellTextDocument(textDocument);
|
||||
document.detachCellTextDocument(documentData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -593,6 +597,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any> }>();
|
||||
private readonly _notebookOutputRenderers = new Map<number, ExtHostNotebookOutputRenderer>();
|
||||
|
||||
private readonly _onDidChangeNotebookDocument = new Emitter<{ document: ExtHostNotebookDocument, changes: NotebookCellsSplice2[] }>();
|
||||
readonly onDidChangeNotebookDocument: Event<{ document: ExtHostNotebookDocument, changes: NotebookCellsSplice2[] }> = this._onDidChangeNotebookDocument.event;
|
||||
|
||||
private _outputDisplayOrder: INotebookDisplayOrder | undefined;
|
||||
|
||||
get outputDisplayOrder(): INotebookDisplayOrder | undefined {
|
||||
@@ -782,6 +790,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
if (editor) {
|
||||
editor.editor.document.accpetModelChanged(event);
|
||||
this._onDidChangeNotebookDocument.fire({
|
||||
document: editor.editor.document,
|
||||
changes: event.changes
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
152
src/vs/workbench/api/common/extHostNotebookConcatDocument.ts
Normal file
152
src/vs/workbench/api/common/extHostNotebookConcatDocument.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as vscode from 'vscode';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostNotebookDocument, ExtHostNotebookController, ExtHostCell } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { score } from 'vs/editor/common/modes/languageSelector';
|
||||
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
|
||||
export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextDocument {
|
||||
|
||||
private _disposables = new DisposableStore();
|
||||
|
||||
private _cells!: ExtHostCell[];
|
||||
private _cellLengths!: PrefixSumComputer;
|
||||
private _cellLines!: PrefixSumComputer;
|
||||
private _versionId = 0;
|
||||
|
||||
private readonly _onDidChange = new Emitter<this>();
|
||||
readonly onDidChange: Event<this> = this._onDidChange.event;
|
||||
|
||||
constructor(
|
||||
extHostNotebooks: ExtHostNotebookController,
|
||||
extHostDocuments: ExtHostDocuments,
|
||||
private readonly _notebook: ExtHostNotebookDocument,
|
||||
private readonly _selector: vscode.DocumentSelector | undefined,
|
||||
) {
|
||||
this._init();
|
||||
|
||||
this._disposables.add(extHostDocuments.onDidChangeDocument(e => {
|
||||
let cellIdx = this._cells.findIndex(cell => isEqual(cell.uri, e.document.uri));
|
||||
if (cellIdx >= 0) {
|
||||
this._cellLengths.changeValue(cellIdx, this._cells[cellIdx].document.getText().length + 1);
|
||||
this._cellLines.changeValue(cellIdx, this._cells[cellIdx].document.lineCount);
|
||||
this._versionId += 1;
|
||||
this._onDidChange.fire(this);
|
||||
}
|
||||
}));
|
||||
this._disposables.add(extHostNotebooks.onDidChangeNotebookDocument(e => {
|
||||
if (e.document === this._notebook) {
|
||||
this._init();
|
||||
this._versionId += 1;
|
||||
this._onDidChange.fire(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
private _init() {
|
||||
this._cells = [];
|
||||
const cellLengths: number[] = [];
|
||||
const cellLineCounts: number[] = [];
|
||||
for (let cell of this._notebook.cells) {
|
||||
if (cell.cellKind === CellKind.Code && (!this._selector || score(this._selector, cell.uri, cell.language, true))) {
|
||||
this._cells.push(cell);
|
||||
cellLengths.push(cell.document.getText().length + 1);
|
||||
cellLineCounts.push(cell.document.lineCount);
|
||||
}
|
||||
}
|
||||
this._cellLengths = new PrefixSumComputer(new Uint32Array(cellLengths));
|
||||
this._cellLines = new PrefixSumComputer(new Uint32Array(cellLineCounts));
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
|
||||
getText(range?: vscode.Range): string {
|
||||
if (!range) {
|
||||
let result = '';
|
||||
for (let cell of this._cells) {
|
||||
result += cell.document.getText() + '\n';
|
||||
}
|
||||
// remove last newline again
|
||||
result = result.slice(0, -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (range.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// get start and end locations and create substrings
|
||||
const start = this.locationAt(range.start);
|
||||
const end = this.locationAt(range.end);
|
||||
const startCell = this._cells.find(cell => isEqual(cell.uri, start.uri));
|
||||
const endCell = this._cells.find(cell => isEqual(cell.uri, end.uri));
|
||||
|
||||
if (!startCell || !endCell) {
|
||||
return '';
|
||||
} else if (startCell === endCell) {
|
||||
return startCell.document.getText(new types.Range(start.range.start, end.range.end));
|
||||
} else {
|
||||
let a = startCell.document.getText(new types.Range(start.range.start, new types.Position(startCell.document.lineCount, 0)));
|
||||
let b = endCell.document.getText(new types.Range(new types.Position(0, 0), end.range.end));
|
||||
return a + '\n' + b;
|
||||
}
|
||||
}
|
||||
|
||||
offsetAt(position: vscode.Position): number {
|
||||
const idx = this._cellLines.getIndexOf(position.line);
|
||||
const offset1 = this._cellLengths.getAccumulatedValue(idx.index - 1);
|
||||
const offset2 = this._cells[idx.index].document.offsetAt(position.with(idx.remainder));
|
||||
return offset1 + offset2;
|
||||
}
|
||||
|
||||
positionAt(locationOrOffset: vscode.Location | number): vscode.Position {
|
||||
if (typeof locationOrOffset === 'number') {
|
||||
const idx = this._cellLengths.getIndexOf(locationOrOffset);
|
||||
const lineCount = this._cellLines.getAccumulatedValue(idx.index - 1);
|
||||
return this._cells[idx.index].document.positionAt(idx.remainder).translate(lineCount);
|
||||
}
|
||||
|
||||
const idx = this._cells.findIndex(cell => isEqual(cell.uri, locationOrOffset.uri));
|
||||
if (idx >= 0) {
|
||||
let line = this._cellLines.getAccumulatedValue(idx - 1);
|
||||
return new types.Position(line + locationOrOffset.range.start.line, locationOrOffset.range.start.character);
|
||||
}
|
||||
// do better?
|
||||
// return undefined;
|
||||
return new types.Position(0, 0);
|
||||
}
|
||||
|
||||
locationAt(positionOrRange: vscode.Range | vscode.Position): types.Location {
|
||||
if (!types.Range.isRange(positionOrRange)) {
|
||||
positionOrRange = new types.Range(<types.Position>positionOrRange, <types.Position>positionOrRange);
|
||||
}
|
||||
|
||||
const startIdx = this._cellLines.getIndexOf(positionOrRange.start.line);
|
||||
let endIdx = startIdx;
|
||||
if (!positionOrRange.isEmpty) {
|
||||
endIdx = this._cellLines.getIndexOf(positionOrRange.end.line);
|
||||
}
|
||||
|
||||
let startPos = new types.Position(startIdx.remainder, positionOrRange.start.character);
|
||||
let endPos = new types.Position(endIdx.remainder, positionOrRange.end.character);
|
||||
let range = new types.Range(startPos, endPos);
|
||||
|
||||
const startCell = this._cells[startIdx.index];
|
||||
return new types.Location(startCell.uri, <types.Range>startCell.document.validateRange(range));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user