diff --git a/src/vs/editor/test/common/model/textModelWithTokens.test.ts b/src/vs/editor/test/common/model/textModelWithTokens.test.ts index 99dc7b08963b5aa3113e64bf4ad414e4974af93b..61d95192b3d8103b6e56da8f02e8ae44bc1f2909 100644 --- a/src/vs/editor/test/common/model/textModelWithTokens.test.ts +++ b/src/vs/editor/test/common/model/textModelWithTokens.test.ts @@ -572,9 +572,10 @@ suite('TextModelWithTokens regression tests', () => { }); suite('TextModel.getLineIndentGuide', () => { - function assertIndentGuides(lines: [number, number, number, number, string][]): void { + function assertIndentGuides(lines: [number, number, number, number, string][], tabSize: number): void { let text = lines.map(l => l[4]).join('\n'); let model = TextModel.createFromString(text); + model.updateOptions({ tabSize: tabSize }); let actualIndents = model.getLinesIndentGuides(1, model.getLineCount()); @@ -589,13 +590,13 @@ suite('TextModel.getLineIndentGuide', () => { model.dispose(); } - test('getLineIndentGuide one level', () => { + test('getLineIndentGuide one level 2', () => { assertIndentGuides([ [0, 1, 1, 0, 'A'], [1, 2, 4, 1, ' A'], [1, 2, 4, 1, ' A'], [1, 2, 4, 1, ' A'], - ]); + ], 2); }); test('getLineIndentGuide two levels', () => { @@ -603,45 +604,45 @@ suite('TextModel.getLineIndentGuide', () => { [0, 1, 1, 0, 'A'], [1, 2, 5, 1, ' A'], [1, 2, 5, 1, ' A'], - [1, 2, 5, 1, ' A'], - [1, 2, 5, 1, ' A'], - ]); + [2, 4, 5, 2, ' A'], + [2, 4, 5, 2, ' A'], + ], 2); }); test('getLineIndentGuide three levels', () => { assertIndentGuides([ [0, 1, 1, 0, 'A'], [1, 2, 4, 1, ' A'], - [1, 2, 4, 1, ' A'], - [2, 4, 4, 2, ' A'], + [2, 3, 4, 2, ' A'], + [3, 4, 4, 3, ' A'], [0, 5, 5, 0, 'A'], - ]); + ], 2); }); test('getLineIndentGuide decreasing indent', () => { assertIndentGuides([ - [1, 1, 2, 1, ' A'], + [2, 1, 1, 2, ' A'], [1, 1, 2, 1, ' A'], [0, 3, 3, 0, 'A'], - ]); + ], 2); }); test('getLineIndentGuide Java', () => { assertIndentGuides([ /* 1*/[0, 1, 1, 0, 'class A {'], /* 2*/[1, 2, 9, 1, ' void foo() {'], - /* 3*/[1, 2, 9, 1, ' console.log(1);'], - /* 4*/[1, 2, 9, 1, ' console.log(2);'], + /* 3*/[2, 3, 4, 2, ' console.log(1);'], + /* 4*/[2, 3, 4, 2, ' console.log(2);'], /* 5*/[1, 2, 9, 1, ' }'], /* 6*/[1, 2, 9, 1, ''], /* 7*/[1, 2, 9, 1, ' void bar() {'], - /* 8*/[1, 2, 9, 1, ' console.log(3);'], + /* 8*/[2, 8, 8, 2, ' console.log(3);'], /* 9*/[1, 2, 9, 1, ' }'], /*10*/[0, 10, 10, 0, '}'], /*11*/[0, 11, 11, 0, 'interface B {'], /*12*/[1, 12, 12, 1, ' void bar();'], /*13*/[0, 13, 13, 0, '}'], - ]); + ], 2); }); test('getLineIndentGuide Javadoc', () => { @@ -653,7 +654,7 @@ suite('TextModel.getLineIndentGuide', () => { [1, 5, 6, 1, ' void foo() {'], [1, 5, 6, 1, ' }'], [0, 7, 7, 0, '}'], - ]); + ], 2); }); test('getLineIndentGuide Whitespace', () => { @@ -661,12 +662,12 @@ suite('TextModel.getLineIndentGuide', () => { [0, 1, 1, 0, 'class A {'], [1, 2, 7, 1, ''], [1, 2, 7, 1, ' void foo() {'], - [1, 2, 7, 1, ' '], - [2, 5, 5, 2, ' return 1;'], + [2, 4, 5, 2, ' '], + [3, 5, 5, 3, ' return 1;'], [1, 2, 7, 1, ' }'], [1, 2, 7, 1, ' '], [0, 8, 8, 0, '}'] - ]); + ], 2); }); test('getLineIndentGuide Tabs', () => { @@ -679,7 +680,7 @@ suite('TextModel.getLineIndentGuide', () => { [1, 2, 7, 1, ' \t}'], [1, 2, 7, 1, ' '], [0, 8, 8, 0, '}'] - ]); + ], 4); }); test('getLineIndentGuide checker.ts', () => { @@ -701,7 +702,7 @@ suite('TextModel.getLineIndentGuide', () => { /*15*/[2, 11, 15, 2, ' return node.id;'], /*16*/[1, 5, 16, 1, ' }'], /*17*/[0, 17, 17, 0, '}'] - ]); + ], 4); }); test('issue #8425 - Missing indentation lines for first level indentation', () => { @@ -710,7 +711,7 @@ suite('TextModel.getLineIndentGuide', () => { [2, 2, 3, 2, '\t\tindent2'], [2, 2, 3, 2, '\t\tindent2'], [1, 1, 4, 1, '\tindent1'] - ]); + ], 4); }); test('issue #8952 - Indentation guide lines going through text on .yml file', () => { @@ -721,7 +722,7 @@ suite('TextModel.getLineIndentGuide', () => { [2, 3, 5, 2, ' - length:'], [3, 5, 5, 3, ' max: 255'], [0, 6, 6, 0, 'getters:'] - ]); + ], 4); }); test('issue #11892 - Indent guides look funny', () => { @@ -734,7 +735,7 @@ suite('TextModel.getLineIndentGuide', () => { [3, 6, 6, 3, '\t\t\treturn 2;'], [1, 2, 7, 1, '\t}'], [0, 8, 8, 0, '}'] - ]); + ], 4); }); test('issue #12398 - Problem in indent guidelines', () => { @@ -742,7 +743,7 @@ suite('TextModel.getLineIndentGuide', () => { [2, 1, 2, 2, '\t\t.bla'], [3, 2, 2, 3, '\t\t\tlabel(for)'], [0, 3, 3, 0, 'include script'] - ]); + ], 4); }); test('issue #49173', () => { diff --git a/src/vs/workbench/services/textfile/browser/textFileService.ts b/src/vs/workbench/services/textfile/browser/textFileService.ts index 27273f2213d6de45391f295c475c0663eaad020f..139629a26b650e210707fd144687ce2477740623 100644 --- a/src/vs/workbench/services/textfile/browser/textFileService.ts +++ b/src/vs/workbench/services/textfile/browser/textFileService.ts @@ -35,7 +35,7 @@ import { coalesce } from 'vs/base/common/arrays'; import { suggestFilename } from 'vs/base/common/mime'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { resolve } from 'vs/base/common/path'; +import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService'; /** * The workbench file service implementation implements the raw file service spec and adds additional methods on top. @@ -85,7 +85,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex @IFilesConfigurationService protected readonly filesConfigurationService: IFilesConfigurationService, @ITextModelService private readonly textModelService: ITextModelService, @ICodeEditorService private readonly codeEditorService: ICodeEditorService, - @INotificationService private readonly notificationService: INotificationService + @INotificationService private readonly notificationService: INotificationService, + @IRemotePathService private readonly remotePathService: IRemotePathService ) { super(); @@ -321,12 +322,12 @@ export abstract class AbstractTextFileService extends Disposable implements ITex // Untitled with associated file path don't need to prompt if (model.hasAssociatedFilePath) { - targetUri = this.suggestSavePath(resource); + targetUri = await this.suggestSavePath(resource); } // Otherwise ask user else { - targetUri = await this.fileDialogService.pickFileToSave(this.suggestSavePath(resource), options?.availableFileSystems); + targetUri = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(resource), options?.availableFileSystems); } // Save as if target provided @@ -367,7 +368,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex // Get to target resource if (!target) { - target = await this.fileDialogService.pickFileToSave(this.suggestSavePath(source), options?.availableFileSystems); + target = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(source), options?.availableFileSystems); } if (!target) { @@ -546,7 +547,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex return (await this.dialogService.confirm(confirm)).confirmed; } - private suggestSavePath(resource: URI): URI { + private async suggestSavePath(resource: URI): Promise { // Just take the resource as is if the file service can handle it if (this.fileService.canHandleResource(resource)) { @@ -582,16 +583,8 @@ export abstract class AbstractTextFileService extends Disposable implements ITex } // Try to place where last active file was if any - const defaultFilePath = this.fileDialogService.defaultFilePath(); - if (defaultFilePath) { - return joinPath(defaultFilePath, suggestedFilename); - } - - // Finally fallback to suggest just the file name - // Since we do not have a default file path to - // put, we use path.resolve() to make sure the path - // is absolute. - return toLocalResource(resource.with({ path: resolve(suggestedFilename) }), remoteAuthority); + // Otherwise fallback to user home + return joinPath(this.fileDialogService.defaultFilePath() || (await this.remotePathService.userHome), suggestedFilename); } //#endregion diff --git a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts index 2ee9c3ea47eb31c27dc42a12670eb03bc0463020..34ffc230de40baf81811ccc772bfcf680e14f552 100644 --- a/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts +++ b/src/vs/workbench/services/textfile/electron-browser/nativeTextFileService.ts @@ -38,6 +38,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService'; export class NativeTextFileService extends AbstractTextFileService { @@ -55,9 +56,10 @@ export class NativeTextFileService extends AbstractTextFileService { @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, @ITextModelService textModelService: ITextModelService, @ICodeEditorService codeEditorService: ICodeEditorService, - @INotificationService notificationService: INotificationService + @INotificationService notificationService: INotificationService, + @IRemotePathService remotePathService: IRemotePathService ) { - super(fileService, untitledTextEditorService, lifecycleService, instantiationService, modelService, environmentService, dialogService, fileDialogService, textResourceConfigurationService, filesConfigurationService, textModelService, codeEditorService, notificationService); + super(fileService, untitledTextEditorService, lifecycleService, instantiationService, modelService, environmentService, dialogService, fileDialogService, textResourceConfigurationService, filesConfigurationService, textModelService, codeEditorService, notificationService, remotePathService); } private _encoding: EncodingOracle | undefined; diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 770514ff8fbf2f153c3f48f70dd81fef6eb2eae1..f5a8dd698787d295cf1b4ed20e95533b60099824 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -92,6 +92,7 @@ export import TestTextResourcePropertiesService = CommonWorkbenchTestServices.Te export import TestContextService = CommonWorkbenchTestServices.TestContextService; export import TestStorageService = CommonWorkbenchTestServices.TestStorageService; export import TestWorkingCopyService = CommonWorkbenchTestServices.TestWorkingCopyService; +import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService'; export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined); @@ -118,7 +119,8 @@ export class TestTextFileService extends BrowserTextFileService { @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, @ITextModelService textModelService: ITextModelService, @ICodeEditorService codeEditorService: ICodeEditorService, - @INotificationService notificationService: INotificationService + @INotificationService notificationService: INotificationService, + @IRemotePathService remotePathService: IRemotePathService ) { super( fileService, @@ -133,7 +135,8 @@ export class TestTextFileService extends BrowserTextFileService { filesConfigurationService, textModelService, codeEditorService, - notificationService + notificationService, + remotePathService ); } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index a6435298de70cd9d684491a68b4866d735f4dc90..0857cc45c11b82b1b7b59b1a5cef0d95cf4f0cdd 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -29,6 +29,7 @@ import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textMo import { IOpenedWindow, IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions, IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { LogLevel } from 'vs/platform/log/common/log'; +import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService'; export const TestWindowConfiguration: IWindowConfiguration = { windowId: 0, @@ -61,7 +62,8 @@ export class TestTextFileService extends NativeTextFileService { @IFilesConfigurationService filesConfigurationService: IFilesConfigurationService, @ITextModelService textModelService: ITextModelService, @ICodeEditorService codeEditorService: ICodeEditorService, - @INotificationService notificationService: INotificationService + @INotificationService notificationService: INotificationService, + @IRemotePathService remotePathService: IRemotePathService ) { super( fileService, @@ -77,7 +79,8 @@ export class TestTextFileService extends NativeTextFileService { filesConfigurationService, textModelService, codeEditorService, - notificationService + notificationService, + remotePathService ); }