From 92eea8df3285a8d6cba657e40b737ece7790ff07 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Dec 2023 09:17:53 +0100 Subject: [PATCH 1/2] working copy - enable file limits when resolving (#172129) --- src/vs/workbench/common/editor.ts | 4 ++- .../common/editor/resourceEditorInput.ts | 32 +++++++++++++++++-- .../common/editor/textResourceEditorInput.ts | 11 ++++--- .../files/browser/editors/fileEditorInput.ts | 30 ++--------------- .../mergeEditor/browser/mergeEditorInput.ts | 6 ++-- .../contrib/notebook/common/notebookCommon.ts | 6 ++++ .../notebook/common/notebookEditorInput.ts | 16 ++++++---- .../notebook/common/notebookEditorModel.ts | 8 +++-- .../notebookEditorModelResolverService.ts | 5 +-- .../notebookEditorModelResolverServiceImpl.ts | 13 ++++---- .../performance/browser/perfviewEditor.ts | 7 ++-- .../textfile/common/textFileEditorModel.ts | 3 +- .../common/untitledTextEditorInput.ts | 6 ++-- .../common/storedFileWorkingCopy.ts | 13 ++++++-- .../common/storedFileWorkingCopyManager.ts | 3 +- .../parts/editor/resourceEditorInput.test.ts | 6 ++-- 16 files changed, 105 insertions(+), 64 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2c0acaa442a16..ee6a8e501c87c 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -928,7 +928,7 @@ export interface IFileEditorInput extends EditorInput, IEncodingSupport, ILangua isResolved(): boolean; } -export interface IFileEditorInputOptions extends ITextEditorOptions { +export interface IFileLimitedEditorInputOptions extends IEditorOptions { /** * If provided, the size of the file will be checked against the limits @@ -937,6 +937,8 @@ export interface IFileEditorInputOptions extends ITextEditorOptions { readonly limits?: IFileReadLimits; } +export interface IFileEditorInputOptions extends ITextEditorOptions, IFileLimitedEditorInputOptions { } + export function createTooLargeFileError(group: IEditorGroup, input: EditorInput, options: IEditorOptions | undefined, message: string, preferencesService: IPreferencesService): Error { return createEditorOpenError(message, [ toAction({ diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index d1d5f8c567482..6f5af0deee3a1 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -3,14 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Verbosity, EditorInputWithPreferredResource, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { Verbosity, EditorInputWithPreferredResource, EditorInputCapabilities, IFileLimitedEditorInputOptions } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { URI } from 'vs/base/common/uri'; -import { IFileService } from 'vs/platform/files/common/files'; +import { ByteSize, IFileReadLimits, IFileService, getLargeFileConfirmationLimit } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; import { dirname, isEqual } from 'vs/base/common/resources'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { isConfigured } from 'vs/platform/configuration/common/configuration'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; /** * The base class for all editor inputs that open resources. @@ -43,7 +45,8 @@ export abstract class AbstractResourceEditorInput extends EditorInput implements preferredResource: URI | undefined, @ILabelService protected readonly labelService: ILabelService, @IFileService protected readonly fileService: IFileService, - @IFilesConfigurationService protected readonly filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService protected readonly filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService protected readonly textResourceConfigurationService: ITextResourceConfigurationService ) { super(); @@ -179,4 +182,27 @@ export abstract class AbstractResourceEditorInput extends EditorInput implements override isReadonly(): boolean | IMarkdownString { return this.filesConfigurationService.isReadonly(this.resource); } + + protected ensureLimits(options?: IFileLimitedEditorInputOptions): IFileReadLimits | undefined { + if (options?.limits) { + return options.limits; // respect passed in limits if any + } + + // We want to determine the large file configuration based on the best defaults + // for the resource but also respecting user settings. We only apply user settings + // if explicitly configured by the user. Otherwise we pick the best limit for the + // resource scheme. + + const defaultSizeLimit = getLargeFileConfirmationLimit(this.resource); + let configuredSizeLimit: number | undefined = undefined; + + const configuredSizeLimitMb = this.textResourceConfigurationService.inspect(this.resource, null, 'workbench.editorLargeFileConfirmation'); + if (isConfigured(configuredSizeLimitMb)) { + configuredSizeLimit = configuredSizeLimitMb.value * ByteSize.MB; // normalize to MB + } + + return { + size: configuredSizeLimit ?? defaultSizeLimit + }; + } } diff --git a/src/vs/workbench/common/editor/textResourceEditorInput.ts b/src/vs/workbench/common/editor/textResourceEditorInput.ts index 02217560ffd42..8416d2cc2493c 100644 --- a/src/vs/workbench/common/editor/textResourceEditorInput.ts +++ b/src/vs/workbench/common/editor/textResourceEditorInput.ts @@ -18,6 +18,7 @@ import { TextResourceEditorModel } from 'vs/workbench/common/editor/textResource import { IReference } from 'vs/base/common/lifecycle'; import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; /** * The base class for all editor inputs that open in text editors. @@ -31,9 +32,10 @@ export abstract class AbstractTextResourceEditorInput extends AbstractResourceEd @ITextFileService protected readonly textFileService: ITextFileService, @ILabelService labelService: ILabelService, @IFileService fileService: IFileService, - @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(resource, preferredResource, labelService, fileService, filesConfigurationService); + super(resource, preferredResource, labelService, fileService, filesConfigurationService, textResourceConfigurationService); } override save(group: GroupIdentifier, options?: ITextFileSaveOptions): Promise { @@ -104,9 +106,10 @@ export class TextResourceEditorInput extends AbstractTextResourceEditorInput imp @IEditorService editorService: IEditorService, @IFileService fileService: IFileService, @ILabelService labelService: ILabelService, - @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(resource, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService); + super(resource, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService, textResourceConfigurationService); } override getName(): string { diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 3f4b1910cf49a..dd25f4509bc5c 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -9,7 +9,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; -import { ByteSize, IFileReadLimits, IFileService, getLargeFileConfirmationLimit } from 'vs/platform/files/common/files'; +import { IFileService } from 'vs/platform/files/common/files'; import { ITextFileService, TextFileEditorModelState, TextFileResolveReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel, EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IReference, dispose, DisposableStore } from 'vs/base/common/lifecycle'; @@ -24,7 +24,6 @@ import { Schemas } from 'vs/base/common/network'; import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; -import { isConfigured } from 'vs/platform/configuration/common/configuration'; import { IMarkdownString } from 'vs/base/common/htmlContent'; const enum ForceOpenAs { @@ -99,9 +98,9 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, @IEditorService editorService: IEditorService, @IPathService private readonly pathService: IPathService, - @ITextResourceConfigurationService private readonly textResourceConfigurationService: ITextResourceConfigurationService + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(resource, preferredResource, editorService, textFileService, labelService, fileService, filesConfigurationService); + super(resource, preferredResource, editorService, textFileService, labelService, fileService, filesConfigurationService, textResourceConfigurationService); this.model = this.textFileService.files.get(resource); @@ -396,29 +395,6 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements } } - private ensureLimits(options?: IFileEditorInputOptions): IFileReadLimits | undefined { - if (options?.limits) { - return options.limits; // respect passed in limits if any - } - - // We want to determine the large file configuration based on the best defaults - // for the resource but also respecting user settings. We only apply user settings - // if explicitly configured by the user. Otherwise we pick the best limit for the - // resource scheme. - - const defaultSizeLimit = getLargeFileConfirmationLimit(this.resource); - let configuredSizeLimit: number | undefined = undefined; - - const configuredSizeLimitMb = this.textResourceConfigurationService.inspect(this.resource, null, 'workbench.editorLargeFileConfirmation'); - if (isConfigured(configuredSizeLimitMb)) { - configuredSizeLimit = configuredSizeLimitMb.value * ByteSize.MB; // normalize to MB - } - - return { - size: configuredSizeLimit ?? defaultSizeLimit - }; - } - private async doResolveAsBinary(): Promise { const model = this.instantiationService.createInstance(BinaryEditorModel, this.preferredResource, this.getName()); await model.resolve(); diff --git a/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts b/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts index e9f69bfa0ad77..3304f0b90b746 100644 --- a/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts +++ b/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorInput.ts @@ -8,6 +8,7 @@ import { autorun } from 'vs/base/common/observable'; import { isEqual } from 'vs/base/common/resources'; import { isDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; @@ -60,9 +61,10 @@ export class MergeEditorInput extends AbstractTextResourceEditorInput implements @ILabelService labelService: ILabelService, @IFileService fileService: IFileService, @IConfigurationService private readonly configurationService: IConfigurationService, - @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(result, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService); + super(result, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService, textResourceConfigurationService); } override dispose(): void { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 99230c87970c2..e88290fa0632f 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -30,6 +30,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; import { IWorkingCopyBackupMeta, IWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/workingCopy'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { IFileReadLimits } from 'vs/platform/files/common/files'; export const NOTEBOOK_EDITOR_ID = 'workbench.editor.notebook'; export const NOTEBOOK_DIFF_EDITOR_ID = 'workbench.editor.notebookTextDiffEditor'; @@ -787,6 +788,11 @@ export interface INotebookLoadOptions { * Go to disk bypassing any cache of the model if any. */ forceReadFromFile?: boolean; + /** + * If provided, the size of the file will be checked against the limits + * and an error will be thrown if any limit is exceeded. + */ + readonly limits?: IFileReadLimits; } export interface IResolvedNotebookEditorModel extends INotebookEditorModel { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index 1d6bba5410014..8a0f53e0b8cb3 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as glob from 'vs/base/common/glob'; -import { GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorInputCapabilities, Verbosity, IUntypedEditorInput } from 'vs/workbench/common/editor'; +import { GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorInputCapabilities, Verbosity, IUntypedEditorInput, IFileLimitedEditorInputOptions } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService'; import { URI } from 'vs/base/common/uri'; @@ -18,7 +18,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; -import { IEditorOptions, IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { onUnexpectedError } from 'vs/base/common/errors'; import { VSBuffer } from 'vs/base/common/buffer'; import { IWorkingCopyIdentifier } from 'vs/workbench/services/workingCopy/common/workingCopy'; @@ -29,6 +29,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { localize } from 'vs/nls'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; export interface NotebookEditorInputOptions { startDirty?: boolean; @@ -79,9 +80,10 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { @IFileService fileService: IFileService, @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, @IExtensionService extensionService: IExtensionService, - @IEditorService editorService: IEditorService + @IEditorService editorService: IEditorService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(resource, preferredResource, labelService, fileService, filesConfigurationService); + super(resource, preferredResource, labelService, fileService, filesConfigurationService, textResourceConfigurationService); this._defaultDirtyState = !!options.startDirty; // Automatically resolve this input when the "wanted" model comes to life via @@ -281,7 +283,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { } } - override async resolve(_options?: IEditorOptions, perf?: NotebookPerfMarks): Promise { + override async resolve(_options?: IFileLimitedEditorInputOptions, perf?: NotebookPerfMarks): Promise { if (!await this._notebookService.canResolve(this.viewType)) { return null; } @@ -293,7 +295,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { this._sideLoadedListener.dispose(); if (!this._editorModelReference) { - const ref = await this._notebookModelResolverService.resolve(this.resource, this.viewType); + const ref = await this._notebookModelResolverService.resolve(this.resource, this.viewType, this.ensureLimits(_options)); if (this._editorModelReference) { // Re-entrant, double resolve happened. Dispose the addition references and proceed // with the truth. @@ -313,7 +315,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { this._onDidChangeDirty.fire(); } } else { - this._editorModelReference.object.load(); + this._editorModelReference.object.load({ limits: this.ensureLimits(_options) }); } if (this.options._backupId) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index cb01185b511c8..4e7864c066723 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -136,7 +136,10 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE } this._workingCopy.onDidRevert(() => this._onDidRevertUntitled.fire()); } else { - this._workingCopy = await this._workingCopyManager.resolve(this.resource, options?.forceReadFromFile ? { reload: { async: false, force: true } } : undefined); + this._workingCopy = await this._workingCopyManager.resolve(this.resource, { + limits: options?.limits, + reload: options?.forceReadFromFile ? { async: false, force: true } : undefined + }); this._workingCopyListeners.add(this._workingCopy.onDidSave(e => this._onDidSave.fire(e))); this._workingCopyListeners.add(this._workingCopy.onDidChangeOrphaned(() => this._onDidChangeOrphaned.fire())); this._workingCopyListeners.add(this._workingCopy.onDidChangeReadonly(() => this._onDidChangeReadonly.fire())); @@ -152,7 +155,8 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE reload: { async: !options?.forceReadFromFile, force: options?.forceReadFromFile - } + }, + limits: options?.limits }); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverService.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverService.ts index e2d2a6c4fe449..3eff1eb5060bb 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverService.ts @@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IReference } from 'vs/base/common/lifecycle'; import { Event, IWaitUntil } from 'vs/base/common/event'; +import { IFileReadLimits } from 'vs/platform/files/common/files'; export const INotebookEditorModelResolverService = createDecorator('INotebookModelResolverService'); @@ -49,6 +50,6 @@ export interface INotebookEditorModelResolverService { isDirty(resource: URI): boolean; - resolve(resource: URI, viewType?: string): Promise>; - resolve(resource: IUntitledNotebookResource, viewType: string): Promise>; + resolve(resource: URI, viewType?: string, limits?: IFileReadLimits): Promise>; + resolve(resource: IUntitledNotebookResource, viewType: string, limits?: IFileReadLimits): Promise>; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts index 9da04357e1b8e..bbc69d31aa2cc 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts @@ -21,6 +21,7 @@ import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/noteb import { assertIsDefined } from 'vs/base/common/types'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IFileReadLimits } from 'vs/platform/files/common/files'; class NotebookModelReferenceCollection extends ReferenceCollection> { @@ -58,7 +59,7 @@ class NotebookModelReferenceCollection extends ReferenceCollection { + protected async createReferencedObject(key: string, viewType: string, hasAssociatedFilePath: boolean, limits?: IFileReadLimits): Promise { // Untrack as being disposed this.modelsToDispose.delete(key); @@ -77,7 +78,7 @@ class NotebookModelReferenceCollection extends ReferenceCollection>; - async resolve(resource: IUntitledNotebookResource, viewType: string): Promise>; - async resolve(arg0: URI | IUntitledNotebookResource, viewType?: string): Promise> { + async resolve(resource: URI, viewType?: string, limits?: IFileReadLimits): Promise>; + async resolve(resource: IUntitledNotebookResource, viewType: string, limits?: IFileReadLimits): Promise>; + async resolve(arg0: URI | IUntitledNotebookResource, viewType?: string, limits?: IFileReadLimits): Promise> { let resource: URI; let hasAssociatedFilePath = false; if (URI.isUri(arg0)) { @@ -235,7 +236,7 @@ export class NotebookModelResolverServiceImpl implements INotebookEditorModelRes } } - const reference = this._data.acquire(resource.toString(), viewType, hasAssociatedFilePath); + const reference = this._data.acquire(resource.toString(), viewType, hasAssociatedFilePath, limits); try { const model = await reference.object; return { diff --git a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts index e953502efac77..db3605eb6bd66 100644 --- a/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts +++ b/src/vs/workbench/contrib/performance/browser/perfviewEditor.ts @@ -27,6 +27,7 @@ import { isWeb } from 'vs/base/common/platform'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import * as perf from 'vs/base/common/performance'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; export class PerfviewContrib { @@ -59,7 +60,8 @@ export class PerfviewInput extends TextResourceEditorInput { @IEditorService editorService: IEditorService, @IFileService fileService: IFileService, @ILabelService labelService: ILabelService, - @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { super( PerfviewInput.Uri, @@ -72,7 +74,8 @@ export class PerfviewInput extends TextResourceEditorInput { editorService, fileService, labelService, - filesConfigurationService + filesConfigurationService, + textResourceConfigurationService ); } } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 4ae7f6692c6f8..e546ab6c566af 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -443,7 +443,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil try { const content = await this.textFileService.readStream(this.resource, { acceptTextOnly: !allowBinary, - etag, encoding: this.preferredEncoding, + etag, + encoding: this.preferredEncoding, limits: options?.limits }); diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts index 5780d63cce9e0..766081132c171 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts @@ -19,6 +19,7 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { dispose, IReference } from 'vs/base/common/lifecycle'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; /** * An editor input to be used for untitled text buffers. @@ -47,9 +48,10 @@ export class UntitledTextEditorInput extends AbstractTextResourceEditorInput imp @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @IPathService private readonly pathService: IPathService, @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, - @ITextModelService private readonly textModelService: ITextModelService + @ITextModelService private readonly textModelService: ITextModelService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(model.resource, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService); + super(model.resource, undefined, editorService, textFileService, labelService, fileService, filesConfigurationService, textResourceConfigurationService); this.registerModelListeners(model); } diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts index 7a00e3208d893..aee59bce62b47 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { ETAG_DISABLED, FileOperationError, FileOperationResult, IFileService, IFileStatWithMetadata, IFileStreamContent, IWriteFileOptions, NotModifiedSinceFileOperationError } from 'vs/platform/files/common/files'; +import { ETAG_DISABLED, FileOperationError, FileOperationResult, IFileReadLimits, IFileService, IFileStatWithMetadata, IFileStreamContent, IWriteFileOptions, NotModifiedSinceFileOperationError } from 'vs/platform/files/common/files'; import { ISaveOptions, IRevertOptions, SaveReason } from 'vs/workbench/common/editor'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopyBackup, IWorkingCopyBackupMeta, IWorkingCopySaveEvent, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopy'; @@ -262,6 +262,12 @@ export interface IStoredFileWorkingCopyResolveOptions { * Go to disk bypassing any cache of the stored file working copy if any. */ readonly forceReadFromFile?: boolean; + + /** + * If provided, the size of the file will be checked against the limits + * and an error will be thrown if any limit is exceeded. + */ + readonly limits?: IFileReadLimits; } /** @@ -571,7 +577,10 @@ export class StoredFileWorkingCopy extend // Resolve Content try { - const content = await this.fileService.readFileStream(this.resource, { etag }); + const content = await this.fileService.readFileStream(this.resource, { + etag, + limits: options?.limits + }); // Clear orphaned state when resolving was successful this.setOrphaned(false); diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts index cfdce4134e347..f76fdd404c7e6 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopyManager.ts @@ -475,7 +475,8 @@ export class StoredFileWorkingCopyManager const resolveOptions: IStoredFileWorkingCopyResolveOptions = { contents: options?.contents, - forceReadFromFile: options?.reload?.force + forceReadFromFile: options?.reload?.force, + limits: options?.limits }; // Working copy exists diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts index f44f395fac611..7481879807d31 100644 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts @@ -14,6 +14,7 @@ import { EditorInputCapabilities, Verbosity } from 'vs/workbench/common/editor'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; +import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; suite('ResourceEditorInput', () => { @@ -28,9 +29,10 @@ suite('ResourceEditorInput', () => { resource: URI, @ILabelService labelService: ILabelService, @IFileService fileService: IFileService, - @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService + @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, + @ITextResourceConfigurationService textResourceConfigurationService: ITextResourceConfigurationService ) { - super(resource, resource, labelService, fileService, filesConfigurationService); + super(resource, resource, labelService, fileService, filesConfigurationService, textResourceConfigurationService); } } From b5eaa6eeb58181f0905c757177c1624df25bfdcb Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 5 Dec 2023 15:20:00 +0100 Subject: [PATCH 2/2] . --- .../contrib/notebook/browser/notebookEditor.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 7bcd5a348d978..2370b8a297292 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -17,14 +17,14 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/tex import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; -import { IFileService } from 'vs/platform/files/common/files'; +import { ByteSize, FileOperationError, FileOperationResult, IFileService, TooLargeFileOperationError } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Selection } from 'vs/editor/common/core/selection'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { DEFAULT_EDITOR_ASSOCIATION, EditorPaneSelectionChangeReason, EditorPaneSelectionCompareResult, EditorResourceAccessor, IEditorMemento, IEditorOpenContext, IEditorPaneSelection, IEditorPaneSelectionChangeEvent, createEditorOpenError, isEditorOpenError } from 'vs/workbench/common/editor'; +import { DEFAULT_EDITOR_ASSOCIATION, EditorPaneSelectionChangeReason, EditorPaneSelectionCompareResult, EditorResourceAccessor, IEditorMemento, IEditorOpenContext, IEditorPaneSelection, IEditorPaneSelectionChangeEvent, createEditorOpenError, createTooLargeFileError, isEditorOpenError } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/controller/coreActions'; import { INotebookEditorOptions, INotebookEditorPane, INotebookEditorViewState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -46,6 +46,7 @@ import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/com import { streamToBuffer } from 'vs/base/common/buffer'; import { ILogService } from 'vs/platform/log/common/log'; import { INotebookEditorWorkerService } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerService'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState'; @@ -90,6 +91,7 @@ export class NotebookEditor extends EditorPane implements INotebookEditorPane { @IWorkingCopyBackupService private readonly _workingCopyBackupService: IWorkingCopyBackupService, @ILogService private readonly logService: ILogService, @INotebookEditorWorkerService private readonly _notebookEditorWorkerService: INotebookEditorWorkerService, + @IPreferencesService private readonly _preferencesService: IPreferencesService, ) { super(NotebookEditor.ID, telemetryService, themeService, storageService); this._editorMemento = this.getEditorMemento(_editorGroupService, configurationService, NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY); @@ -327,6 +329,18 @@ export class NotebookEditor extends EditorPane implements INotebookEditorPane { throw e; } + // Handle case where a file is too large to open without confirmation + if ((e).fileOperationResult === FileOperationResult.FILE_TOO_LARGE && this.group) { + let message: string; + if (e instanceof TooLargeFileOperationError) { + message = localize('notebookTooLargeForHeapErrorWithSize', "The notebook is not displayed in the notebook editor because it is very large ({0}).", ByteSize.formatSize(e.size)); + } else { + message = localize('notebookTooLargeForHeapErrorWithoutSize', "The notebook is not displayed in the notebook editor because it is very large."); + } + + throw createTooLargeFileError(this.group, input, options, message, this._preferencesService); + } + const error = createEditorOpenError(e instanceof Error ? e : new Error((e ? e.message : '')), [ toAction({ id: 'workbench.notebook.action.openInTextEditor', label: localize('notebookOpenInTextEditor', "Open in Text Editor"), run: async () => {