diff --git a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts index b4c312b5327..330be4494f0 100644 --- a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts @@ -11,7 +11,7 @@ import { Schemas } from 'vs/base/common/network'; import { IPath, normalize } from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; import { isObject } from 'vs/base/common/types'; -import { URI as uri } from 'vs/base/common/uri'; +import { URI } from 'vs/base/common/uri'; import { Selection } from 'vs/editor/common/core/selection'; import { EditorType } from 'vs/editor/common/editorCommon'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -45,7 +45,7 @@ class TestEditorServiceWithActiveEditor extends TestEditorService { override get activeEditor(): any { return { get resource(): any { - return uri.parse('file:///VSCode/workspaceLocation/file'); + return URI.parse('file:///VSCode/workspaceLocation/file'); } }; } @@ -81,7 +81,7 @@ suite('Configuration Resolver Service', () => { labelService = new MockLabelService(); pathService = new MockPathService(); extensionService = new TestExtensionService(); - containingWorkspace = testWorkspace(uri.parse('file:///VSCode/workspaceLocation')); + containingWorkspace = testWorkspace(URI.parse('file:///VSCode/workspaceLocation')); workspace = containingWorkspace.folders[0]; configurationResolverService = new TestConfigurationResolverService(nullContext, Promise.resolve(environmentService.userEnv), editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService, pathService, extensionService); }); @@ -192,9 +192,9 @@ suite('Configuration Resolver Service', () => { test('supports extensionDir', async () => { const getExtension = stub(extensionService, 'getExtension'); - getExtension.withArgs('publisher.extId').returns(Promise.resolve({ extensionLocation: uri.file('/some/path') } as IExtensionDescription)); + getExtension.withArgs('publisher.extId').returns(Promise.resolve({ extensionLocation: URI.file('/some/path') } as IExtensionDescription)); - assert.strictEqual(await configurationResolverService!.resolveAsync(workspace, '${extensionInstallFolder:publisher.extId}'), uri.file('/some/path').fsPath); + assert.strictEqual(await configurationResolverService!.resolveAsync(workspace, '${extensionInstallFolder:publisher.extId}'), URI.file('/some/path').fsPath); }); // test('substitute keys and values in object', () => { @@ -679,13 +679,13 @@ class MockCommandService implements ICommandService { class MockLabelService implements ILabelService { _serviceBrand: undefined; - getUriLabel(resource: uri, options?: { relative?: boolean | undefined; noPrefix?: boolean | undefined }): string { + getUriLabel(resource: URI, options?: { relative?: boolean | undefined; noPrefix?: boolean | undefined }): string { return normalize(resource.fsPath); } - getUriBasenameLabel(resource: uri): string { + getUriBasenameLabel(resource: URI): string { throw new Error('Method not implemented.'); } - getWorkspaceLabel(workspace: uri | IWorkspaceIdentifier | IWorkspace, options?: { verbose: boolean }): string { + getWorkspaceLabel(workspace: URI | IWorkspaceIdentifier | IWorkspace, options?: { verbose: boolean }): string { throw new Error('Method not implemented.'); } getHostLabel(scheme: string, authority?: string): string { @@ -709,18 +709,21 @@ class MockPathService implements IPathService { throw new Error('Property not implemented'); } defaultUriScheme: string = Schemas.file; - fileURI(path: string): Promise { + fileURI(path: string): Promise { throw new Error('Method not implemented.'); } - async userHome(options?: { preferLocal: boolean }): Promise { - return uri.file('c:\\users\\username'); + userHome(options?: { preferLocal: boolean }): Promise; + userHome(options: { preferLocal: true }): URI; + userHome(options?: { preferLocal: boolean }): Promise | URI { + const uri = URI.file('c:\\users\\username'); + return options?.preferLocal ? uri : Promise.resolve(uri); } - hasValidBasename(resource: uri, basename?: string): Promise; - hasValidBasename(resource: uri, os: platform.OperatingSystem, basename?: string): boolean; - hasValidBasename(resource: uri, arg2?: string | platform.OperatingSystem, name?: string): boolean | Promise { + hasValidBasename(resource: URI, basename?: string): Promise; + hasValidBasename(resource: URI, os: platform.OperatingSystem, basename?: string): boolean; + hasValidBasename(resource: URI, arg2?: string | platform.OperatingSystem, name?: string): boolean | Promise { throw new Error('Method not implemented.'); } - resolvedUserHome: uri | undefined; + resolvedUserHome: URI | undefined; } class MockInputsConfigurationService extends TestConfigurationService { diff --git a/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts b/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts index 0bea5b5eb37..d8ab94017c1 100644 --- a/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts +++ b/src/vs/workbench/services/dialogs/test/electron-sandbox/fileDialogService.test.ts @@ -127,7 +127,7 @@ suite('FileDialogService', function () { instantiationService.stub(IPathService, new class { defaultUriScheme: string = 'vscode-virtual-test'; userHome = async () => URI.file('/user/home'); - }); + } as IPathService); const dialogService = instantiationService.createInstance(TestFileDialogService, new TestSimpleFileDialog()); instantiationService.set(IFileDialogService, dialogService); const workspaceService: IWorkspaceEditingService = instantiationService.createInstance(BrowserWorkspaceEditingService); @@ -159,7 +159,7 @@ suite('FileDialogService', function () { instantiationService.stub(IPathService, new class { defaultUriScheme: string = Schemas.vscodeRemote; userHome = async () => URI.file('/user/home'); - }); + } as IPathService); const dialogService = instantiationService.createInstance(TestFileDialogService, new TestSimpleFileDialog()); instantiationService.set(IFileDialogService, dialogService); const workspaceService: IWorkspaceEditingService = instantiationService.createInstance(BrowserWorkspaceEditingService); diff --git a/src/vs/workbench/services/label/common/labelService.ts b/src/vs/workbench/services/label/common/labelService.ts index 7e69b5953ef..9946853e53c 100644 --- a/src/vs/workbench/services/label/common/labelService.ts +++ b/src/vs/workbench/services/label/common/labelService.ts @@ -23,6 +23,7 @@ import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { OperatingSystem, OS } from 'vs/base/common/platform'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; +import { Schemas } from 'vs/base/common/network'; const resourceLabelFormattersExtPoint = ExtensionsRegistry.registerExtensionPoint({ extensionPoint: 'resourceLabelFormatters', @@ -109,8 +110,8 @@ export class LabelService extends Disposable implements ILabelService { private readonly _onDidChangeFormatters = this._register(new Emitter({ leakWarningThreshold: 400 })); readonly onDidChangeFormatters = this._onDidChangeFormatters.event; - private os = OS; - private userHome: URI | undefined = undefined; + private os: OperatingSystem; + private userHome: URI | undefined; constructor( @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @@ -120,11 +121,18 @@ export class LabelService extends Disposable implements ILabelService { ) { super(); - // Resolve OS & Paths with remote in mind - this.resolveEnvironment(); + // Find some meaningful defaults until the remote environment + // is resolved, by taking the current OS we are running in + // and by taking the local `userHome` if we run on a local + // file scheme. + this.os = OS; + this.userHome = pathService.defaultUriScheme === Schemas.file ? this.pathService.userHome({ preferLocal: true }) : undefined; + + // Remote environment is potentially long running + this.resolveRemoteEnvironment(); } - private async resolveEnvironment(): Promise { + private async resolveRemoteEnvironment(): Promise { // OS const env = await this.remoteAgentService.getEnvironment(); diff --git a/src/vs/workbench/services/path/common/pathService.ts b/src/vs/workbench/services/path/common/pathService.ts index b00c949dc3f..f61ee26be86 100644 --- a/src/vs/workbench/services/path/common/pathService.ts +++ b/src/vs/workbench/services/path/common/pathService.ts @@ -57,6 +57,7 @@ export interface IPathService { * remote's user home directory, otherwise the local one unless * `preferLocal` is set to `true`. */ + userHome(options: { preferLocal: true }): URI; userHome(options?: { preferLocal: boolean }): Promise; /** @@ -103,7 +104,7 @@ export abstract class AbstractPathService implements IPathService { // User Home this.resolveUserHome = (async () => { const env = await this.remoteAgentService.getEnvironment(); - const userHome = this.maybeUnresolvedUserHome = env?.userHome || localUserHome; + const userHome = this.maybeUnresolvedUserHome = env?.userHome ?? localUserHome; return userHome; })(); @@ -161,7 +162,9 @@ export abstract class AbstractPathService implements IPathService { return Schemas.file; } - async userHome(options?: { preferLocal: boolean }): Promise { + userHome(options?: { preferLocal: boolean }): Promise; + userHome(options: { preferLocal: true }): URI; + userHome(options?: { preferLocal: boolean }): Promise | URI { return options?.preferLocal ? this.localUserHome : this.resolveUserHome; } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 3504ef02dc4..62e691e60bb 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -1699,7 +1699,12 @@ export class TestPathService implements IPathService { get path() { return Promise.resolve(isWindows ? win32 : posix); } - async userHome() { return this.fallbackUserHome; } + userHome(options?: { preferLocal: boolean }): Promise; + userHome(options: { preferLocal: true }): URI; + userHome(options?: { preferLocal: boolean }): Promise | URI { + return options?.preferLocal ? this.fallbackUserHome : Promise.resolve(this.fallbackUserHome); + } + get resolvedUserHome() { return this.fallbackUserHome; } async fileURI(path: string): Promise {