diff --git a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts index dae16c51df6b6589ae780225b64635dadb111557..77c1841c5f6203dfc017f2149b60832f48fd620b 100644 --- a/src/vs/workbench/browser/parts/editor/diffEditorInput.ts +++ b/src/vs/workbench/browser/parts/editor/diffEditorInput.ts @@ -11,9 +11,7 @@ import {EventType} from 'vs/base/common/events'; import {EditorModel, IFileEditorInput, EditorInput, IInputStatus, BaseDiffEditorInput} from 'vs/workbench/common/editor'; import {BaseTextEditorModel} from 'vs/workbench/browser/parts/editor/textEditorModel'; import {DiffEditorModel} from 'vs/workbench/browser/parts/editor/diffEditorModel'; -import {TextDiffEditor} from 'vs/workbench/browser/parts/editor/textDiffEditor'; import {TextDiffEditorModel} from 'vs/workbench/browser/parts/editor/textDiffEditorModel'; -import {BinaryResourceDiffEditor} from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; /** * The base editor input for the diff editor. It is made up of two editor inputs, the original version @@ -27,12 +25,14 @@ export class DiffEditorInput extends BaseDiffEditorInput { private name: string; private description: string; private cachedModel: DiffEditorModel; + private forceOpenAsBinary: boolean; - constructor(name: string, description: string, originalInput: EditorInput, modifiedInput: EditorInput) { + constructor(name: string, description: string, originalInput: EditorInput, modifiedInput: EditorInput, forceOpenAsBinary?: boolean) { super(originalInput, modifiedInput); this.name = name; this.description = description; + this.forceOpenAsBinary = forceOpenAsBinary; this._toUnbind = []; @@ -129,9 +129,9 @@ export class DiffEditorInput extends BaseDiffEditorInput { public getPreferredEditorId(candidates: string[]): string { // Find the right diff editor for the given isBinary/isText state - let useBinaryEditor = this.isBinary(this.originalInput) || this.isBinary(this.modifiedInput); + let useBinaryEditor = this.forceOpenAsBinary || this.isBinary(this.originalInput) || this.isBinary(this.modifiedInput); - return !useBinaryEditor ? TextDiffEditor.ID : BinaryResourceDiffEditor.ID; + return !useBinaryEditor ? 'workbench.editors.textDiffEditor' : 'workbench.editors.binaryResourceDiffEditor'; } private isBinary(input: EditorInput): boolean { diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index d4e05c29fa09a3b484bc2aac8f81a6d9420ace0b..449888aa908969db3fa11564e94467aa6791ef57 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -10,6 +10,7 @@ import {Promise, TPromise} from 'vs/base/common/winjs.base'; import nls = require('vs/nls'); import {Builder} from 'vs/base/browser/builder'; import {Action, IAction} from 'vs/base/common/actions'; +import {onUnexpectedError} from 'vs/base/common/errors'; import types = require('vs/base/common/types'); import {IDiffEditor} from 'vs/editor/browser/editorBrowser'; import {IDiffEditorOptions, IEditorOptions} from 'vs/editor/common/editorCommon'; @@ -136,8 +137,8 @@ export class TextDiffEditor extends BaseTextEditor { return this.editorService.resolveEditorModel(input, true /* Reload */).then((resolvedModel: EditorModel) => { // Assert Model Instance - if (!(resolvedModel instanceof TextDiffEditorModel)) { - return TPromise.wrapError(nls.localize('cannotDiffBinary', "At least one of the resources to compare seems to be binary and this is currently not supported")); + if (!(resolvedModel instanceof TextDiffEditorModel) && this.openAsBinary(input, options)) { + return null; } // Assert that the current input is still the one we expect. This prevents a race condition when loading a diff takes long and another input was set meanwhile @@ -174,9 +175,9 @@ export class TextDiffEditor extends BaseTextEditor { diffEditor.updateOptions(this.getCodeEditorOptions()); }, (error) => { - // In case we tried to open a file and the response indicates that this is not a text file, bail out to the user. - if (this.isFileBinaryError(error)) { - return Promise.wrapError(nls.localize('cannotDiffBinary', "At least one of the resources to compare seems to be binary and this is currently not supported")); + // In case we tried to open a file and the response indicates that this is not a text file, fallback to binary diff. + if (this.isFileBinaryError(error) && this.openAsBinary(input, options)) { + return null; } // Otherwise make sure the error bubbles up @@ -184,6 +185,21 @@ export class TextDiffEditor extends BaseTextEditor { }); } + private openAsBinary(input: EditorInput, options: EditorOptions): boolean { + if (input instanceof DiffEditorInput) { + let originalInput = input.originalInput; + let modifiedInput = input.modifiedInput; + + let binaryDiffInput = new DiffEditorInput(input.getName(), input.getDescription(), originalInput, modifiedInput, true); + + this.editorService.openEditor(binaryDiffInput, options, this.position).done(null, onUnexpectedError); + + return true; + } + + return false; + } + protected getCodeEditorOptions(): IEditorOptions { let options: IDiffEditorOptions = super.getCodeEditorOptions(); diff --git a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts index 5ff6698b4efce3b2713a5c6e87f9566e6d333984..a9480382cff1ae2bc03ba5f4c25ac1aea9354c67 100644 --- a/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/parts/files/browser/editors/fileEditorInput.ts @@ -17,6 +17,7 @@ import assert = require('vs/base/common/assert'); import {EditorModel, IInputStatus, EncodingMode} from 'vs/workbench/common/editor'; import {IEditorRegistry, Extensions, EditorDescriptor} from 'vs/workbench/browser/parts/editor/baseEditor'; import {BinaryEditorModel} from 'vs/workbench/browser/parts/editor/binaryEditorModel'; +import {IFileOperationResult, FileOperationResult} from 'vs/platform/files/common/files'; import {FileEditorDescriptor} from 'vs/workbench/parts/files/browser/files'; import {BINARY_FILE_EDITOR_ID, FILE_EDITOR_INPUT_ID, FileEditorInput as CommonFileEditorInput} from 'vs/workbench/parts/files/common/files'; import {CACHE, TextFileEditorModel, State} from 'vs/workbench/parts/files/browser/editors/textFileEditorModel'; @@ -238,7 +239,7 @@ export class FileEditorInput extends CommonFileEditorInput { // Otherwise Create Model and Load else { - modelPromise = this.createModel().load(); + modelPromise = this.createAndLoadModel(); FileEditorInput.FILE_EDITOR_MODEL_LOADERS[this.resource.toString()] = modelPromise; } @@ -269,24 +270,27 @@ export class FileEditorInput extends CommonFileEditorInput { return -1; } - private createModel(): EditorModel { + private createAndLoadModel(): TPromise { let descriptor = (Registry.as(Extensions.Editors)).getEditor(this); if (!descriptor) { throw new Error('Unable to find an editor in the registry for this input.'); } - // Binary model if editor is binary editor - let model: EditorModel; - if (descriptor.getId() === BINARY_FILE_EDITOR_ID) { - model = new BinaryEditorModel(this.resource, this.getName()); - } + // Optimistically create a text model assuming that the file is not binary + let textModel = this.instantiationService.createInstance(TextFileEditorModel, this.resource, this.preferredEncoding); + return textModel.load().then(() => textModel, (error) => { - // Otherwise use text model - else { - model = this.instantiationService.createInstance(TextFileEditorModel, this.resource, this.preferredEncoding); - } + // In case of an error that indicates that the file is binary, just return with the binary editor model + if ((error).fileOperationResult === FileOperationResult.FILE_IS_BINARY) { + textModel.dispose(); - return model; + let binaryModel = new BinaryEditorModel(this.resource, this.getName()); + return binaryModel.load(); + } + + // Bubble any other error up + return Promise.wrapError(error); + }); } public dispose(force?: boolean): void {