#28538 Introduce IWorkspace2 in IWorkspaceContextService

This commit is contained in:
Sandeep Somavarapu
2017-06-14 10:45:06 +02:00
parent b33113d484
commit a7d864df4c
5 changed files with 82 additions and 38 deletions

View File

@@ -17,7 +17,7 @@ import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingReso
import { IKeybindingEvent, KeybindingSource, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IConfirmation, IMessageService } from 'vs/platform/message/common/message';
import { IWorkspaceContextService, Workspace, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceContextService, Workspace, IWorkspace, IWorkspace2 } from 'vs/platform/workspace/common/workspace';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { Selection } from 'vs/editor/common/core/selection';
@@ -495,8 +495,8 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService {
public _serviceBrand: any;
private readonly _onDidChangeFolders: Emitter<URI[]> = new Emitter<URI[]>();
public readonly onDidChangeFolders: Event<URI[]> = this._onDidChangeFolders.event;
private readonly _onDidChangeWorkspaceRoots: Emitter<URI[]> = new Emitter<URI[]>();
public readonly onDidChangeWorkspaceRoots: Event<URI[]> = this._onDidChangeWorkspaceRoots.event;
private readonly folders: URI[];
@@ -512,6 +512,10 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService {
return this.workspace;
}
public getWorkspace2(): IWorkspace2 {
return this.workspace ? { id: `${this.workspace.uid}`, roots: [this.workspace.resource] } : void 0;
}
public hasWorkspace(): boolean {
return !!this.workspace;
}

View File

@@ -27,6 +27,17 @@ export interface IWorkspaceContextService {
*/
getWorkspace(): IWorkspace;
/**
* Provides access to the workspace object the platform is running with. This may be null if the workbench was opened
* without workspace (empty);
*/
getWorkspace2(): IWorkspace2;
/**
* An event which fires on workspace roots change.
*/
onDidChangeWorkspaceRoots: Event<URI[]>;
/**
* Returns iff the provided resource is inside the workspace or not.
*/
@@ -44,11 +55,6 @@ export interface IWorkspaceContextService {
*/
toResource: (workspaceRelativePath: string) => URI;
/**
* TODO@Ben multiroot
*/
getFolders(): URI[];
onDidChangeFolders: Event<URI[]>;
}
export interface IWorkspace {
@@ -72,6 +78,20 @@ export interface IWorkspace {
name?: string;
}
export interface IWorkspace2 {
/**
* the unique identifier of the workspace.
*/
readonly id: string;
/**
* Mutliple roots in this workspace. First entry is master and never changes.
*/
readonly roots: URI[];
}
export class Workspace implements IWorkspace {
constructor(private _resource: URI, private _uid?: number, private _name?: string) {
@@ -105,9 +125,9 @@ export class Workspace implements IWorkspace {
return null;
}
public toResource(workspaceRelativePath: string): URI {
public toResource(workspaceRelativePath: string, root?: URI): URI {
if (typeof workspaceRelativePath === 'string') {
return URI.file(paths.join(this._resource.fsPath, workspaceRelativePath));
return URI.file(paths.join(root ? root.fsPath : this._resource.fsPath, workspaceRelativePath));
}
return null;

View File

@@ -37,7 +37,7 @@ export class MainThreadWorkspace extends MainThreadWorkspaceShape {
) {
super();
this._proxy = threadService.get(ExtHostContext.ExtHostWorkspace);
this._contextService.onDidChangeFolders(this._onDidChangeWorkspace, this, this._toDispose);
this._contextService.onDidChangeWorkspaceRoots(this._onDidChangeWorkspace, this, this._toDispose);
}
// --- workspace ---

View File

@@ -17,7 +17,7 @@ import { Schemas } from "vs/base/common/network";
import { RunOnceScheduler } from 'vs/base/common/async';
import { readFile } from 'vs/base/node/pfs';
import * as extfs from 'vs/base/node/extfs';
import { IWorkspaceContextService, Workspace, IWorkspace } from "vs/platform/workspace/common/workspace";
import { IWorkspaceContextService, IWorkspace2, Workspace as SingleRootWorkspace, IWorkspace } from "vs/platform/workspace/common/workspace";
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { FileChangeType, FileChangesEvent, isEqual } from 'vs/platform/files/common/files';
import { ConfigModel } from 'vs/platform/configuration/common/model';
@@ -44,14 +44,29 @@ interface IWorkspaceConfiguration<T> {
type IWorkspaceFoldersConfiguration = { [rootFolder: string]: { folders: string[]; } };
class Workspace implements IWorkspace2 {
constructor(readonly id: string, private _roots: URI[]) {
}
get roots(): URI[] {
return this._roots;
}
setRoots(roots: URI[]): void {
this._roots = roots;
}
}
export class WorkspaceConfigurationService extends Disposable implements IWorkspaceContextService, IWorkspaceConfigurationService {
private static RELOAD_CONFIGURATION_DELAY = 50;
public _serviceBrand: any;
private readonly _onDidChangeFolders: Emitter<URI[]> = this._register(new Emitter<URI[]>());
public readonly onDidChangeFolders: Event<URI[]> = this._onDidChangeFolders.event;
private readonly _onDidChangeWorkspaceRoots: Emitter<URI[]> = this._register(new Emitter<URI[]>());
public readonly onDidChangeWorkspaceRoots: Event<URI[]> = this._onDidChangeWorkspaceRoots.event;
private readonly _onDidUpdateConfiguration: Emitter<IConfigurationServiceEvent> = this._register(new Emitter<IConfigurationServiceEvent>());
public readonly onDidUpdateConfiguration: Event<IConfigurationServiceEvent> = this._onDidUpdateConfiguration.event;
@@ -65,12 +80,12 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
private workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: TPromise<IConfigModel<any>> };
private reloadConfigurationScheduler: RunOnceScheduler;
private folders: URI[];
private readonly workspace: Workspace;
constructor(private environmentService: IEnvironmentService, private workspace?: Workspace, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) {
constructor(private environmentService: IEnvironmentService, private singleRootWorkspace?: SingleRootWorkspace, private workspaceSettingsRootFolder: string = WORKSPACE_CONFIG_FOLDER_DEFAULT_NAME) {
super();
this.folders = workspace ? [workspace.resource] : [];
this.workspace = singleRootWorkspace ? new Workspace(`${singleRootWorkspace.uid}`, [singleRootWorkspace.resource]) : null;
this.workspaceFilePathToConfiguration = Object.create(null);
this.cachedConfig = new ConfigModel<any>(null);
@@ -95,10 +110,11 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
}
// Resovled configured folders for workspace
let configuredFolders: URI[] = [this.workspace.resource];
let [master] = this.workspace.roots;
let configuredFolders: URI[] = [master];
const config = this.getConfiguration<IWorkspaceFoldersConfiguration>('workspace');
if (config) {
const workspaceConfig = config[this.workspace.resource.toString()];
const workspaceConfig = config[master.toString()];
if (workspaceConfig) {
const additionalFolders = workspaceConfig.folders
.map(f => URI.parse(f))
@@ -112,20 +128,20 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
configuredFolders = distinct(configuredFolders, r => r.toString());
// Find changes
const changed = !equals(this.folders, configuredFolders, (r1, r2) => r1.toString() === r2.toString());
const changed = !equals(this.workspace.roots, configuredFolders, (r1, r2) => r1.toString() === r2.toString());
this.folders = configuredFolders;
this.workspace.setRoots(configuredFolders);
if (notify && changed) {
this._onDidChangeFolders.fire(configuredFolders);
this._onDidChangeWorkspaceRoots.fire(configuredFolders);
}
}
public getFolders(): URI[] {
return this.folders;
public getWorkspace(): IWorkspace {
return this.singleRootWorkspace;
}
public getWorkspace(): IWorkspace {
public getWorkspace2(): IWorkspace2 {
return this.workspace;
}
@@ -134,15 +150,15 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
}
public isInsideWorkspace(resource: URI): boolean {
return this.workspace ? this.workspace.isInsideWorkspace(resource) : false;
return this.workspace ? this.singleRootWorkspace.isInsideWorkspace(resource) : false;
}
public toWorkspaceRelativePath(resource: URI, toOSPath?: boolean): string {
return this.workspace ? this.workspace.toWorkspaceRelativePath(resource, toOSPath) : null;
return this.workspace ? this.singleRootWorkspace.toWorkspaceRelativePath(resource, toOSPath) : null;
}
public toResource(workspaceRelativePath: string): URI {
return this.workspace ? this.workspace.toResource(workspaceRelativePath) : null;
return this.workspace ? this.singleRootWorkspace.toResource(workspaceRelativePath) : null;
}
private onBaseConfigurationChanged(event: IConfigurationServiceEvent): void {
@@ -276,7 +292,7 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
// once: when invoked for the first time we fetch json files that contribute settings
if (!this.bulkFetchFromWorkspacePromise) {
this.bulkFetchFromWorkspacePromise = resolveStat(this.workspace.toResource(this.workspaceSettingsRootFolder)).then(stat => {
this.bulkFetchFromWorkspacePromise = resolveStat(this.toResource(this.workspaceSettingsRootFolder)).then(stat => {
if (!stat.isDirectory) {
return TPromise.as([]);
}
@@ -287,11 +303,11 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
return false; // only JSON files
}
return this.isWorkspaceConfigurationFile(this.workspace.toWorkspaceRelativePath(stat.resource)); // only workspace config files
return this.isWorkspaceConfigurationFile(this.toWorkspaceRelativePath(stat.resource)); // only workspace config files
}).map(stat => stat.resource));
}, err => [] /* never fail this call */)
.then((contents: IContent[]) => {
contents.forEach(content => this.workspaceFilePathToConfiguration[this.workspace.toWorkspaceRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content)));
contents.forEach(content => this.workspaceFilePathToConfiguration[this.toWorkspaceRelativePath(content.resource)] = TPromise.as(this.createConfigModel(content)));
}, errors.onUnexpectedError);
}
@@ -317,7 +333,7 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
continue; // only JSON files or the actual settings folder
}
const workspacePath = this.workspace.toWorkspaceRelativePath(resource);
const workspacePath = this.toWorkspaceRelativePath(resource);
if (!workspacePath) {
continue; // event is not inside workspace
}
@@ -353,7 +369,7 @@ export class WorkspaceConfigurationService extends Disposable implements IWorksp
}
private createConfigModel<T>(content: IContent): IConfigModel<T> {
const path = this.workspace.toWorkspaceRelativePath(content.resource);
const path = this.toWorkspaceRelativePath(content.resource);
if (path === WORKSPACE_CONFIG_DEFAULT_PATH) {
return new WorkspaceSettingsConfigModel<T>(content.value, content.resource.toString());
} else {

View File

@@ -27,7 +27,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IEditorInput, IEditorOptions, Position, Direction, IEditor, IResourceInput } from 'vs/platform/editor/common/editor';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IMessageService, IConfirmation } from 'vs/platform/message/common/message';
import { IWorkspace, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspace, IWorkspaceContextService, IWorkspace2 } from 'vs/platform/workspace/common/workspace';
import { ILifecycleService, ShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -66,16 +66,16 @@ export class TestContextService implements IWorkspaceContextService {
private workspace: any;
private options: any;
private _onDidChangeFolders: Emitter<URI[]>;
private _onDidChangeWorkspaceRoots: Emitter<URI[]>;
constructor(workspace: any = TestWorkspace, options: any = null) {
this.workspace = workspace;
this.options = options || Object.create(null);
this._onDidChangeFolders = new Emitter<URI[]>();
this._onDidChangeWorkspaceRoots = new Emitter<URI[]>();
}
public get onDidChangeFolders(): Event<URI[]> {
return this._onDidChangeFolders.event;
public get onDidChangeWorkspaceRoots(): Event<URI[]> {
return this._onDidChangeWorkspaceRoots.event;
}
public getFolders(): URI[] {
@@ -90,6 +90,10 @@ export class TestContextService implements IWorkspaceContextService {
return this.workspace;
}
public getWorkspace2(): IWorkspace2 {
return this.workspace ? { id: `${this.workspace.uid}`, roots: [this.workspace.resource] } : void 0;
}
public setWorkspace(workspace: any): void {
this.workspace = workspace;
}