diff --git a/CHANGELOG.md b/CHANGELOG.md index 800b0af652cf7..7f4c9ef7add43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ Breaking changes: - `debug.restart` renamed to `workbench.action.debug.restart` - [preferences] renamed overridenPreferenceName to overriddenPreferenceName - [task] `cwd`, which used to be defined directly under `Task`, is moved into `Task.options` object +- [preferences] removed constructor from the `FolderPreferenceProvider` class +- [workspace] `isMultiRootWorkspaceOpened()` is renamed into `isMultiRootWorkspaceEnabled()` ## v0.7.0 diff --git a/packages/core/src/browser/preferences/preference-service.ts b/packages/core/src/browser/preferences/preference-service.ts index b552900f65f9d..9288189b07312 100644 --- a/packages/core/src/browser/preferences/preference-service.ts +++ b/packages/core/src/browser/preferences/preference-service.ts @@ -202,7 +202,16 @@ export class PreferenceServiceImpl implements PreferenceService, FrontendApplica if (scope > change.scope && value !== undefined) { // preference defined in a more specific scope break; - } else if (scope === change.scope) { + } else if (scope === change.scope && change.newValue !== undefined) { + // preference is changed into something other than `undefined` + acceptChange(change); + } else if (scope < change.scope && change.newValue === undefined && value !== undefined) { + // preference is changed to `undefined`, use the value from a more general scope + change = { + ...change, + newValue: value, + scope + }; acceptChange(change); } } diff --git a/packages/debug/src/browser/debug-prefix-configuration.ts b/packages/debug/src/browser/debug-prefix-configuration.ts index 2214b05347829..125f7fa48b66b 100644 --- a/packages/debug/src/browser/debug-prefix-configuration.ts +++ b/packages/debug/src/browser/debug-prefix-configuration.ts @@ -90,13 +90,12 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan } async onType(_lookFor: string, acceptor: (items: QuickOpenItem[]) => void): Promise { - const isMulti: boolean = !!this.workspaceService.workspace && !this.workspaceService.workspace.isDirectory; const items: QuickOpenItem[] = []; const configurations = this.debugConfigurationManager.all; Array.from(configurations).forEach(config => { items.push(new QuickOpenItem({ label: config.configuration.name, - description: isMulti + description: this.workspaceService.isMultiRootWorkspaceOpened ? this.labelProvider.getName(new URI(config.workspaceFolderUri)) : '', run: (mode: QuickOpenMode) => { diff --git a/packages/debug/src/browser/view/debug-configuration-widget.tsx b/packages/debug/src/browser/view/debug-configuration-widget.tsx index bbd1d24910aee..c5e7a9fdaca54 100644 --- a/packages/debug/src/browser/view/debug-configuration-widget.tsx +++ b/packages/debug/src/browser/view/debug-configuration-widget.tsx @@ -97,7 +97,7 @@ export class DebugConfigurationWidget extends ReactWidget { return configuration.name + '__CONF__' + workspaceFolderUri; } protected toName({ configuration, workspaceFolderUri }: DebugSessionOptions): string { - if (!workspaceFolderUri || !this.workspaceService.isMultiRootWorkspaceOpened) { + if (!workspaceFolderUri || !this.workspaceService.isMultiRootWorkspaceEnabled) { return configuration.name; } return configuration.name + ' (' + new URI(workspaceFolderUri).path.base + ')'; diff --git a/packages/file-search/src/browser/quick-file-open.ts b/packages/file-search/src/browser/quick-file-open.ts index dc61612d978b8..92a30a8d30649 100644 --- a/packages/file-search/src/browser/quick-file-open.ts +++ b/packages/file-search/src/browser/quick-file-open.ts @@ -319,7 +319,7 @@ export class QuickFileOpenService implements QuickOpenModel, QuickOpenHandler { private async toItem(uriOrString: URI | string, group?: QuickOpenGroupItemOptions) { const uri = uriOrString instanceof URI ? uriOrString : new URI(uriOrString); let description = this.labelProvider.getLongName(uri.parent); - if (this.workspaceService.workspace && !this.workspaceService.workspace.isDirectory) { + if (this.workspaceService.isMultiRootWorkspaceOpened) { const rootUri = this.workspaceService.getWorkspaceRootUri(uri); if (rootUri) { description = `${rootUri.displayName} • ${description}`; diff --git a/packages/navigator/src/browser/navigator-widget.tsx b/packages/navigator/src/browser/navigator-widget.tsx index 491b8c183cdd2..e2ef79550caf5 100644 --- a/packages/navigator/src/browser/navigator-widget.tsx +++ b/packages/navigator/src/browser/navigator-widget.tsx @@ -116,7 +116,7 @@ export class FileNavigatorWidget extends FileTreeWidget { protected getContainerTreeNode(): TreeNode | undefined { const root = this.model.root; - if (this.workspaceService.isMultiRootWorkspaceOpened) { + if (this.workspaceService.isMultiRootWorkspaceEnabled) { return root; } if (WorkspaceNode.is(root)) { diff --git a/packages/preferences/src/browser/folder-preference-provider.ts b/packages/preferences/src/browser/folder-preference-provider.ts index a669ada5ff50b..353b442135c6f 100644 --- a/packages/preferences/src/browser/folder-preference-provider.ts +++ b/packages/preferences/src/browser/folder-preference-provider.ts @@ -18,7 +18,8 @@ import { inject, injectable } from 'inversify'; import URI from '@theia/core/lib/common/uri'; import { PreferenceScope } from '@theia/core/lib/browser'; import { AbstractResourcePreferenceProvider } from './abstract-resource-preference-provider'; -import { FileSystem, FileStat } from '@theia/filesystem/lib/common'; +import { FileStat } from '@theia/filesystem/lib/common'; +import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; export const FolderPreferenceProviderFactory = Symbol('FolderPreferenceProviderFactory'); export interface FolderPreferenceProviderFactory { @@ -34,14 +35,11 @@ export interface FolderPreferenceProviderOptions { @injectable() export class FolderPreferenceProvider extends AbstractResourcePreferenceProvider { - readonly folderUri: URI; + @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; + @inject(FolderPreferenceProviderOptions) protected readonly options: FolderPreferenceProviderOptions; - constructor( - @inject(FolderPreferenceProviderOptions) protected readonly options: FolderPreferenceProviderOptions, - @inject(FileSystem) protected readonly fileSystem: FileSystem - ) { - super(); - this.folderUri = new URI(this.options.folder.uri); + get folderUri(): URI { + return new URI(this.options.folder.uri); } protected getUri(): URI { @@ -49,6 +47,10 @@ export class FolderPreferenceProvider extends AbstractResourcePreferenceProvider } protected getScope(): PreferenceScope { + if (!this.workspaceService.isMultiRootWorkspaceOpened) { + // when FolderPreferenceProvider is used as a delegate of WorkspacePreferenceProvider in a one-folder workspace + return PreferenceScope.Workspace; + } return PreferenceScope.Folder; } diff --git a/packages/preferences/src/browser/workspace-preference-provider.ts b/packages/preferences/src/browser/workspace-preference-provider.ts index 0730462729c16..99838e0ed76e3 100644 --- a/packages/preferences/src/browser/workspace-preference-provider.ts +++ b/packages/preferences/src/browser/workspace-preference-provider.ts @@ -77,7 +77,7 @@ export class WorkspacePreferenceProvider extends PreferenceProvider { if (!workspace) { return undefined; } - if (workspace.isDirectory) { + if (!this.workspaceService.isMultiRootWorkspaceOpened) { return this.folderPreferenceProvider; } return this.workspaceFileProviderFactory({ @@ -109,9 +109,8 @@ export class WorkspacePreferenceProvider extends PreferenceProvider { } protected ensureResourceUri(): string | undefined { - const workspace = this.workspaceService.workspace; - if (workspace && workspace.isDirectory) { - return workspace.uri; + if (this.workspaceService.workspace && !this.workspaceService.isMultiRootWorkspaceOpened) { + return this.workspaceService.workspace.uri; } return undefined; } diff --git a/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx b/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx index 41fbe0cf707b2..c0dfa94a9d5d6 100644 --- a/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx +++ b/packages/search-in-workspace/src/browser/search-in-workspace-result-tree-widget.tsx @@ -315,7 +315,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget { id: rootUri, parent: this.model.root as SearchInWorkspaceRoot, icon: FOLDER_ICON, - visible: this.workspaceService.workspace && !this.workspaceService.workspace.isDirectory + visible: this.workspaceService.isMultiRootWorkspaceOpened }; } diff --git a/packages/workspace/src/browser/workspace-commands.ts b/packages/workspace/src/browser/workspace-commands.ts index f012c481df765..e6f41a541c251 100644 --- a/packages/workspace/src/browser/workspace-commands.ts +++ b/packages/workspace/src/browser/workspace-commands.ts @@ -265,7 +265,7 @@ export class WorkspaceCommandContribution implements CommandContribution { registry.registerCommand(WorkspaceCommands.FILE_COMPARE, this.newMultiUriAwareCommandHandler(this.compareHandler)); this.preferences.ready.then(() => { registry.registerCommand(WorkspaceCommands.ADD_FOLDER, this.newMultiUriAwareCommandHandler({ - isEnabled: () => this.workspaceService.isMultiRootWorkspaceOpened, + isEnabled: () => this.workspaceService.isMultiRootWorkspaceEnabled, isVisible: uris => !uris.length || this.areWorkspaceRoots(uris), execute: async uris => { const uri = await this.fileDialogService.showOpenDialog({ @@ -293,7 +293,7 @@ export class WorkspaceCommandContribution implements CommandContribution { })); registry.registerCommand(WorkspaceCommands.REMOVE_FOLDER, this.newMultiUriAwareCommandHandler({ execute: uris => this.removeFolderFromWorkspace(uris), - isEnabled: () => this.workspaceService.isMultiRootWorkspaceOpened, + isEnabled: () => this.workspaceService.isMultiRootWorkspaceEnabled, isVisible: uris => this.areWorkspaceRoots(uris) && this.workspaceService.saved })); }); @@ -441,7 +441,7 @@ export class WorkspaceRootUriAwareCommandHandler extends UriAwareCommandHandler< protected getUri(): URI | undefined { const uri = super.getUri(); - if (this.workspaceService.isMultiRootWorkspaceOpened) { + if (this.workspaceService.isMultiRootWorkspaceEnabled) { return uri; } if (uri) { diff --git a/packages/workspace/src/browser/workspace-frontend-contribution.ts b/packages/workspace/src/browser/workspace-frontend-contribution.ts index b929b32899681..b01525ee53f14 100644 --- a/packages/workspace/src/browser/workspace-frontend-contribution.ts +++ b/packages/workspace/src/browser/workspace-frontend-contribution.ts @@ -90,7 +90,7 @@ export class WorkspaceFrontendContribution implements CommandContribution, Keybi execute: () => this.quickOpenWorkspace.select() }); commands.registerCommand(WorkspaceCommands.SAVE_WORKSPACE_AS, { - isEnabled: () => this.workspaceService.isMultiRootWorkspaceOpened, + isEnabled: () => this.workspaceService.isMultiRootWorkspaceEnabled, execute: () => this.saveWorkspaceAs() }); commands.registerCommand(WorkspaceCommands.SAVE_AS, diff --git a/packages/workspace/src/browser/workspace-service.spec.ts b/packages/workspace/src/browser/workspace-service.spec.ts index 49fb32eb3a35c..16e1d54964694 100644 --- a/packages/workspace/src/browser/workspace-service.spec.ts +++ b/packages/workspace/src/browser/workspace-service.spec.ts @@ -600,10 +600,10 @@ describe('WorkspaceService', () => { }); }); - describe('isMultiRootWorkspaceOpened status', () => { + describe('isMultiRootWorkspaceEnabled status', () => { it('should be true if there is an opened workspace and preference["workspace.supportMultiRootWorkspace"] = true, otherwise false', () => { mockPreferenceValues['workspace.supportMultiRootWorkspace'] = true; - expect(wsService.isMultiRootWorkspaceOpened).to.be.false; + expect(wsService.isMultiRootWorkspaceEnabled).to.be.false; const file = { uri: 'file:///home/file', @@ -612,9 +612,31 @@ describe('WorkspaceService', () => { }; wsService['_workspace'] = file; mockPreferenceValues['workspace.supportMultiRootWorkspace'] = true; - expect(wsService.isMultiRootWorkspaceOpened).to.be.true; + expect(wsService.isMultiRootWorkspaceEnabled).to.be.true; mockPreferenceValues['workspace.supportMultiRootWorkspace'] = false; + expect(wsService.isMultiRootWorkspaceEnabled).to.be.false; + }); + }); + + describe('isMultiRootWorkspaceOpened status', () => { + it('should be true if there is an opened workspace and the workspace is not a directory, otherwise false', () => { + expect(wsService.isMultiRootWorkspaceOpened).to.be.false; + + const file = { + uri: 'file:///home/file', + lastModification: 0, + isDirectory: false + }; + wsService['_workspace'] = file; + expect(wsService.isMultiRootWorkspaceOpened).to.be.true; + + const dir = { + uri: 'file:///home/dir', + lastModification: 0, + isDirectory: true + }; + wsService['_workspace'] = dir; expect(wsService.isMultiRootWorkspaceOpened).to.be.false; }); }); diff --git a/packages/workspace/src/browser/workspace-service.ts b/packages/workspace/src/browser/workspace-service.ts index f77a86d86840f..f1b8117c6b1f8 100644 --- a/packages/workspace/src/browser/workspace-service.ts +++ b/packages/workspace/src/browser/workspace-service.ts @@ -261,10 +261,18 @@ export class WorkspaceService implements FrontendApplicationContribution { } /** - * Returns `true` if there is an opened workspace in theia, and the workspace has more than one root. + * Returns `true` if a multiple-root workspace is currently open. * @returns {boolean} */ get isMultiRootWorkspaceOpened(): boolean { + return !!this.workspace && !this.workspace.isDirectory; + } + + /** + * Returns `true` if there is an opened workspace, and multi root workspace support is enabled. + * @returns {boolean} + */ + get isMultiRootWorkspaceEnabled(): boolean { return this.opened && this.preferences['workspace.supportMultiRootWorkspace']; }