diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index b4de3177a8039b7ce6c24553679a30b3f7131884..13fe1340361b4c0f8c14b7a246cb0fc7cf2e684a 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -163,8 +163,14 @@ export interface IEditorControl extends ICompositeControl { } export interface IFileEditorInputFactory { + /** + * Creates new new editor input capable of showing files. + */ createFileEditorInput(resource: URI, encoding: string | undefined, mode: string | undefined, instantiationService: IInstantiationService): IFileEditorInput; + /** + * Check if the provided object is a file editor input. + */ isFileEditorInput(obj: unknown): obj is IFileEditorInput; } diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index 7416fd9418da37311c881793aeb5205d88b685ef..0fd8abac93b5e14716e30155fd5d4692de742311 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -58,6 +58,8 @@ import { TestTextResourcePropertiesService, TestContextService, TestWorkingCopyS import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; +import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentityService'; class TestEnvironmentService extends NativeWorkbenchEnvironmentService { @@ -117,6 +119,7 @@ suite('KeybindingsEditing', () => { fileService.registerProvider(Schemas.file, diskFileSystemProvider); fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); instantiationService.stub(IFileService, fileService); + instantiationService.stub(IUriIdentityService, new UriIdentityService(fileService)); instantiationService.stub(IWorkingCopyService, new TestWorkingCopyService()); instantiationService.stub(IWorkingCopyFileService, instantiationService.createInstance(WorkingCopyFileService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); diff --git a/src/vs/workbench/services/textfile/browser/textFileService.ts b/src/vs/workbench/services/textfile/browser/textFileService.ts index e4d7065f227a0bee7cbcf2c58ea219f4c17ac7c0..11bcba042b1b332dc878237f2f6e9ebe638d8de7 100644 --- a/src/vs/workbench/services/textfile/browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/browser/textFileService.ts @@ -34,6 +34,7 @@ import { suggestFilename } from 'vs/base/common/mime'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { isValidBasename } from 'vs/base/common/extpath'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; /** * The workbench file service implementation implements the raw file service spec and adds additional methods on top. @@ -69,7 +70,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex @ITextModelService private readonly textModelService: ITextModelService, @ICodeEditorService private readonly codeEditorService: ICodeEditorService, @IPathService private readonly pathService: IPathService, - @IWorkingCopyFileService private readonly workingCopyFileService: IWorkingCopyFileService + @IWorkingCopyFileService private readonly workingCopyFileService: IWorkingCopyFileService, + @IUriIdentityService private readonly uriIdentitiyService: IUriIdentityService ) { super(); @@ -226,6 +228,15 @@ export abstract class AbstractTextFileService extends Disposable implements ITex return this.save(source, options); } + // If the target is different but of same identity, we + // move the source to the target, knowing that the + // underlying file system cannot have both and then save. + if (this.fileService.canHandleResource(source) && this.uriIdentitiyService.extUri.isEqual(source, target)) { + await this.workingCopyFileService.move(source, target); + + return this.save(target, options); + } + // Do it return this.doSaveAs(source, target, options); } diff --git a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts index 0c2d8de960abe0ac483f348c2f45ade7e29b917f..48114750c9b5b144a9225e9934bd207e62e1d57f 100644 --- a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts @@ -40,6 +40,7 @@ import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { ILogService } from 'vs/platform/log/common/log'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; export class NativeTextFileService extends AbstractTextFileService { @@ -59,9 +60,10 @@ export class NativeTextFileService extends AbstractTextFileService { @ICodeEditorService codeEditorService: ICodeEditorService, @IPathService pathService: IPathService, @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IUriIdentityService uriIdentitiyService: IUriIdentityService ) { - super(fileService, untitledTextEditorService, lifecycleService, instantiationService, modelService, environmentService, dialogService, fileDialogService, textResourceConfigurationService, filesConfigurationService, textModelService, codeEditorService, pathService, workingCopyFileService); + super(fileService, untitledTextEditorService, lifecycleService, instantiationService, modelService, environmentService, dialogService, fileDialogService, textResourceConfigurationService, filesConfigurationService, textModelService, codeEditorService, pathService, workingCopyFileService, uriIdentitiyService); } private _encoding: EncodingOracle | undefined; diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 4ddd096d6cc5dfbaad9386c9401d586861386772..09a7cddb2cd90321bfd5353e5c9548ec9077fd4a 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -223,7 +223,8 @@ export class TestTextFileService extends BrowserTextFileService { @ITextModelService textModelService: ITextModelService, @ICodeEditorService codeEditorService: ICodeEditorService, @IPathService pathService: IPathService, - @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService + @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, + @IUriIdentityService uriIdentitiyService: IUriIdentityService ) { super( fileService, @@ -239,7 +240,8 @@ export class TestTextFileService extends BrowserTextFileService { textModelService, codeEditorService, pathService, - workingCopyFileService + workingCopyFileService, + uriIdentitiyService ); } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index f5f61e1272dbb6aafef1ae30e95e5bae32d60909..5b78cc1512648a1326a0b59e21d42f2cf1aa57ff 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -38,6 +38,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { INativeWindowConfiguration } from 'vs/platform/windows/node/window'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; export const TestWindowConfiguration: INativeWindowConfiguration = { windowId: 0, @@ -74,7 +75,8 @@ export class TestTextFileService extends NativeTextFileService { @ICodeEditorService codeEditorService: ICodeEditorService, @IPathService athService: IPathService, @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, - @ILogService logService: ILogService + @ILogService logService: ILogService, + @IUriIdentityService uriIdentitiyService: IUriIdentityService ) { super( fileService, @@ -92,7 +94,8 @@ export class TestTextFileService extends NativeTextFileService { codeEditorService, athService, workingCopyFileService, - logService + logService, + uriIdentitiyService ); }