<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { Schemas } from 'vs/base/common/network';
import { deepClone, deepFreeze, equals } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { NotebookRange } from 'vs/workbench/api/common/extHostTypes';
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as vscode from 'vscode';

class RawContentChangeEvent {


	constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) {

	}

	asApiEvent(): vscode.NotebookDocumentContentChange {
		return {
			range: new NotebookRange(this.start, this.start + this.deletedCount),
			addedCells: this.items.map(cell => cell.apiCell),
			removedCells: this.deletedItems,
		};
	}


	static asApiEvents(events: RawContentChangeEvent[]): readonly vscode.NotebookCellsChangeData[] {
		return events.map(event => {
			return {
				start: event.start,
				deletedCount: event.deletedCount,
				deletedItems: event.deletedItems,
				items: event.items.map(data => data.apiCell)
			};
		});
	}
}

export class ExtHostCell {

	static asModelAddData(notebook: vscode.NotebookDocument, cell: extHostProtocol.NotebookCellDto): IExtHostModelAddedData {
		return {
			EOL: cell.eol,
			lines: cell.source,
			languageId: cell.language,
			uri: cell.uri,
			isDirty: false,
			versionId: 1,
			notebook
		};
	}

	private _outputs: vscode.NotebookCellOutput[];
	private _metadata: Readonly<notebookCommon.NotebookCellMetadata>;
	private _previousResult: Readonly<vscode.NotebookCellExecutionSummary | undefined>;

	private _internalMetadata: notebookCommon.NotebookCellInternalMetadata;
	readonly handle: number;
	readonly uri: URI;
	readonly cellKind: notebookCommon.CellKind;

	private _apiCell: vscode.NotebookCell | undefined;
	private _mime: string | undefined;

	constructor(
		readonly notebook: ExtHostNotebookDocument,
		private readonly _extHostDocument: ExtHostDocumentsAndEditors,
		private readonly _cellData: extHostProtocol.NotebookCellDto,
	) {
		this.handle = _cellData.handle;
		this.uri = URI.revive(_cellData.uri);
		this.cellKind = _cellData.cellKind;
		this._outputs = _cellData.outputs.map(extHostTypeConverters.NotebookCellOutput.to);
		this._internalMetadata = _cellData.internalMetadata ?? {};
		this._metadata = Object.freeze(_cellData.metadata ?? {});
		this._previousResult = Object.freeze(extHostTypeConverters.NotebookCellExecutionSummary.to(_cellData.internalMetadata ?? {}));
	}

	get internalMetadata(): notebookCommon.NotebookCellInternalMetadata {
		return this._internalMetadata;
	}

	get apiCell(): vscode.NotebookCell {
		if (!this._apiCell) {
			const that = this;
			const data = this._extHostDocument.getDocument(this.uri);
			if (!data) {
				throw new Error(`MISSING extHostDocument for notebook cell: ${this.uri}`);
			}
			this._apiCell = Object.freeze<vscode.NotebookCell>({
				get index() { return that.notebook.getCellIndex(that); },
				notebook: that.notebook.apiNotebook,
				kind: extHostTypeConverters.NotebookCellKind.to(this._cellData.cellKind),
				document: data.document,
				get mime() { return that._mime; },
				set mime(value: string | undefined) { that._mime = value; },
				get outputs() { return that._outputs.slice(0); },
				get metadata() { return that._metadata; },
				get executionSummary() { return that._previousResult; }
			});
		}
		return this._apiCell;
	}

	setOutputs(newOutputs: extHostProtocol.NotebookOutputDto[]): void {
		this._outputs = newOutputs.map(extHostTypeConverters.NotebookCellOutput.to);
	}

	setOutputItems(outputId: string, append: boolean, newOutputItems: extHostProtocol.NotebookOutputItemDto[]) {
		const newItems = newOutputItems.map(extHostTypeConverters.NotebookCellOutputItem.to);

		// Use an index so we can overwrite internal properties (otherwise readonly)
		const index = this._outputs.findIndex(op => op.id === outputId);
		if (index >= 0) {
			const output = deepClone(this._outputs[index]);
			if (!append) {
				output.items.length = 0; // This crashes without a copy
			}
			output.items.push(...newItems);
			this._outputs[index] = output;
		}
	}

	setMetadata(newMetadata: notebookCommon.NotebookCellMetadata): void {<commit_msg>Update comment to indicate why readonly<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { Schemas } from 'vs/base/common/network';
import { deepClone, deepFreeze, equals } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { NotebookRange } from 'vs/workbench/api/common/extHostTypes';
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as vscode from 'vscode';

class RawContentChangeEvent {


	constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) {

	}

	asApiEvent(): vscode.NotebookDocumentContentChange {
		return {
			range: new NotebookRange(this.start, this.start + this.deletedCount),
			addedCells: this.items.map(cell => cell.apiCell),
			removedCells: this.deletedItems,
		};
	}


	static asApiEvents(events: RawContentChangeEvent[]): readonly vscode.NotebookCellsChangeData[] {
		return events.map(event => {
			return {
				start: event.start,
				deletedCount: event.deletedCount,
				deletedItems: event.deletedItems,
				items: event.items.map(data => data.apiCell)
			};
		});
	}
}

export class ExtHostCell {

	static asModelAddData(notebook: vscode.NotebookDocument, cell: extHostProtocol.NotebookCellDto): IExtHostModelAddedData {
		return {
			EOL: cell.eol,
			lines: cell.source,
			languageId: cell.language,
			uri: cell.uri,
			isDirty: false,
			versionId: 1,
			notebook
		};
	}

	private _outputs: vscode.NotebookCellOutput[];
	private _metadata: Readonly<notebookCommon.NotebookCellMetadata>;
	private _previousResult: Readonly<vscode.NotebookCellExecutionSummary | undefined>;

	private _internalMetadata: notebookCommon.NotebookCellInternalMetadata;
	readonly handle: number;
	readonly uri: URI;
	readonly cellKind: notebookCommon.CellKind;

	private _apiCell: vscode.NotebookCell | undefined;
	private _mime: string | undefined;

	constructor(
		readonly notebook: ExtHostNotebookDocument,
		private readonly _extHostDocument: ExtHostDocumentsAndEditors,
		private readonly _cellData: extHostProtocol.NotebookCellDto,
	) {
		this.handle = _cellData.handle;
		this.uri = URI.revive(_cellData.uri);
		this.cellKind = _cellData.cellKind;
		this._outputs = _cellData.outputs.map(extHostTypeConverters.NotebookCellOutput.to);
		this._internalMetadata = _cellData.internalMetadata ?? {};
		this._metadata = Object.freeze(_cellData.metadata ?? {});
		this._previousResult = Object.freeze(extHostTypeConverters.NotebookCellExecutionSummary.to(_cellData.internalMetadata ?? {}));
	}

	get internalMetadata(): notebookCommon.NotebookCellInternalMetadata {
		return this._internalMetadata;
	}

	get apiCell(): vscode.NotebookCell {
		if (!this._apiCell) {
			const that = this;
			const data = this._extHostDocument.getDocument(this.uri);
			if (!data) {
				throw new Error(`MISSING extHostDocument for notebook cell: ${this.uri}`);
			}
			this._apiCell = Object.freeze<vscode.NotebookCell>({
				get index() { return that.notebook.getCellIndex(that); },
				notebook: that.notebook.apiNotebook,
				kind: extHostTypeConverters.NotebookCellKind.to(this._cellData.cellKind),
				document: data.document,
				get mime() { return that._mime; },
				set mime(value: string | undefined) { that._mime = value; },
				get outputs() { return that._outputs.slice(0); },
				get metadata() { return that._metadata; },
				get executionSummary() { return that._previousResult; }
			});
		}
		return this._apiCell;
	}

	setOutputs(newOutputs: extHostProtocol.NotebookOutputDto[]): void {
		this._outputs = newOutputs.map(extHostTypeConverters.NotebookCellOutput.to);
	}

	setOutputItems(outputId: string, append: boolean, newOutputItems: extHostProtocol.NotebookOutputItemDto[]) {
		const newItems = newOutputItems.map(extHostTypeConverters.NotebookCellOutputItem.to);

		// Use an index so we can overwrite internal properties (otherwise readonly from freezing that occurs)
		const index = this._outputs.findIndex(op => op.id === outputId);
		if (index >= 0) {
			const output = deepClone(this._outputs[index]);
			if (!append) {
				output.items.length = 0; // This crashes without a copy
			}
			output.items.push(...newItems);
			this._outputs[index] = output;
		}
	}

	setMetadata(newMetadata: notebookCommon.NotebookCellMetadata): void {
{'fraction_non_alphanumeric': 0.14489263495886012, 'fraction_numerical': 0.0008027292795504716, 'mean_word_length': 4.069684638860631, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4888527', 'n_tokens_mistral': 3209, 'n_tokens_neox': 2931, 'n_words': 619}