Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

working copy - enable file limits when resolving (#172129) #200009

Merged
merged 2 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/vs/workbench/common/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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({
Expand Down
32 changes: 29 additions & 3 deletions src/vs/workbench/common/editor/resourceEditorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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<number>(this.resource, null, 'workbench.editorLargeFileConfirmation');
if (isConfigured(configuredSizeLimitMb)) {
configuredSizeLimit = configuredSizeLimitMb.value * ByteSize.MB; // normalize to MB
}

return {
size: configuredSizeLimit ?? defaultSizeLimit
};
}
}
11 changes: 7 additions & 4 deletions src/vs/workbench/common/editor/textResourceEditorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<IUntypedEditorInput | undefined> {
Expand Down Expand Up @@ -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 {
Expand Down
30 changes: 3 additions & 27 deletions src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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<number>(this.resource, null, 'workbench.editorLargeFileConfirmation');
if (isConfigured(configuredSizeLimitMb)) {
configuredSizeLimit = configuredSizeLimitMb.value * ByteSize.MB; // normalize to MB
}

return {
size: configuredSizeLimit ?? defaultSizeLimit
};
}

private async doResolveAsBinary(): Promise<BinaryEditorModel> {
const model = this.instantiationService.createInstance(BinaryEditorModel, this.preferredResource, this.getName());
await model.resolve();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 {
Expand Down
18 changes: 16 additions & 2 deletions src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand Down Expand Up @@ -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<INotebookEditorViewState>(_editorGroupService, configurationService, NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY);
Expand Down Expand Up @@ -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 ((<FileOperationError>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 () => {
Expand Down
6 changes: 6 additions & 0 deletions src/vs/workbench/contrib/notebook/common/notebookCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 {
Expand Down
16 changes: 9 additions & 7 deletions src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -281,7 +283,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
}
}

override async resolve(_options?: IEditorOptions, perf?: NotebookPerfMarks): Promise<IResolvedNotebookEditorModel | null> {
override async resolve(_options?: IFileLimitedEditorInputOptions, perf?: NotebookPerfMarks): Promise<IResolvedNotebookEditorModel | null> {
if (!await this._notebookService.canResolve(this.viewType)) {
return null;
}
Expand All @@ -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.
Expand All @@ -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) {
Expand Down
Loading
Loading