From d860afddc374f3606f46f608ef456244aa7ea105 Mon Sep 17 00:00:00 2001 From: Greg Van Liew Date: Wed, 31 May 2017 10:09:55 -0700 Subject: [PATCH 001/145] ATA is Automatic Type Acquisition --- extensions/typescript/package.nls.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/typescript/package.nls.json b/extensions/typescript/package.nls.json index 6aab169b6fb..374860ba9c4 100644 --- a/extensions/typescript/package.nls.json +++ b/extensions/typescript/package.nls.json @@ -36,8 +36,8 @@ "typescript.selectTypeScriptVersion.title": "Select TypeScript Version", "jsDocCompletion.enabled": "Enable/disable auto JSDoc comments", "javascript.implicitProjectConfig.checkJs": "Enable/disable semantic checking of JavaScript files. Existing jsconfig.json or tsconfig.json files override this setting. Requires TypeScript >=2.3.1.", - "typescript.npm": "Specifies the path to the NPM install used for automatic typings acquisition. Requires TypeScript >= 2.3.4", - "typescript.check.npmIsInstalled": "Check if NPM is installed for automatic typings acquisition", + "typescript.npm": "Specifies the path to the NPM install used for Automatic Type Acquisition. Requires TypeScript >= 2.3.4.", + "typescript.check.npmIsInstalled": "Check if NPM is installed for Automatic Type Acquisition.", "javascript.nameSuggestions": "Enable/disable including unique names from the file in JavaScript suggestion lists.", "typescript.tsc.autoDetect": "Controls whether auto detection of tsc tasks is on or off." } From e94706d5b28270bc83b3ef648eb0c42cace7ecf7 Mon Sep 17 00:00:00 2001 From: Joao Date: Wed, 30 Aug 2017 09:30:25 +0200 Subject: [PATCH 002/145] fixes #30624 --- src/vs/platform/environment/node/environmentService.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 8823268a00a..8a71922baa6 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -31,9 +31,13 @@ function getUniqueUserId(): string { return crypto.createHash('sha256').update(username).digest('hex').substr(0, 6); } +// Read this before there's any chance it is overwritten +// Related to https://github.com/Microsoft/vscode/issues/30624 +const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR']; + function getNixIPCHandle(userDataPath: string, type: string): string { - if (process.env['XDG_RUNTIME_DIR']) { - return path.join(process.env['XDG_RUNTIME_DIR'], `${pkg.name}-${pkg.version}-${type}.sock`); + if (xdgRuntimeDir) { + return path.join(xdgRuntimeDir, `${pkg.name}-${pkg.version}-${type}.sock`); } return path.join(userDataPath, `${pkg.version}-${type}.sock`); } From 2f2ff9fc68bad096d611106c850ea30fd1fdbf1f Mon Sep 17 00:00:00 2001 From: Keegan Carruthers-Smith Date: Fri, 8 Sep 2017 22:47:38 +0200 Subject: [PATCH 003/145] Handle user information in URI Without this change encoding an URL like `git+ssh://git@github.com/Microsoft/vscode.git` results in `git+ssh://git%40github.com/Microsoft/vscode.git`. --- src/vs/base/common/uri.ts | 14 +++++++++++++- src/vs/base/test/common/uri.test.ts | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 043e9be8be9..39ad9e80805 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -301,8 +301,20 @@ export default class URI { parts.push('//'); } if (authority) { + let idx = authority.indexOf('@'); + if (idx !== -1) { + const userinfo = authority.substr(0, idx); + authority = authority.substr(idx + 1); + idx = userinfo.indexOf(':'); + if (idx === -1) { + parts.push(encoder(userinfo)); + } else { + parts.push(encoder(userinfo.substr(0, idx)), ':', encoder(userinfo.substr(idx + 1))); + } + parts.push('@'); + } authority = authority.toLowerCase(); - let idx = authority.indexOf(':'); + idx = authority.indexOf(':'); if (idx === -1) { parts.push(encoder(authority)); } else { diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 1e8340f98c7..3341b0bcb6a 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -368,6 +368,23 @@ suite('URI', () => { assert.equal(value.toString(), 'http://l%C3%B6calhost:8080/far'); }); + test('URI#toString, user information in authority', () => { + var value = URI.parse('http://foo:bar@localhost/far'); + assert.equal(value.toString(), 'http://foo:bar@localhost/far'); + + value = URI.parse('http://foo@localhost/far'); + assert.equal(value.toString(), 'http://foo@localhost/far'); + + value = URI.parse('http://foo:bAr@localhost:8080/far'); + assert.equal(value.toString(), 'http://foo:bAr@localhost:8080/far'); + + value = URI.parse('http://foo@localhost:8080/far'); + assert.equal(value.toString(), 'http://foo@localhost:8080/far'); + + value = URI.from({ scheme: 'http', authority: 'föö:bör@löcalhost:8080', path: '/far', query: undefined, fragment: undefined }); + assert.equal(value.toString(), 'http://f%C3%B6%C3%B6:b%C3%B6r@l%C3%B6calhost:8080/far'); + }); + test('correctFileUriToFilePath2', () => { var test = (input: string, expected: string) => { From 8396f97cbc85afdf1ef853e6cc0a4c5c74f7abf4 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Fri, 8 Sep 2017 17:20:23 -0700 Subject: [PATCH 004/145] Add a rootIndex property to FileStat to ensure sorting roots is stable --- src/vs/workbench/parts/files/browser/views/explorerViewer.ts | 3 +++ src/vs/workbench/parts/files/common/explorerModel.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index d67a2880f86..2e2de7ba747 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -569,6 +569,9 @@ export class FileSorter implements ISorter { public compare(tree: ITree, statA: FileStat, statB: FileStat): number { // Do not sort roots + if (statA.isRoot && statB.isRoot) { + return statA.rootIndex - statB.rootIndex; + } if (statA.isRoot) { return -1; } diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index e3d97b1d97b..831c371cc09 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -25,7 +25,7 @@ export class Model { private _roots: FileStat[]; constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { - const setRoots = () => this._roots = this.contextService.getWorkspace().roots.map(uri => new FileStat(uri, undefined)); + const setRoots = () => this._roots = this.contextService.getWorkspace().roots.map((uri, index) => new FileStat(uri, undefined, undefined, undefined, undefined, undefined, undefined, index)); this.contextService.onDidChangeWorkspaceRoots(() => setRoots()); setRoots(); } @@ -74,7 +74,7 @@ export class FileStat implements IFileStat { public exists: boolean; public isDirectoryResolved: boolean; - constructor(resource: URI, public root: FileStat, isDirectory?: boolean, hasChildren?: boolean, name: string = paths.basename(resource.fsPath), mtime?: number, etag?: string) { + constructor(resource: URI, public root: FileStat, isDirectory?: boolean, hasChildren?: boolean, name: string = paths.basename(resource.fsPath), mtime?: number, etag?: string, public rootIndex?: number) { this.resource = resource; this.name = name; this.isDirectory = !!isDirectory; From b12b198f07964b8e320bf5d7c2ead8c4eeccf2b2 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Fri, 8 Sep 2017 17:36:21 -0700 Subject: [PATCH 005/145] Tiny optimisation to tree sorting --- .../workbench/parts/files/browser/views/explorerViewer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 2e2de7ba747..17677e0cf7f 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -569,10 +569,10 @@ export class FileSorter implements ISorter { public compare(tree: ITree, statA: FileStat, statB: FileStat): number { // Do not sort roots - if (statA.isRoot && statB.isRoot) { - return statA.rootIndex - statB.rootIndex; - } if (statA.isRoot) { + if (statB.isRoot) { + return statA.rootIndex - statB.rootIndex; + } return -1; } if (statB.isRoot) { From e6dda15fd5f1e8184ee9a13e519c6c4a71570b53 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 14:36:47 +0200 Subject: [PATCH 006/145] Remove legacy workspace. Use first root of the workspace instead of legacy workspace resource. --- .../standalone/browser/simpleServices.ts | 11 ++-- src/vs/platform/workspace/common/workspace.ts | 52 +------------------ src/vs/workbench/electron-browser/main.ts | 9 ++-- .../extensions/browser/extensionsActions.ts | 2 +- .../electron-browser/task.contribution.ts | 2 +- .../electron-browser/terminalTaskSystem.ts | 2 +- .../parts/tasks/node/processRunnerDetector.ts | 8 +-- .../parts/tasks/node/processTaskSystem.ts | 2 +- .../configuration/node/configuration.ts | 16 +++--- .../quickopen.perf.integrationTest.ts | 5 +- .../textsearch.perf.integrationTest.ts | 5 +- .../workbench/test/workbenchTestServices.ts | 6 +-- 12 files changed, 30 insertions(+), 90 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 7863e391781..aea8a1ba989 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -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, ILegacyWorkspace, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace } 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'; @@ -527,16 +527,11 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { private readonly _onDidChangeWorkspaceRoots: Emitter = new Emitter(); public readonly onDidChangeWorkspaceRoots: Event = this._onDidChangeWorkspaceRoots.event; - private readonly legacyWorkspace: ILegacyWorkspace; private readonly workspace: IWorkspace; constructor() { - this.legacyWorkspace = { resource: URI.from({ scheme: SimpleWorkspaceContextService.SCHEME, authority: 'model', path: '/' }) }; - this.workspace = { id: '4064f6ec-cb38-4ad0-af64-ee6467e63c82', roots: [this.legacyWorkspace.resource], name: this.legacyWorkspace.resource.fsPath }; - } - - public getLegacyWorkspace(): ILegacyWorkspace { - return this.legacyWorkspace; + const resource = URI.from({ scheme: SimpleWorkspaceContextService.SCHEME, authority: 'model', path: '/' }); + this.workspace = { id: '4064f6ec-cb38-4ad0-af64-ee6467e63c82', roots: [resource], name: resource.fsPath }; } public getWorkspace(): IWorkspace { diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 4eeb0b8fb83..25e02e15d77 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -6,7 +6,6 @@ import URI from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import * as paths from 'vs/base/common/paths'; import { TrieMap } from 'vs/base/common/map'; import Event from 'vs/base/common/event'; import { isLinux } from 'vs/base/common/platform'; @@ -32,12 +31,6 @@ export interface IWorkspaceContextService { */ hasMultiFolderWorkspace(): boolean; - /** - * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened - * without workspace (empty); - */ - getLegacyWorkspace(): ILegacyWorkspace; - /** * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened * without workspace (empty); @@ -71,20 +64,6 @@ export interface IWorkspaceContextService { toResource: (workspaceRelativePath: string) => URI; } -export interface ILegacyWorkspace { - - /** - * the full uri of the workspace. this is a file:// URL to the location - * of the workspace on disk. - */ - resource: URI; - - /** - * creation time of the workspace folder if known - */ - ctime?: number; -} - export interface IWorkspace { /** @@ -108,34 +87,6 @@ export interface IWorkspace { readonly configuration?: URI; } -export class LegacyWorkspace implements ILegacyWorkspace { - private _name: string; - - constructor(private _resource: URI, private _ctime?: number) { - this._name = paths.basename(this._resource.fsPath) || this._resource.fsPath; - } - - public get resource(): URI { - return this._resource; - } - - public get name(): string { - return this._name; - } - - public get ctime(): number { - return this._ctime; - } - - public toResource(workspaceRelativePath: string, root?: URI): URI { - if (typeof workspaceRelativePath === 'string') { - return URI.file(paths.join(root ? root.fsPath : this._resource.fsPath, workspaceRelativePath)); - } - - return null; - } -} - export class Workspace implements IWorkspace { private _rootsMap: TrieMap = new TrieMap(); @@ -145,7 +96,8 @@ export class Workspace implements IWorkspace { public readonly id: string, private _name: string, roots: URI[], - private _configuration: URI = null + private _configuration: URI = null, + public readonly ctime?: number ) { this.roots = roots; } diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index f1b566e63da..fad53b83a01 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -16,7 +16,7 @@ import platform = require('vs/base/common/platform'); import paths = require('vs/base/common/paths'); import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace'; import { EmptyWorkspaceServiceImpl, WorkspaceServiceImpl, WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -148,7 +148,7 @@ function validateWorkspacePath(configuration: IWindowConfiguration): TPromiseworkspaceService.getWorkspace(); let workspaceId: string; let secondaryWorkspaceId: number; @@ -161,9 +161,8 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // in single folder mode we use the path of the opened folder as key for workspace storage // the ctime is used as secondary workspace id to clean up stale UI state if necessary else if (workspaceService.hasFolderWorkspace()) { - const legacyWorkspace = workspaceService.getLegacyWorkspace(); - workspaceId = legacyWorkspace.resource.toString(); - secondaryWorkspaceId = legacyWorkspace.ctime; + workspaceId = workspace.roots[0].toString(); + secondaryWorkspaceId = workspace.ctime; } // finaly, if we do not have a workspace open, we need to find another identifier for the window to store diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 7251ddc6149..0ab03cca7a8 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -1276,7 +1276,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { } private getOrCreateExtensionsFile(): TPromise<{ created: boolean, extensionsFileResource: URI }> { - const extensionsFileResource = URI.file(paths.join(this.contextService.getLegacyWorkspace().resource.fsPath, '.vscode', 'extensions.json')); // TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) + const extensionsFileResource = URI.file(paths.join(this.contextService.getWorkspace().roots[0].fsPath, '.vscode', 'extensions.json')); // TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) return this.fileService.resolveContent(extensionsFileResource).then(content => { return { created: false, extensionsFileResource }; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index b96413b5374..a1f13668c09 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1547,7 +1547,7 @@ class TaskService extends EventEmitter implements ITaskService { } private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.hasWorkspace() ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getLegacyWorkspace().resource }) : undefined; + let result = this.contextService.hasWorkspace() ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; if (!result) { return { config: undefined, hasParseErrors: false }; } diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index 39bd49ba690..b3f2037268f 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -647,7 +647,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { private resolveVariable(value: string): string { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 - return this.configurationResolverService.resolve(this.contextService.getLegacyWorkspace().resource, value); + return this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], value); } private resolveOptions(options: CommandOptions): CommandOptions { diff --git a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts index bbc05d0d7d4..22e79fe9aa2 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts @@ -156,7 +156,7 @@ export class ProcessRunnerDetector { this.taskConfiguration = config; this._stderr = []; this._stdout = []; - this._cwd = this.contextService.hasWorkspace() ? Paths.normalize(this.contextService.getLegacyWorkspace().resource.fsPath, true) : ''; + this._cwd = this.contextService.hasWorkspace() ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; } public get stderr(): string[] { @@ -175,7 +175,7 @@ export class ProcessRunnerDetector { let isShellCommand = !!this.taskConfiguration.isShellCommand; // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 return this.runDetection( - new LineProcess(this.taskConfiguration.command, this.configurationResolverService.resolve(this.contextService.getLegacyWorkspace().resource, args), isShellCommand, options), + new LineProcess(this.taskConfiguration.command, this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], args), isShellCommand, options), this.taskConfiguration.command, isShellCommand, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list); } else { if (detectSpecific) { @@ -219,10 +219,10 @@ export class ProcessRunnerDetector { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 let result = Objects.clone(options); if (result.cwd) { - result.cwd = this.configurationResolverService.resolve(this.contextService.getLegacyWorkspace().resource, result.cwd); + result.cwd = this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], result.cwd); } if (result.env) { - result.env = this.configurationResolverService.resolve(this.contextService.getLegacyWorkspace().resource, result.env); + result.env = this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], result.env); } return result; } diff --git a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts index b15509838dc..c320299767d 100644 --- a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts @@ -382,7 +382,7 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { private resolveVariable(value: string): string { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 - return this.configurationResolverService.resolve(this.contextService.getLegacyWorkspace().resource, value); + return this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], value); } public log(value: string): void { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 0f45a64cd69..4941a92ebec 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -18,7 +18,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { readFile, stat } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import * as extfs from 'vs/base/node/extfs'; -import { IWorkspaceContextService, IWorkspace, Workspace, ILegacyWorkspace, LegacyWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, Workspace } from 'vs/platform/workspace/common/workspace'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; @@ -178,7 +178,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat public _serviceBrand: any; protected workspace: Workspace = null; - protected legacyWorkspace: LegacyWorkspace = null; protected _configuration: Configuration; protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); @@ -195,10 +194,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this._configuration = new Configuration(new BaseConfiguration(new ConfigurationModel(), new ConfigurationModel()), new ConfigurationModel(), new StrictResourceMap>(), this.workspace); } - public getLegacyWorkspace(): ILegacyWorkspace { - return this.legacyWorkspace; - } - public getWorkspace(): IWorkspace { return this.workspace; } @@ -228,7 +223,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public toResource(workspaceRelativePath: string): URI { - return this.workspace ? this.legacyWorkspace.toResource(workspaceRelativePath) : null; + if (this.workspace && this.workspace.roots.length) { + return URI.file(paths.join(this.workspace.roots[0].fsPath, workspaceRelativePath)); + } + return null; } public initialize(trigger: boolean = true): TPromise { @@ -443,7 +441,6 @@ export class WorkspaceServiceImpl extends WorkspaceService { const workspaceId = (this.workspaceIdentifier as IWorkspaceIdentifier).id; const workspaceName = getWorkspaceLabel({ id: workspaceId, configPath: this.workspaceConfigPath.fsPath }, this.environmentService); this.workspace = new Workspace(workspaceId, workspaceName, workspaceFolders, this.workspaceConfigPath); - this.legacyWorkspace = new LegacyWorkspace(this.workspace.roots[0]); this._register(this.workspaceConfiguration.onDidUpdateConfiguration(() => this.onWorkspaceConfigurationChanged())); return null; }); @@ -511,8 +508,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { const ctime = isLinux ? workspaceStat.ino : workspaceStat.birthtime.getTime(); // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead! const id = createHash('md5').update(this.folderPath.fsPath).update(ctime ? String(ctime) : '').digest('hex'); const folder = URI.file(this.folderPath.fsPath); - this.workspace = new Workspace(id, paths.basename(this.folderPath.fsPath), [folder], null); - this.legacyWorkspace = new LegacyWorkspace(folder, ctime); + this.workspace = new Workspace(id, paths.basename(this.folderPath.fsPath), [folder], null, ctime); return TPromise.as(null); }); } diff --git a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts index d967748494d..e9495f05e70 100644 --- a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts @@ -7,7 +7,7 @@ import 'vs/workbench/parts/search/browser/search.contribution'; // load contributions import * as assert from 'assert'; -import { IWorkspaceContextService, LegacyWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ISearchService } from 'vs/platform/search/common/search'; @@ -30,6 +30,7 @@ import { SimpleConfigurationService } from 'vs/editor/standalone/browser/simpleS import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IModelService } from 'vs/editor/common/services/modelService'; +import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; namespace Timer { export interface ITimerEvent { @@ -74,7 +75,7 @@ suite('QuickOpen performance (integration)', () => { [IExperimentService, experimentService], [IConfigurationService, configurationService], [IModelService, new ModelServiceImpl(null, configurationService)], - [IWorkspaceContextService, new TestContextService(new LegacyWorkspace(URI.file(testWorkspacePath)))], + [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IWorkbenchEditorService, new TestEditorService()], [IEditorGroupService, new TestEditorGroupService()], [IEnvironmentService, TestEnvironmentService], diff --git a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts index b5b53cf077e..0cc049bd232 100644 --- a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts @@ -8,7 +8,7 @@ import 'vs/workbench/parts/search/browser/search.contribution'; // load contributions import * as assert from 'assert'; import * as fs from 'fs'; -import { IWorkspaceContextService, LegacyWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { ISearchService, IQueryOptions } from 'vs/platform/search/common/search'; @@ -33,6 +33,7 @@ import { SearchModel } from 'vs/workbench/parts/search/common/searchModel'; import { QueryBuilder } from 'vs/workbench/parts/search/common/queryBuilder'; import Event, * as event from 'vs/base/common/event'; +import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; declare var __dirname: string; @@ -61,7 +62,7 @@ suite('TextSearch performance (integration)', () => { [ITelemetryService, telemetryService], [IConfigurationService, configurationService], [IModelService, new ModelServiceImpl(null, configurationService)], - [IWorkspaceContextService, new TestContextService(new LegacyWorkspace(URI.file(testWorkspacePath)))], + [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IWorkbenchEditorService, new TestEditorService()], [IEditorGroupService, new TestEditorGroupService()], [IEnvironmentService, TestEnvironmentService], diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 44617592da0..22f11eefcd5 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -27,7 +27,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IEditorInput, IEditorOptions, Position, Direction, IEditor, IResourceInput, ITextEditorSelection } 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 { ILegacyWorkspace, IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace } 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'; @@ -106,10 +106,6 @@ export class TestContextService implements IWorkspaceContextService { return this.workspace && !!this.workspace.configuration; } - public getLegacyWorkspace(): ILegacyWorkspace { - return this.workspace ? { resource: this.workspace.roots[0] } : void 0; - } - public getWorkspace(): IWorkbenchWorkspace { return this.workspace; } From 6180e697d69507e60f0660f54471696daeda82ca Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 12 Sep 2017 16:03:29 +0200 Subject: [PATCH 007/145] debug repl: do not focus element on context menu fixes #34066 --- .../workbench/parts/debug/electron-browser/debugViewer.ts | 6 ++++-- src/vs/workbench/parts/debug/electron-browser/replViewer.ts | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index 4737247e86b..f069333aeea 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -209,7 +209,7 @@ export class BaseDebugController extends DefaultController { this.contributedContextMenu = menuService.createMenu(menuId, contextKeyService); } - public onContextMenu(tree: ITree, element: debug.IEnablement, event: ContextMenuEvent): boolean { + public onContextMenu(tree: ITree, element: debug.IEnablement, event: ContextMenuEvent, focusElement = true): boolean { if (event.target && event.target.tagName && event.target.tagName.toLowerCase() === 'input') { return false; } @@ -217,7 +217,9 @@ export class BaseDebugController extends DefaultController { event.preventDefault(); event.stopPropagation(); - tree.setFocus(element); + if (focusElement) { + tree.setFocus(element); + } if (this.actionProvider.hasSecondaryActions(tree, element)) { const anchor = { x: event.posx, y: event.posy }; diff --git a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts index 9ae5593472c..bfe1493d1d1 100644 --- a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts @@ -11,7 +11,7 @@ import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; import * as dom from 'vs/base/browser/dom'; import severity from 'vs/base/common/severity'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; -import { ITree, IAccessibilityProvider, IDataSource, IRenderer, IActionProvider } from 'vs/base/parts/tree/browser/tree'; +import { ITree, IAccessibilityProvider, ContextMenuEvent, IDataSource, IRenderer, IActionProvider } from 'vs/base/parts/tree/browser/tree'; import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults'; import { IExpressionContainer, IExpression } from 'vs/workbench/parts/debug/common/debug'; import { Model, OutputNameValueElement, Expression, OutputElement, Variable } from 'vs/workbench/parts/debug/common/debugModel'; @@ -431,4 +431,8 @@ export class ReplExpressionsController extends BaseDebugController { return true; } + + public onContextMenu(tree: ITree, element: any, event: ContextMenuEvent): boolean { + return super.onContextMenu(tree, element, event, false); + } } From 327d06f5a2983da22339daf1da04c58de431b1d0 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 12 Sep 2017 16:43:12 +0200 Subject: [PATCH 008/145] debug: only show exception widget when exception frame is focused fixes #29097 --- .../parts/debug/electron-browser/debugEditorContribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts index 9a2d6bfe963..bcb12909cf6 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugEditorContribution.ts @@ -365,7 +365,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { // First call stack frame that is available is the frame where exception has been thrown const exceptionSf = first(callStack, sf => sf.source && sf.source.available, undefined); - if (!exceptionSf) { + if (!exceptionSf || exceptionSf !== focusedSf) { this.closeExceptionWidget(); return; } From f75cee9513c476891850d0255d451279f5a2fce1 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 18:10:09 +0200 Subject: [PATCH 009/145] Introduce an API in workspace contet service to check current workspace is with given workspace identifier --- .../standalone/browser/simpleServices.ts | 5 ++++ src/vs/platform/workspace/common/workspace.ts | 6 +++++ src/vs/workbench/electron-browser/actions.ts | 4 ++-- .../page/electron-browser/welcomePage.ts | 24 ++----------------- .../configuration/node/configuration.ts | 23 +++++++++++++++++- .../workbench/test/workbenchTestServices.ts | 15 +++++++++++- 6 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index aea8a1ba989..d45c0f557cc 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -9,6 +9,7 @@ import Severity from 'vs/base/common/severity'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; import { IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, IConfigurationValues, Configuration, IConfigurationData, ConfigurationModel, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; +import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IEditor, IEditorInput, IEditorOptions, IEditorService, IResourceInput, Position } from 'vs/platform/editor/common/editor'; import { ICommandService, ICommand, ICommandEvent, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService'; @@ -561,4 +562,8 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { public toResource(workspaceRelativePath: string): URI { return URI.file(workspaceRelativePath); } + + public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { + return true; + } } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 25e02e15d77..880388b24e9 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -10,6 +10,7 @@ import { TrieMap } from 'vs/base/common/map'; import Event from 'vs/base/common/event'; import { isLinux } from 'vs/base/common/platform'; import { distinct } from 'vs/base/common/arrays'; +import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; export const IWorkspaceContextService = createDecorator('contextService'); @@ -53,6 +54,11 @@ export interface IWorkspaceContextService { */ getRoot(resource: URI): URI; + /** + * Return `true` if the current workspace has the given identifier otherwise `false`. + */ + isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean; + /** * Returns if the provided resource is inside the workspace or not. */ diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 2f7d94696bc..b6c05bc7097 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -766,8 +766,8 @@ export abstract class BaseOpenRecentAction extends Action { isCurrentWorkspaceInList = true; // we always show folder workspaces } else { const firstWorkspace = recentWorkspaces[0]; - if (firstWorkspace && !isSingleFolderWorkspaceIdentifier(firstWorkspace)) { - isCurrentWorkspaceInList = firstWorkspace.id === this.contextService.getWorkspace().id; + if (firstWorkspace) { + isCurrentWorkspaceInList = this.contextService.isCurrentWorkspace(firstWorkspace); } else { isCurrentWorkspaceInList = false; // this is an untitled workspace thereby } diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index 452f9863d31..03bfd0e28e9 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -35,7 +35,6 @@ import { used } from 'vs/workbench/parts/welcome/page/electron-browser/vs_code_w import { ILifecycleService, StartupKind } from 'vs/platform/lifecycle/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { tildify } from 'vs/base/common/labels'; -import { isLinux } from 'vs/base/common/platform'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { registerColor, focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { getExtraColor } from 'vs/workbench/parts/welcome/walkThrough/node/walkThroughUtils'; @@ -232,18 +231,8 @@ class WelcomePage { }); recentlyOpened.then(({ workspaces }) => { - const context = this.contextService.getWorkspace(); - workspaces = workspaces.filter(workspace => { - if (this.contextService.hasMultiFolderWorkspace() && typeof workspace !== 'string' && context.id === workspace.id) { - return false; // do not show current workspace - } - - if (this.contextService.hasFolderWorkspace() && isSingleFolderWorkspaceIdentifier(workspace) && this.pathEquals(context.roots[0].fsPath, workspace)) { - return false; // do not show current workspace (single folder case) - } - - return true; - }); + // Filter out the current workspace + workspaces = workspaces.filter(workspace => !this.contextService.isCurrentWorkspace(workspace)); if (!workspaces.length) { const recent = container.querySelector('.welcomePage') as HTMLElement; recent.classList.add('emptyRecent'); @@ -366,15 +355,6 @@ class WelcomePage { } } - private pathEquals(path1: string, path2: string): boolean { - if (!isLinux) { - path1 = path1.toLowerCase(); - path2 = path2.toLowerCase(); - } - - return path1 === path2; - } - private installExtension(extensionSuggestion: ExtensionSuggestion, strings: Strings): void { this.telemetryService.publicLog(strings.installEvent, { from: telemetryFrom, diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 4941a92ebec..5f3349926e5 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -33,7 +33,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry'; import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, schemaId } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; -import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspaceFolder, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; interface IStat { resource: URI; @@ -222,6 +222,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return !!this.getRoot(resource); } + public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { + if (!this.workspace) { + return false; + } + + if (this.workspace.configuration) { + return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; + } + + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + } + public toResource(workspaceRelativePath: string): URI { if (this.workspace && this.workspace.roots.length) { return URI.file(paths.join(this.workspace.roots[0].fsPath, workspaceRelativePath)); @@ -287,6 +299,15 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat // implemented by sub classes return TPromise.as(false); } + + private pathEquals(path1: string, path2: string): boolean { + if (!isLinux) { + path1 = path1.toLowerCase(); + path2 = path2.toLowerCase(); + } + + return path1 === path2; + } } export class EmptyWorkspaceServiceImpl extends WorkspaceService { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 22f11eefcd5..f9c8e2f2ddf 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -54,7 +54,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { isLinux } from 'vs/base/common/platform'; import { generateUuid } from 'vs/base/common/uuid'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; -import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { IPosition } from 'vs/editor/common/core/position'; @@ -137,6 +137,19 @@ export class TestContextService implements IWorkspaceContextService { public toResource(workspaceRelativePath: string): URI { return URI.file(paths.join('C:\\', workspaceRelativePath)); } + + public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + } + + private pathEquals(path1: string, path2: string): boolean { + if (!isLinux) { + path1 = path1.toLowerCase(); + path2 = path2.toLowerCase(); + } + + return path1 === path2; + } } export class TestTextFileService extends TextFileService { From 3d314e25eb1c95851a2dc3310beb1f79bc405fad Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 09:32:49 -0700 Subject: [PATCH 010/145] Fix ruby embedded source puctuator colorization --- .../themes/dimmed-monokai-color-theme.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index 31cd63a47bc..39ee42a7762 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -453,7 +453,9 @@ }, { "name": "Ruby Embedded Source", - "scope": "source.ruby.embedded.source", + "scope": [ + "punctuation.section.embedded.begin.ruby", + "punctuation.section.embedded.end.ruby"], "settings": { "foreground": "#D08442" } From ea663a872fee380dde945467f7f7fe4092c86fe2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 18:35:06 +0200 Subject: [PATCH 011/145] Simplify autofocus in recent workspaces list --- src/vs/workbench/electron-browser/actions.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index b6c05bc7097..494f3624d16 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -759,23 +759,10 @@ export abstract class BaseOpenRecentAction extends Action { const workspacePicks: IFilePickOpenEntry[] = recentWorkspaces.map((workspace, index) => toPick(workspace, index === 0 ? { label: nls.localize('workspaces', "workspaces") } : void 0, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.environmentService, !this.isQuickNavigate() ? this.removeAction : void 0)); const filePicks: IFilePickOpenEntry[] = recentFiles.map((p, index) => toPick(p, index === 0 ? { label: nls.localize('files', "files"), border: true } : void 0, FileKind.FILE, this.environmentService, !this.isQuickNavigate() ? this.removeAction : void 0)); - let isCurrentWorkspaceInList: boolean; - if (!this.contextService.hasWorkspace()) { - isCurrentWorkspaceInList = false; // we never show empty workspaces - } else if (this.contextService.hasFolderWorkspace()) { - isCurrentWorkspaceInList = true; // we always show folder workspaces - } else { - const firstWorkspace = recentWorkspaces[0]; - if (firstWorkspace) { - isCurrentWorkspaceInList = this.contextService.isCurrentWorkspace(firstWorkspace); - } else { - isCurrentWorkspaceInList = false; // this is an untitled workspace thereby - } - } - + let autoFocusSecondEntry: boolean = this.contextService.hasWorkspace(); // focus second entry when there is a workspace this.quickOpenService.pick([...workspacePicks, ...filePicks], { contextKey: inRecentFilesPickerContextKey, - autoFocus: { autoFocusFirstEntry: !isCurrentWorkspaceInList, autoFocusSecondEntry: isCurrentWorkspaceInList }, + autoFocus: { autoFocusFirstEntry: !autoFocusSecondEntry, autoFocusSecondEntry: autoFocusSecondEntry }, placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"), matchOnDescription: true, quickNavigateConfiguration: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : void 0 From dc2f6ec2a55596b6cfe95b58f829d80127dcd4b8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 09:49:40 -0700 Subject: [PATCH 012/145] Improve colorization of embedded start end puctuators across languages --- .../colorize-results/test-regex_coffee.json | 20 +++++----- .../test/colorize-results/test_coffee.json | 40 +++++++++---------- .../test/colorize-results/test_jsx.json | 40 +++++++++---------- .../colorize-results/issue-28354_php.json | 6 +-- .../php/test/colorize-results/test_php.json | 6 +-- .../ruby/test/colorize-results/test_rb.json | 20 +++++----- extensions/theme-defaults/themes/dark_vs.json | 2 +- .../themes/hc_black_defaults.json | 2 +- .../theme-defaults/themes/light_vs.json | 2 +- .../themes/monokai-color-theme.json | 2 +- .../theme-red/themes/Red-color-theme.json | 8 ---- 11 files changed, 70 insertions(+), 78 deletions(-) diff --git a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json index b6a7a06b854..1aa6d09a015 100644 --- a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json @@ -454,11 +454,11 @@ "c": "#{", "t": "source.coffee string.regexp.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -476,11 +476,11 @@ "c": "}", "t": "source.coffee string.regexp.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/coffeescript/test/colorize-results/test_coffee.json b/extensions/coffeescript/test/colorize-results/test_coffee.json index 55a97e8b7ef..63217562f0c 100644 --- a/extensions/coffeescript/test/colorize-results/test_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test_coffee.json @@ -311,11 +311,11 @@ "c": "#{", "t": "source.coffee meta.function-call.coffee meta.arguments.coffee string.quoted.double.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -333,11 +333,11 @@ "c": "}", "t": "source.coffee meta.function-call.coffee meta.arguments.coffee string.quoted.double.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -575,11 +575,11 @@ "c": "#{", "t": "source.coffee meta.function-call.coffee meta.arguments.coffee string.quoted.double.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -597,11 +597,11 @@ "c": "}", "t": "source.coffee meta.function-call.coffee meta.arguments.coffee string.quoted.double.coffee source.coffee.embedded.source punctuation.section.embedded.coffee", "r": { - "dark_plus": "punctuation.section.embedded.coffee: #569CD6", - "light_plus": "punctuation.section.embedded.coffee: #0000FF", - "dark_vs": "punctuation.section.embedded.coffee: #569CD6", - "light_vs": "punctuation.section.embedded.coffee: #0000FF", - "hc_black": "punctuation.section.embedded.coffee: #569CD6" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/javascript/test/colorize-results/test_jsx.json b/extensions/javascript/test/colorize-results/test_jsx.json index 7da4b94367c..349083b8c19 100644 --- a/extensions/javascript/test/colorize-results/test_jsx.json +++ b/extensions/javascript/test/colorize-results/test_jsx.json @@ -1664,11 +1664,11 @@ "c": "{", "t": "source.js meta.var.expr.js meta.objectliteral.js meta.object.member.js meta.function.expression.js meta.block.js meta.tag.without-attributes.js meta.jsx.children.tsx meta.tag.without-attributes.js meta.jsx.children.tsx meta.embedded.expression.js punctuation.section.embedded.begin.js", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -1686,11 +1686,11 @@ "c": "}", "t": "source.js meta.var.expr.js meta.objectliteral.js meta.object.member.js meta.function.expression.js meta.block.js meta.tag.without-attributes.js meta.jsx.children.tsx meta.tag.without-attributes.js meta.jsx.children.tsx meta.embedded.expression.js punctuation.section.embedded.end.js", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -1862,11 +1862,11 @@ "c": "{", "t": "source.js meta.var.expr.js meta.objectliteral.js meta.object.member.js meta.function.expression.js meta.block.js meta.tag.without-attributes.js meta.jsx.children.tsx meta.tag.js meta.embedded.expression.js punctuation.section.embedded.begin.js", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -1906,11 +1906,11 @@ "c": "}", "t": "source.js meta.var.expr.js meta.objectliteral.js meta.object.member.js meta.function.expression.js meta.block.js meta.tag.without-attributes.js meta.jsx.children.tsx meta.tag.js meta.embedded.expression.js punctuation.section.embedded.end.js", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/php/test/colorize-results/issue-28354_php.json b/extensions/php/test/colorize-results/issue-28354_php.json index 669388a960e..1fe8eed9596 100644 --- a/extensions/php/test/colorize-results/issue-28354_php.json +++ b/extensions/php/test/colorize-results/issue-28354_php.json @@ -73,7 +73,7 @@ "light_plus": "punctuation.section.embedded.begin.php: #800000", "dark_vs": "punctuation.section.embedded.begin.php: #569CD6", "light_vs": "punctuation.section.embedded.begin.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -458,7 +458,7 @@ "light_plus": "punctuation.section.embedded.end.php: #800000", "dark_vs": "punctuation.section.embedded.end.php: #569CD6", "light_vs": "punctuation.section.embedded.end.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -469,7 +469,7 @@ "light_plus": "punctuation.section.embedded.end.php: #800000", "dark_vs": "punctuation.section.embedded.end.php: #569CD6", "light_vs": "punctuation.section.embedded.end.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/php/test/colorize-results/test_php.json b/extensions/php/test/colorize-results/test_php.json index 5e1b41ed8e1..1e211bbafc1 100644 --- a/extensions/php/test/colorize-results/test_php.json +++ b/extensions/php/test/colorize-results/test_php.json @@ -227,7 +227,7 @@ "light_plus": "punctuation.section.embedded.begin.php: #800000", "dark_vs": "punctuation.section.embedded.begin.php: #569CD6", "light_vs": "punctuation.section.embedded.begin.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -3549,7 +3549,7 @@ "light_plus": "punctuation.section.embedded.end.php: #800000", "dark_vs": "punctuation.section.embedded.end.php: #569CD6", "light_vs": "punctuation.section.embedded.end.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -3560,7 +3560,7 @@ "light_plus": "punctuation.section.embedded.end.php: #800000", "dark_vs": "punctuation.section.embedded.end.php: #569CD6", "light_vs": "punctuation.section.embedded.end.php: #800000", - "hc_black": "default: #FFFFFF" + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/ruby/test/colorize-results/test_rb.json b/extensions/ruby/test/colorize-results/test_rb.json index a3c5163218e..be7150a63e0 100644 --- a/extensions/ruby/test/colorize-results/test_rb.json +++ b/extensions/ruby/test/colorize-results/test_rb.json @@ -2258,11 +2258,11 @@ "c": "#{", "t": "source.ruby string.interpolated.ruby meta.embedded.line.ruby punctuation.section.embedded.begin.ruby", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "string: #CE9178" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -2280,11 +2280,11 @@ "c": "}", "t": "source.ruby string.interpolated.ruby meta.embedded.line.ruby punctuation.section.embedded.end.ruby source.ruby", "r": { - "dark_plus": "meta.embedded: #D4D4D4", - "light_plus": "meta.embedded: #000000", - "dark_vs": "meta.embedded: #D4D4D4", - "light_vs": "meta.embedded: #000000", - "hc_black": "string: #CE9178" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json index 57dd332be52..0e5a993be3d 100644 --- a/extensions/theme-defaults/themes/dark_vs.json +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -252,7 +252,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded.coffee" + "punctuation.section.embedded" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index 986fa7cf615..9edb5f89b3a 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -231,7 +231,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded.coffee" + "punctuation.section.embedded" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json index 91f311a80a8..046624bc8c1 100644 --- a/extensions/theme-defaults/themes/light_vs.json +++ b/extensions/theme-defaults/themes/light_vs.json @@ -248,7 +248,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded.coffee" + "punctuation.section.embedded" ], "settings": { "foreground": "#0000ff" diff --git a/extensions/theme-monokai/themes/monokai-color-theme.json b/extensions/theme-monokai/themes/monokai-color-theme.json index a3152125248..89b753c660d 100644 --- a/extensions/theme-monokai/themes/monokai-color-theme.json +++ b/extensions/theme-monokai/themes/monokai-color-theme.json @@ -121,7 +121,7 @@ "name": "Template Definition", "scope": [ "punctuation.definition.template-expression", - "punctuation.section.embedded.coffee" + "punctuation.section.embedded" ], "settings": { "foreground": "#F92672" diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index 414ad2fb5e8..d9dcac4892d 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -169,14 +169,6 @@ "foreground": "#aa5507ff" } }, - { - "name": "String embedded-source", - "scope": "string.quoted source", - "settings": { - "fontStyle": "", - "foreground": "#9df39fff" - } - }, { "name": "String constant", "scope": "string constant", From 69bc9d6ac927e70a9b2f48eeb0d91d308e43a941 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 10:44:05 -0700 Subject: [PATCH 013/145] Update groovy and cshtml colorization tests --- .../test/colorize-results/test_groovy.json | 20 +++---- .../test/colorize-results/test_cshtml.json | 60 +++++++++---------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/extensions/groovy/test/colorize-results/test_groovy.json b/extensions/groovy/test/colorize-results/test_groovy.json index ee78a65becc..5d5b7db026b 100644 --- a/extensions/groovy/test/colorize-results/test_groovy.json +++ b/extensions/groovy/test/colorize-results/test_groovy.json @@ -9232,11 +9232,11 @@ "c": "${", "t": "source.groovy meta.definition.method.groovy meta.method.body.java string.quoted.double.groovy source.groovy.embedded.source punctuation.section.embedded.groovy", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -9254,11 +9254,11 @@ "c": "}", "t": "source.groovy meta.definition.method.groovy meta.method.body.java string.quoted.double.groovy source.groovy.embedded.source punctuation.section.embedded.groovy", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { diff --git a/extensions/razor/test/colorize-results/test_cshtml.json b/extensions/razor/test/colorize-results/test_cshtml.json index 2e3dbe31e97..e7eead2eeeb 100644 --- a/extensions/razor/test/colorize-results/test_cshtml.json +++ b/extensions/razor/test/colorize-results/test_cshtml.json @@ -14,11 +14,11 @@ "c": "{", "t": "text.html.cshtml section.embedded.source.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -333,11 +333,11 @@ "c": "{", "t": "text.html.cshtml section.embedded.source.cshtml section.embedded.source.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -1125,22 +1125,22 @@ "c": "}", "t": "text.html.cshtml section.embedded.source.cshtml section.embedded.source.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { "c": "}", "t": "text.html.cshtml section.embedded.source.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -3226,11 +3226,11 @@ "c": "@(", "t": "text.html.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { @@ -3270,11 +3270,11 @@ "c": ")", "t": "text.html.cshtml punctuation.section.embedded.begin.cshtml", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", - "dark_vs": "default: #D4D4D4", - "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "dark_plus": "punctuation.section.embedded: #569CD6", + "light_plus": "punctuation.section.embedded: #0000FF", + "dark_vs": "punctuation.section.embedded: #569CD6", + "light_vs": "punctuation.section.embedded: #0000FF", + "hc_black": "punctuation.section.embedded: #569CD6" } }, { From 35c8bc4daa2c5d538ab17a21b6885aad400fc16c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 11:04:02 -0700 Subject: [PATCH 014/145] Further improve colorization of embeded expressions - Add groovy embedded support - Make high contrast colorization consistent --- .../test/colorize-results/test_groovy.json | 10 +- .../test/colorize-results/12750_html.json | 24 +- .../test/colorize-results/25920_html.json | 34 +- .../html/test/colorize-results/test_html.json | 132 ++++---- .../test/colorize-results/test_jsx.json | 2 +- .../test/colorize-results/test_md.json | 26 +- .../colorize-results/issue-28354_php.json | 32 +- .../php/test/colorize-results/test_php.json | 314 +++++++++--------- .../theme-abyss/themes/abyss-color-theme.json | 2 +- extensions/theme-defaults/themes/dark_vs.json | 2 +- .../themes/hc_black_defaults.json | 10 + .../theme-defaults/themes/light_vs.json | 2 +- .../themes/kimbie-dark-color-theme.json | 2 +- .../themes/dimmed-monokai-color-theme.json | 2 +- .../themes/monokai-color-theme.json | 2 +- .../themes/quietlight-color-theme.json | 2 +- .../theme-red/themes/Red-color-theme.json | 13 +- .../themes/solarized-dark-color-theme.json | 2 +- .../themes/solarized-light-color-theme.json | 2 +- .../themes/tomorrow-night-blue-theme.json | 2 +- 20 files changed, 319 insertions(+), 298 deletions(-) diff --git a/extensions/groovy/test/colorize-results/test_groovy.json b/extensions/groovy/test/colorize-results/test_groovy.json index 5d5b7db026b..8d1191aa367 100644 --- a/extensions/groovy/test/colorize-results/test_groovy.json +++ b/extensions/groovy/test/colorize-results/test_groovy.json @@ -9243,11 +9243,11 @@ "c": "System.currentTimeMillis() - start", "t": "source.groovy meta.definition.method.groovy meta.method.body.java string.quoted.double.groovy source.groovy.embedded.source", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", - "dark_vs": "string: #CE9178", - "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "dark_plus": "source.groovy.embedded: #D4D4D4", + "light_plus": "source.groovy.embedded: #000000", + "dark_vs": "source.groovy.embedded: #D4D4D4", + "light_vs": "source.groovy.embedded: #000000", + "hc_black": "source.groovy.embedded: #FFFFFF" } }, { diff --git a/extensions/html/test/colorize-results/12750_html.json b/extensions/html/test/colorize-results/12750_html.json index 571e60f4ee5..a89b03aa84f 100644 --- a/extensions/html/test/colorize-results/12750_html.json +++ b/extensions/html/test/colorize-results/12750_html.json @@ -29,7 +29,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -51,7 +51,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -106,7 +106,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -128,7 +128,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -150,7 +150,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -194,7 +194,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -205,7 +205,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -293,7 +293,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -315,7 +315,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -337,7 +337,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -381,7 +381,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -392,7 +392,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/html/test/colorize-results/25920_html.json b/extensions/html/test/colorize-results/25920_html.json index 88dc0cc895c..16b71acbe88 100644 --- a/extensions/html/test/colorize-results/25920_html.json +++ b/extensions/html/test/colorize-results/25920_html.json @@ -62,7 +62,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -84,7 +84,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -139,7 +139,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -172,7 +172,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -194,7 +194,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -359,7 +359,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -381,7 +381,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -436,7 +436,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -458,7 +458,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -480,7 +480,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -502,7 +502,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -524,7 +524,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -601,7 +601,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -623,7 +623,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -678,7 +678,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -711,7 +711,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -733,7 +733,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/html/test/colorize-results/test_html.json b/extensions/html/test/colorize-results/test_html.json index 1609f7270c1..a1da5d2c393 100644 --- a/extensions/html/test/colorize-results/test_html.json +++ b/extensions/html/test/colorize-results/test_html.json @@ -480,7 +480,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -502,7 +502,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -557,7 +557,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -579,7 +579,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -590,7 +590,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -601,7 +601,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -623,7 +623,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -634,7 +634,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -656,7 +656,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -667,7 +667,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -689,7 +689,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -700,7 +700,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -733,7 +733,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -744,7 +744,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -755,7 +755,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -766,7 +766,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1129,7 +1129,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1151,7 +1151,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1283,7 +1283,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1305,7 +1305,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1448,7 +1448,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1470,7 +1470,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1492,7 +1492,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1536,7 +1536,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1547,7 +1547,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1558,7 +1558,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1580,7 +1580,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1602,7 +1602,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1613,7 +1613,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1624,7 +1624,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1657,7 +1657,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1701,7 +1701,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1712,7 +1712,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1745,7 +1745,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1756,7 +1756,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1767,7 +1767,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1800,7 +1800,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1844,7 +1844,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1855,7 +1855,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1866,7 +1866,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1877,7 +1877,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1888,7 +1888,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1899,7 +1899,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1910,7 +1910,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1932,7 +1932,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1943,7 +1943,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1954,7 +1954,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1976,7 +1976,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1987,7 +1987,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1998,7 +1998,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2009,7 +2009,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2020,7 +2020,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2042,7 +2042,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2053,7 +2053,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2064,7 +2064,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2075,7 +2075,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2086,7 +2086,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2097,7 +2097,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2119,7 +2119,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2141,7 +2141,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2152,7 +2152,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2163,7 +2163,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2174,7 +2174,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2185,7 +2185,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2196,7 +2196,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2207,7 +2207,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/javascript/test/colorize-results/test_jsx.json b/extensions/javascript/test/colorize-results/test_jsx.json index 349083b8c19..f12ab38729b 100644 --- a/extensions/javascript/test/colorize-results/test_jsx.json +++ b/extensions/javascript/test/colorize-results/test_jsx.json @@ -1888,7 +1888,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/markdown/test/colorize-results/test_md.json b/extensions/markdown/test/colorize-results/test_md.json index 4779949f7ae..c07d8316525 100644 --- a/extensions/markdown/test/colorize-results/test_md.json +++ b/extensions/markdown/test/colorize-results/test_md.json @@ -656,7 +656,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -678,7 +678,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -733,7 +733,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -744,7 +744,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1030,7 +1030,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1052,7 +1052,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1063,7 +1063,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1074,7 +1074,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1096,7 +1096,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1107,7 +1107,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1151,7 +1151,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1162,7 +1162,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1173,7 +1173,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/php/test/colorize-results/issue-28354_php.json b/extensions/php/test/colorize-results/issue-28354_php.json index 1fe8eed9596..d9f870d7f85 100644 --- a/extensions/php/test/colorize-results/issue-28354_php.json +++ b/extensions/php/test/colorize-results/issue-28354_php.json @@ -40,7 +40,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -62,7 +62,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -84,7 +84,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -106,7 +106,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -139,7 +139,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -161,7 +161,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -194,7 +194,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -205,7 +205,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -216,7 +216,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -227,7 +227,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -249,7 +249,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -414,7 +414,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -425,7 +425,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -436,7 +436,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -447,7 +447,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -480,7 +480,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/php/test/colorize-results/test_php.json b/extensions/php/test/colorize-results/test_php.json index 1e211bbafc1..6104d7b68b5 100644 --- a/extensions/php/test/colorize-results/test_php.json +++ b/extensions/php/test/colorize-results/test_php.json @@ -238,7 +238,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -260,7 +260,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -282,7 +282,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -293,7 +293,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -304,7 +304,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -315,7 +315,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -348,7 +348,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -359,7 +359,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -370,7 +370,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -436,7 +436,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -469,7 +469,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -491,7 +491,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -513,7 +513,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -557,7 +557,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -568,7 +568,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -612,7 +612,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -623,7 +623,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -667,7 +667,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -678,7 +678,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -722,7 +722,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -733,7 +733,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -777,7 +777,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -788,7 +788,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -832,7 +832,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -843,7 +843,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -887,7 +887,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -898,7 +898,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -942,7 +942,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -953,7 +953,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -964,7 +964,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -986,7 +986,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1008,7 +1008,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1019,7 +1019,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1030,7 +1030,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1041,7 +1041,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1052,7 +1052,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1074,7 +1074,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1107,7 +1107,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1129,7 +1129,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1151,7 +1151,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1162,7 +1162,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1195,7 +1195,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1217,7 +1217,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1239,7 +1239,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1250,7 +1250,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1294,7 +1294,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1305,7 +1305,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1316,7 +1316,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1327,7 +1327,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1360,7 +1360,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1382,7 +1382,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1404,7 +1404,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1437,7 +1437,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1448,7 +1448,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1459,7 +1459,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1492,7 +1492,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1514,7 +1514,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1525,7 +1525,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1547,7 +1547,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1558,7 +1558,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1602,7 +1602,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1613,7 +1613,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1624,7 +1624,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1646,7 +1646,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1679,7 +1679,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1712,7 +1712,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1723,7 +1723,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1745,7 +1745,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1778,7 +1778,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1789,7 +1789,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1800,7 +1800,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1811,7 +1811,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1855,7 +1855,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1866,7 +1866,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1877,7 +1877,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1888,7 +1888,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1910,7 +1910,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1921,7 +1921,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1932,7 +1932,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1965,7 +1965,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1976,7 +1976,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -1987,7 +1987,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2009,7 +2009,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2042,7 +2042,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2075,7 +2075,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2086,7 +2086,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2097,7 +2097,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2130,7 +2130,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2163,7 +2163,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2174,7 +2174,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2196,7 +2196,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2229,7 +2229,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2240,7 +2240,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2251,7 +2251,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2262,7 +2262,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2273,7 +2273,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2284,7 +2284,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2306,7 +2306,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2328,7 +2328,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2339,7 +2339,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2350,7 +2350,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2361,7 +2361,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2372,7 +2372,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2405,7 +2405,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2427,7 +2427,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2438,7 +2438,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2460,7 +2460,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2471,7 +2471,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2504,7 +2504,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2515,7 +2515,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2526,7 +2526,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2548,7 +2548,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2625,7 +2625,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2636,7 +2636,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2647,7 +2647,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2680,7 +2680,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2702,7 +2702,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2713,7 +2713,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2746,7 +2746,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2768,7 +2768,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2790,7 +2790,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2801,7 +2801,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2834,7 +2834,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2856,7 +2856,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2878,7 +2878,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2889,7 +2889,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2933,7 +2933,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2944,7 +2944,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2955,7 +2955,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2966,7 +2966,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2988,7 +2988,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -2999,7 +2999,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3032,7 +3032,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3054,7 +3054,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3076,7 +3076,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3087,7 +3087,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3098,7 +3098,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3109,7 +3109,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3142,7 +3142,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3164,7 +3164,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3186,7 +3186,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3197,7 +3197,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3208,7 +3208,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3219,7 +3219,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3241,7 +3241,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3362,7 +3362,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3373,7 +3373,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3384,7 +3384,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3428,7 +3428,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3439,7 +3439,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3450,7 +3450,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3461,7 +3461,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3483,7 +3483,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3505,7 +3505,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3516,7 +3516,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3527,7 +3527,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { @@ -3538,7 +3538,7 @@ "light_plus": "meta.embedded: #000000", "dark_vs": "meta.embedded: #D4D4D4", "light_vs": "meta.embedded: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "meta.embedded: #FFFFFF" } }, { diff --git a/extensions/theme-abyss/themes/abyss-color-theme.json b/extensions/theme-abyss/themes/abyss-color-theme.json index 6b1a0f1c474..bae5fd48804 100644 --- a/extensions/theme-abyss/themes/abyss-color-theme.json +++ b/extensions/theme-abyss/themes/abyss-color-theme.json @@ -8,7 +8,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#000c18", "foreground": "#6688cc" diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json index 0e5a993be3d..5c44ca0bbcc 100644 --- a/extensions/theme-defaults/themes/dark_vs.json +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -10,7 +10,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "foreground": "#D4D4D4", "background": "#1E1E1E" diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index 9edb5f89b3a..be310e8addd 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -14,6 +14,16 @@ "background": "#000000" } }, + { + "scope": [ + "meta.embedded", + "source.groovy.embedded" + ], + "settings": { + "foreground": "#FFFFFF", + "background": "#000000" + } + }, { "scope": "emphasis", "settings": { diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json index 046624bc8c1..9627e324264 100644 --- a/extensions/theme-defaults/themes/light_vs.json +++ b/extensions/theme-defaults/themes/light_vs.json @@ -4,7 +4,7 @@ "include": "./light_defaults.json", "tokenColors": [ { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "foreground": "#000000ff", "background":"#ffffffff" diff --git a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json index 3a14293383f..bad21aface9 100644 --- a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json +++ b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json @@ -55,7 +55,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#221a0f", "foreground": "#d3af86" diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index 39ee42a7762..398853e9988 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -52,7 +52,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#1e1e1e", "foreground": "#C5C8C6" diff --git a/extensions/theme-monokai/themes/monokai-color-theme.json b/extensions/theme-monokai/themes/monokai-color-theme.json index 89b753c660d..f7e45a6daf0 100644 --- a/extensions/theme-monokai/themes/monokai-color-theme.json +++ b/extensions/theme-monokai/themes/monokai-color-theme.json @@ -97,7 +97,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#272822", "foreground": "#F8F8F2" diff --git a/extensions/theme-quietlight/themes/quietlight-color-theme.json b/extensions/theme-quietlight/themes/quietlight-color-theme.json index 59c6834293f..9fd5ad62cee 100644 --- a/extensions/theme-quietlight/themes/quietlight-color-theme.json +++ b/extensions/theme-quietlight/themes/quietlight-color-theme.json @@ -8,7 +8,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#F5F5F5", "foreground": "#333333" diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index d9dcac4892d..b7db36b8fe4 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -69,7 +69,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#390000", "foreground": "#F8F8F8" @@ -385,6 +385,17 @@ "fontStyle": "", "foreground": "#fec758ff" } + }, + { + "name": "String interpolation ${}", + "scope": [ + "punctuation.definition.template-expression.begin", + "punctuation.definition.template-expression.end", + "punctuation.section.embedded" + ], + "settings": { + "foreground": "#ec0d1e" + } } ] } \ No newline at end of file diff --git a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json index 88e94050dee..c7bf6f68cb1 100644 --- a/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json +++ b/extensions/theme-solarized-dark/themes/solarized-dark-color-theme.json @@ -8,7 +8,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#002B36", "foreground": "#93A1A1" diff --git a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json index a7a4be6acb7..6d2b7146583 100644 --- a/extensions/theme-solarized-light/themes/solarized-light-color-theme.json +++ b/extensions/theme-solarized-light/themes/solarized-light-color-theme.json @@ -8,7 +8,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#FDF6E3", "foreground": "#657B83" diff --git a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json index 23bf67fb9a6..7163c4d671a 100644 --- a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json +++ b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-theme.json @@ -61,7 +61,7 @@ } }, { - "scope": "meta.embedded", + "scope": ["meta.embedded", "source.groovy.embedded"], "settings": { "background": "#002451", "foreground": "#FFFFFF" From b411fb2c2cace098d6eb95999a2b055962204819 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Sep 2017 11:38:35 -0700 Subject: [PATCH 015/145] Fix majority of terminal line/column cases Part of #34193 --- .../electron-browser/terminalLinkHandler.ts | 2 +- .../terminalLinkHandler.test.ts | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts index d16a97535cc..811bf77c390 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalLinkHandler.ts @@ -41,7 +41,7 @@ const lineAndColumnClause = [ // Changing any regex may effect this value, hence changes this as well if required. const winLineAndColumnMatchIndex = 12; -const unixLineAndColumnMatchIndex = 15; +const unixLineAndColumnMatchIndex = 23; // Each line and column clause have 6 groups (ie no. of expressions in round brackets) const lineAndColumnClauseGroupCount = 6; diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts index d351ba0dc6d..ba9f623fb9f 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -138,16 +138,16 @@ suite('Workbench - TerminalLinkHandler', () => { // { urlFormat: '{0} on line {1}, column {2}', line: '5', column: '3' }, // { urlFormat: '{0}:line {1}', line: '5' }, // { urlFormat: '{0}:line {1}, column {2}', line: '5', column: '3' }, - // { urlFormat: '{0}({1})', line: '5' }, - // { urlFormat: '{0} ({1})', line: '5' }, - // { urlFormat: '{0}({1},{2})', line: '5', column: '3' }, - // { urlFormat: '{0} ({1},{2})', line: '5', column: '3' }, - // { urlFormat: '{0}:{1}', line: '5' }, - // { urlFormat: '{0}:{1}:{2}', line: '5', column: '3' }, - // { urlFormat: '{0}[{1}]', line: '5' }, - // { urlFormat: '{0} [{1}]', line: '5' }, - // { urlFormat: '{0}[{1},{2}]', line: '5', column: '3' }, - // { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' } + { urlFormat: '{0}({1})', line: '5' }, + { urlFormat: '{0} ({1})', line: '5' }, + { urlFormat: '{0}({1},{2})', line: '5', column: '3' }, + { urlFormat: '{0} ({1},{2})', line: '5', column: '3' }, + { urlFormat: '{0}:{1}', line: '5' }, + { urlFormat: '{0}:{1}:{2}', line: '5', column: '3' }, + { urlFormat: '{0}[{1}]', line: '5' }, + { urlFormat: '{0} [{1}]', line: '5' }, + { urlFormat: '{0}[{1},{2}]', line: '5', column: '3' }, + { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' } ]; linkUrls.forEach(linkUrl => { From 3864be5b8ed86aa19a736c14931192df9bcfd485 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 11:52:12 -0700 Subject: [PATCH 016/145] Add rules for regex groups to vs dark+ and light+ themes --- .../colorize-results/test-regex_coffee.json | 12 ++++---- .../test/colorize-results/test_coffee.json | 28 +++++++++---------- .../python/test/colorize-results/test_py.json | 20 ++++++------- .../theme-defaults/themes/dark_plus.json | 23 +++++++++++++++ .../theme-defaults/themes/light_plus.json | 23 +++++++++++++++ 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json index 1aa6d09a015..cc3f1d3d7ab 100644 --- a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json @@ -69,8 +69,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -91,8 +91,8 @@ "c": "+", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -102,8 +102,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" diff --git a/extensions/coffeescript/test/colorize-results/test_coffee.json b/extensions/coffeescript/test/colorize-results/test_coffee.json index 63217562f0c..8c1254dfa9f 100644 --- a/extensions/coffeescript/test/colorize-results/test_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test_coffee.json @@ -1378,8 +1378,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1400,8 +1400,8 @@ "c": "+", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -1411,8 +1411,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1466,8 +1466,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1488,8 +1488,8 @@ "c": "*", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -1499,8 +1499,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", + "light_plus": "punctuation.definition.group.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1554,8 +1554,8 @@ "c": "$", "t": "source.coffee string.regexp.coffee keyword.control.anchor.regexp", "r": { - "dark_plus": "keyword.control: #C586C0", - "light_plus": "keyword.control: #AF00DB", + "dark_plus": "keyword.control.anchor.regexp: #C586C0", + "light_plus": "keyword.control.anchor.regexp: #09885A", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0" diff --git a/extensions/python/test/colorize-results/test_py.json b/extensions/python/test/colorize-results/test_py.json index b456114b1ed..4c183d734fa 100644 --- a/extensions/python/test/colorize-results/test_py.json +++ b/extensions/python/test/colorize-results/test_py.json @@ -5338,8 +5338,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5371,8 +5371,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5426,8 +5426,8 @@ "c": "+", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5470,8 +5470,8 @@ "c": "+", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5503,8 +5503,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator: #D4D4D4", - "light_plus": "keyword.operator: #000000", + "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", + "light_plus": "keyword.operator.quantifier.regexp: #0000FF", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index 972481b7e22..64ba03b2576 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -101,6 +101,29 @@ "settings": { "foreground": "#CE9178" } + }, + { + "scope": [ + "punctuation.definition.group.regexp", + "punctuation.definition.group.assertion.regexp", + "punctuation.definition.character-class.regexp", + "keyword.operator.negation.regexp" + ], + "settings": { + "foreground": "#d7ba7d" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#d4d4d4" + } + }, + { + "scope": "keyword.control.anchor.regexp", + "settings": { + "foreground": "#C586C0" + } } ] } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index c087a8f6ca1..a1dc19560a7 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -101,6 +101,29 @@ "settings": { "foreground": "#0451a5" } + }, + { + "scope": [ + "punctuation.definition.group.regexp", + "punctuation.definition.group.assertion.regexp", + "punctuation.definition.character-class.regexp", + "keyword.operator.negation.regexp" + ], + "settings": { + "foreground": "#ff0000" + } + }, + { + "scope": "keyword.operator.quantifier.regexp", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "keyword.control.anchor.regexp", + "settings": { + "foreground": "#09885a" + } } ] } \ No newline at end of file From 470c65d3731100ae4cd39ea11d94a63a45b742e3 Mon Sep 17 00:00:00 2001 From: Greg Van Liew Date: Tue, 12 Sep 2017 12:07:08 -0700 Subject: [PATCH 017/145] Fix for vscode-docs #1132 --- src/vs/vscode.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index edfa2a8dc69..2de5b818653 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -773,7 +773,7 @@ declare module 'vscode' { export interface ThemableDecorationRenderOptions { /** * Background color of the decoration. Use rgba() and define transparent background colors to play well with other decorations. - * Alternativly a color from the color registry an be [referenced](#ColorIdentifier). + * Alternatively a color from the color registry can be [referenced](#ThemeColor). */ backgroundColor?: string | ThemeColor; From 71d6af1f0139c5daff933b5c40e52a11b2441572 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 21:11:55 +0200 Subject: [PATCH 018/145] Update focussing recent workspaces list --- src/vs/workbench/electron-browser/actions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 494f3624d16..ee7d61c39a9 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -759,7 +759,9 @@ export abstract class BaseOpenRecentAction extends Action { const workspacePicks: IFilePickOpenEntry[] = recentWorkspaces.map((workspace, index) => toPick(workspace, index === 0 ? { label: nls.localize('workspaces', "workspaces") } : void 0, isSingleFolderWorkspaceIdentifier(workspace) ? FileKind.FOLDER : FileKind.ROOT_FOLDER, this.environmentService, !this.isQuickNavigate() ? this.removeAction : void 0)); const filePicks: IFilePickOpenEntry[] = recentFiles.map((p, index) => toPick(p, index === 0 ? { label: nls.localize('files', "files"), border: true } : void 0, FileKind.FILE, this.environmentService, !this.isQuickNavigate() ? this.removeAction : void 0)); - let autoFocusSecondEntry: boolean = this.contextService.hasWorkspace(); // focus second entry when there is a workspace + // focus second entry if the first recent workspace is the current workspace + let autoFocusSecondEntry: boolean = recentWorkspaces[0] && this.contextService.isCurrentWorkspace(recentWorkspaces[0]); + this.quickOpenService.pick([...workspacePicks, ...filePicks], { contextKey: inRecentFilesPickerContextKey, autoFocus: { autoFocusFirstEntry: !autoFocusSecondEntry, autoFocusSecondEntry: autoFocusSecondEntry }, From 77809680cb9897bc0570b89fe39e9dc7f64d4275 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Tue, 12 Sep 2017 12:17:55 -0700 Subject: [PATCH 019/145] Find the index of the root instead of storing it on the model --- .../workbench/parts/files/browser/views/explorerViewer.ts | 6 ++++-- src/vs/workbench/parts/files/common/explorerModel.ts | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 17677e0cf7f..3622e0e1ba4 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -549,7 +549,8 @@ export class FileSorter implements ISorter { private sortOrder: SortOrder; constructor( - @IConfigurationService private configurationService: IConfigurationService + @IConfigurationService private configurationService: IConfigurationService, + @IWorkspaceContextService private contextService: IWorkspaceContextService ) { this.toDispose = []; @@ -571,7 +572,8 @@ export class FileSorter implements ISorter { // Do not sort roots if (statA.isRoot) { if (statB.isRoot) { - return statA.rootIndex - statB.rootIndex; + const ws = this.contextService.getWorkspace(); + return ws.roots.indexOf(statA.resource) - ws.roots.indexOf(statB.resource); } return -1; } diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index 831c371cc09..e3d97b1d97b 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -25,7 +25,7 @@ export class Model { private _roots: FileStat[]; constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { - const setRoots = () => this._roots = this.contextService.getWorkspace().roots.map((uri, index) => new FileStat(uri, undefined, undefined, undefined, undefined, undefined, undefined, index)); + const setRoots = () => this._roots = this.contextService.getWorkspace().roots.map(uri => new FileStat(uri, undefined)); this.contextService.onDidChangeWorkspaceRoots(() => setRoots()); setRoots(); } @@ -74,7 +74,7 @@ export class FileStat implements IFileStat { public exists: boolean; public isDirectoryResolved: boolean; - constructor(resource: URI, public root: FileStat, isDirectory?: boolean, hasChildren?: boolean, name: string = paths.basename(resource.fsPath), mtime?: number, etag?: string, public rootIndex?: number) { + constructor(resource: URI, public root: FileStat, isDirectory?: boolean, hasChildren?: boolean, name: string = paths.basename(resource.fsPath), mtime?: number, etag?: string) { this.resource = resource; this.name = name; this.isDirectory = !!isDirectory; From 6dd25f084836d08fb26123c68a06af7a8e884732 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 21:29:54 +0200 Subject: [PATCH 020/145] Prevent to use hasFolderWorkspace instead check if workspace has configuration --- .../browser/actions/workspaceActions.ts | 26 ++++++------------- .../browser/parts/titlebar/titlebarPart.ts | 13 +++------- src/vs/workbench/electron-browser/window.ts | 9 ++++--- .../parts/files/browser/views/explorerView.ts | 6 ++--- .../preferences/browser/preferencesService.ts | 8 +----- .../node/workspaceMigrationService.ts | 23 ++++++++-------- 6 files changed, 32 insertions(+), 53 deletions(-) diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index d67da02d0a5..1fdf69fd626 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -112,7 +112,8 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); } - if (this.contextService.hasFolderWorkspace()) { + // Create a new workspace configuration if not exists. + if (!this.contextService.getWorkspace().configuration) { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); } @@ -199,35 +200,24 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { } public run(): TPromise { - if (!this.contextService.hasWorkspace()) { + const workspace = this.contextService.getWorkspace(); + if (!workspace) { this.messageService.show(Severity.Info, nls.localize('saveEmptyWorkspaceNotSupported', "Please open a workspace first to save.")); return TPromise.as(null); } const configPath = this.getNewWorkspaceConfigPath(); if (configPath) { - if (this.contextService.hasFolderWorkspace()) { - return this.saveFolderWorkspace(configPath); - } - - if (this.contextService.hasMultiFolderWorkspace()) { - return this.saveWorkspace(configPath); + if (!workspace.configuration) { + const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); + return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); } + return this.windowService.saveAndOpenWorkspace(configPath); } return TPromise.as(null); } - private saveWorkspace(configPath: string): TPromise { - return this.windowService.saveAndOpenWorkspace(configPath); - } - - private saveFolderWorkspace(configPath: string): TPromise { - const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); - - return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); - } - private getNewWorkspaceConfigPath(): string { const workspace = this.contextService.getWorkspace(); let defaultPath: string; diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 15f9670b6c8..645acce581a 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -192,15 +192,8 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - // Compute root resource - // Single Root Workspace: always the single root workspace in this case - // Multi Root Workspace: workspace configuration file - let root: URI; - if (this.contextService.hasMultiFolderWorkspace()) { - root = workspace.configuration; - } else if (this.contextService.hasFolderWorkspace()) { - root = workspace.roots[0]; - } + // root is either workspace configuration file or the first root folder + let root: URI = workspace ? workspace.configuration || workspace.roots[0] : null; // Compute folder resource // Single Root Workspace: always the root single workspace in this case @@ -219,7 +212,7 @@ export class TitlebarPart extends Part implements ITitleService { const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; const rootName = workspace ? workspace.name : ''; - const rootPath = workspace ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const rootPath = root ? labels.getPathLabel(root, void 0, this.environmentService) : ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 947b60ef708..adb1d75ce1a 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -286,18 +286,19 @@ export class ElectronWindow extends Themable { private onAddFolders(request: IAddFoldersRequest): void { const foldersToAdd = request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath)); + const workspace = this.contextService.getWorkspace(); - // Workspace: just add to workspace config - if (this.contextService.hasMultiFolderWorkspace()) { + // Just add to workspace config + if (workspace && workspace.configuration) { this.workspaceEditingService.addRoots(foldersToAdd).done(null, errors.onUnexpectedError); } - // Single folder or no workspace: create workspace and open + // No workspace or no workspace config: create workspace and open else { const workspaceFolders: URI[] = []; // Folder of workspace is the first of multi root workspace, so add it - if (this.contextService.hasFolderWorkspace()) { + if (workspace) { workspaceFolders.push(...this.contextService.getWorkspace().roots); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index e99e1d220a8..25a696a8b01 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -727,8 +727,8 @@ export class ExplorerView extends CollapsibleView { let targetsToExpand: URI[] = []; if (this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES]) { targetsToExpand = this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES].map((e: string) => URI.parse(e)); - } else if (this.contextService.hasFolderWorkspace() || (this.contextService.hasMultiFolderWorkspace() && this.model.roots.length === 1)) { - targetsToExpand = this.model.roots.map(root => root.resource); // always expand single folder workspace and multi folder workspace with only 1 root + } else if (this.model.roots.length === 1) { + targetsToExpand = this.model.roots.map(root => root.resource); // always expand if there is just one root } // First time refresh: Receive target through active editor input or selection and also include settings from previous session @@ -778,7 +778,7 @@ export class ExplorerView extends CollapsibleView { // Subsequent refresh: Merge stat into our local model and refresh tree modelStats.forEach((modelStat, index) => FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index])); - const input = this.contextService.hasFolderWorkspace() ? this.model.roots[0] : this.model; + const input = this.contextService.getWorkspace().configuration ? this.model : this.model.roots[0]; if (input === this.explorerViewer.getInput()) { return this.explorerViewer.refresh(); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index d37e517d962..473b25f5aa1 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -317,13 +317,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return URI.file(this.environmentService.appSettingsPath); case ConfigurationTarget.WORKSPACE: const workspace = this.contextService.getWorkspace(); - if (this.contextService.hasFolderWorkspace()) { - return this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]); - } - if (this.contextService.hasMultiFolderWorkspace()) { - return workspace.configuration; - } - return null; + return workspace ? workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]) : null; case ConfigurationTarget.FOLDER: const root = this.contextService.getRoot(resource); return root ? this.toResource(paths.join('.vscode', 'settings.json'), root) : null; diff --git a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts index 218ccc286d3..6fd3b0e3692 100644 --- a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts @@ -62,18 +62,19 @@ export class WorkspaceMigrationService implements IWorkspaceMigrationService { } private migrateConfiguration(toWorkspaceId: IWorkspaceIdentifier): TPromise { - if (!this.contextService.hasFolderWorkspace()) { - return TPromise.as(void 0); // return early if not a folder workspace is opened - } - - const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); - const targetWorkspaceConfiguration = {}; - for (const key of this.configurationService.keys().workspace) { - if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.WINDOW) { - targetWorkspaceConfiguration[key] = this.configurationService.lookup(key).workspace; + const workspace = this.contextService.getWorkspace(); + // Migrate configuration only if the current workspace configuration comes from folder + if (workspace && !workspace.configuration) { + const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); + const targetWorkspaceConfiguration = {}; + for (const key of this.configurationService.keys().workspace) { + if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.WINDOW) { + targetWorkspaceConfiguration[key] = this.configurationService.lookup(key).workspace; + } } - } - return this.jsonEditingService.write(URI.file(toWorkspaceId.configPath), { key: 'settings', value: targetWorkspaceConfiguration }, true); + return this.jsonEditingService.write(URI.file(toWorkspaceId.configPath), { key: 'settings', value: targetWorkspaceConfiguration }, true); + } + return TPromise.as(void 0); } } From 18ade0aac49473f20a92baf140d0dc7bb4dc5234 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 22:35:20 +0200 Subject: [PATCH 021/145] Revert "Prevent to use hasFolderWorkspace instead check if workspace has configuration" This reverts commit 6dd25f084836d08fb26123c68a06af7a8e884732. --- .../browser/actions/workspaceActions.ts | 26 +++++++++++++------ .../browser/parts/titlebar/titlebarPart.ts | 13 +++++++--- src/vs/workbench/electron-browser/window.ts | 9 +++---- .../parts/files/browser/views/explorerView.ts | 6 ++--- .../preferences/browser/preferencesService.ts | 8 +++++- .../node/workspaceMigrationService.ts | 25 +++++++++--------- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 1fdf69fd626..d67da02d0a5 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -112,8 +112,7 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); } - // Create a new workspace configuration if not exists. - if (!this.contextService.getWorkspace().configuration) { + if (this.contextService.hasFolderWorkspace()) { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); } @@ -200,24 +199,35 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { } public run(): TPromise { - const workspace = this.contextService.getWorkspace(); - if (!workspace) { + if (!this.contextService.hasWorkspace()) { this.messageService.show(Severity.Info, nls.localize('saveEmptyWorkspaceNotSupported', "Please open a workspace first to save.")); return TPromise.as(null); } const configPath = this.getNewWorkspaceConfigPath(); if (configPath) { - if (!workspace.configuration) { - const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); - return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); + if (this.contextService.hasFolderWorkspace()) { + return this.saveFolderWorkspace(configPath); + } + + if (this.contextService.hasMultiFolderWorkspace()) { + return this.saveWorkspace(configPath); } - return this.windowService.saveAndOpenWorkspace(configPath); } return TPromise.as(null); } + private saveWorkspace(configPath: string): TPromise { + return this.windowService.saveAndOpenWorkspace(configPath); + } + + private saveFolderWorkspace(configPath: string): TPromise { + const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); + + return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); + } + private getNewWorkspaceConfigPath(): string { const workspace = this.contextService.getWorkspace(); let defaultPath: string; diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 645acce581a..15f9670b6c8 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -192,8 +192,15 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - // root is either workspace configuration file or the first root folder - let root: URI = workspace ? workspace.configuration || workspace.roots[0] : null; + // Compute root resource + // Single Root Workspace: always the single root workspace in this case + // Multi Root Workspace: workspace configuration file + let root: URI; + if (this.contextService.hasMultiFolderWorkspace()) { + root = workspace.configuration; + } else if (this.contextService.hasFolderWorkspace()) { + root = workspace.roots[0]; + } // Compute folder resource // Single Root Workspace: always the root single workspace in this case @@ -212,7 +219,7 @@ export class TitlebarPart extends Part implements ITitleService { const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; const rootName = workspace ? workspace.name : ''; - const rootPath = root ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const rootPath = workspace ? labels.getPathLabel(root, void 0, this.environmentService) : ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index adb1d75ce1a..947b60ef708 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -286,19 +286,18 @@ export class ElectronWindow extends Themable { private onAddFolders(request: IAddFoldersRequest): void { const foldersToAdd = request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath)); - const workspace = this.contextService.getWorkspace(); - // Just add to workspace config - if (workspace && workspace.configuration) { + // Workspace: just add to workspace config + if (this.contextService.hasMultiFolderWorkspace()) { this.workspaceEditingService.addRoots(foldersToAdd).done(null, errors.onUnexpectedError); } - // No workspace or no workspace config: create workspace and open + // Single folder or no workspace: create workspace and open else { const workspaceFolders: URI[] = []; // Folder of workspace is the first of multi root workspace, so add it - if (workspace) { + if (this.contextService.hasFolderWorkspace()) { workspaceFolders.push(...this.contextService.getWorkspace().roots); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 25a696a8b01..e99e1d220a8 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -727,8 +727,8 @@ export class ExplorerView extends CollapsibleView { let targetsToExpand: URI[] = []; if (this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES]) { targetsToExpand = this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES].map((e: string) => URI.parse(e)); - } else if (this.model.roots.length === 1) { - targetsToExpand = this.model.roots.map(root => root.resource); // always expand if there is just one root + } else if (this.contextService.hasFolderWorkspace() || (this.contextService.hasMultiFolderWorkspace() && this.model.roots.length === 1)) { + targetsToExpand = this.model.roots.map(root => root.resource); // always expand single folder workspace and multi folder workspace with only 1 root } // First time refresh: Receive target through active editor input or selection and also include settings from previous session @@ -778,7 +778,7 @@ export class ExplorerView extends CollapsibleView { // Subsequent refresh: Merge stat into our local model and refresh tree modelStats.forEach((modelStat, index) => FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index])); - const input = this.contextService.getWorkspace().configuration ? this.model : this.model.roots[0]; + const input = this.contextService.hasFolderWorkspace() ? this.model.roots[0] : this.model; if (input === this.explorerViewer.getInput()) { return this.explorerViewer.refresh(); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 473b25f5aa1..d37e517d962 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -317,7 +317,13 @@ export class PreferencesService extends Disposable implements IPreferencesServic return URI.file(this.environmentService.appSettingsPath); case ConfigurationTarget.WORKSPACE: const workspace = this.contextService.getWorkspace(); - return workspace ? workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]) : null; + if (this.contextService.hasFolderWorkspace()) { + return this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]); + } + if (this.contextService.hasMultiFolderWorkspace()) { + return workspace.configuration; + } + return null; case ConfigurationTarget.FOLDER: const root = this.contextService.getRoot(resource); return root ? this.toResource(paths.join('.vscode', 'settings.json'), root) : null; diff --git a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts index 6fd3b0e3692..218ccc286d3 100644 --- a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts @@ -62,19 +62,18 @@ export class WorkspaceMigrationService implements IWorkspaceMigrationService { } private migrateConfiguration(toWorkspaceId: IWorkspaceIdentifier): TPromise { - const workspace = this.contextService.getWorkspace(); - // Migrate configuration only if the current workspace configuration comes from folder - if (workspace && !workspace.configuration) { - const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); - const targetWorkspaceConfiguration = {}; - for (const key of this.configurationService.keys().workspace) { - if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.WINDOW) { - targetWorkspaceConfiguration[key] = this.configurationService.lookup(key).workspace; - } - } - - return this.jsonEditingService.write(URI.file(toWorkspaceId.configPath), { key: 'settings', value: targetWorkspaceConfiguration }, true); + if (!this.contextService.hasFolderWorkspace()) { + return TPromise.as(void 0); // return early if not a folder workspace is opened } - return TPromise.as(void 0); + + const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); + const targetWorkspaceConfiguration = {}; + for (const key of this.configurationService.keys().workspace) { + if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.WINDOW) { + targetWorkspaceConfiguration[key] = this.configurationService.lookup(key).workspace; + } + } + + return this.jsonEditingService.write(URI.file(toWorkspaceId.configPath), { key: 'settings', value: targetWorkspaceConfiguration }, true); } } From 1b8f07fee9e7f2e2eab8c84954bf58fd7a4cf284 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Sep 2017 23:23:49 +0200 Subject: [PATCH 022/145] Introduce WorkspaceState representing Empty, Folder and Workspace. Adopt to use getWorkspaceState instead of hasFolderWorkspace or hasMultiFolderWorkspace --- .../standalone/browser/simpleServices.ts | 20 +++++---- src/vs/platform/workspace/common/workspace.ts | 25 ++++++----- .../mainThreadConfiguration.ts | 4 +- .../browser/actions/workspaceActions.ts | 36 +++++++--------- .../browser/parts/titlebar/titlebarPart.ts | 13 ++---- src/vs/workbench/electron-browser/main.ts | 43 +++++++++++-------- src/vs/workbench/electron-browser/window.ts | 6 +-- .../debug/electron-browser/debugViewer.ts | 4 +- .../parts/files/browser/views/explorerView.ts | 8 ++-- .../files/browser/views/explorerViewer.ts | 6 +-- .../preferences/browser/preferencesActions.ts | 4 +- .../browser/preferencesRenderers.ts | 4 +- .../preferences/browser/preferencesService.ts | 16 +++---- .../preferences/browser/preferencesWidgets.ts | 6 +-- .../parts/search/browser/searchViewlet.ts | 6 +-- .../parts/search/common/queryBuilder.ts | 4 +- .../configuration/node/configuration.ts | 30 +++++++------ .../node/configurationEditingService.ts | 6 +-- .../workspace/node/workspaceEditingService.ts | 4 +- .../node/workspaceMigrationService.ts | 4 +- .../api/mainThreadConfiguration.test.ts | 40 ++++++++--------- .../workbench/test/workbenchTestServices.ts | 20 +++++---- 22 files changed, 153 insertions(+), 156 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index d45c0f557cc..46cf48c9665 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -18,7 +18,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, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, WorkspaceState } 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'; @@ -539,6 +539,16 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { return this.workspace; } + public getWorkspaceState(): WorkspaceState { + if (this.workspace) { + if (this.workspace.configuration) { + return WorkspaceState.WORKSPACE; + } + return WorkspaceState.FOLDER; + } + return WorkspaceState.EMPTY; + } + public getRoot(resource: URI): URI { return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME ? this.workspace.roots[0] : void 0; } @@ -547,14 +557,6 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { return true; } - public hasFolderWorkspace(): boolean { - return true; - } - - public hasMultiFolderWorkspace(): boolean { - return false; - } - public isInsideWorkspace(resource: URI): boolean { return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME; } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 880388b24e9..a3144892141 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -14,24 +14,29 @@ import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platf export const IWorkspaceContextService = createDecorator('contextService'); +export enum WorkspaceState { + EMPTY = 1, + FOLDER, + WORKSPACE +} + export interface IWorkspaceContextService { _serviceBrand: any; + /** + * Return the state of the current workspace. + * + * WorkspaceState.EMPTY - if the application was opened with empty window or file + * WorkspaceState.FOLDER - if the application was opened with a folder + * WorkspaceState.WORKSPACE - if the application was opened with a workspace + */ + getWorkspaceState(): WorkspaceState; + /** * Returns if the application was opened with a workspace or not. */ hasWorkspace(): boolean; - /** - * Returns if the application was opened with a folder. - */ - hasFolderWorkspace(): boolean; - - /** - * Returns if the application was opened with a workspace that can have one or more folders. - */ - hasMultiFolderWorkspace(): boolean; - /** * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened * without workspace (empty); diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 36b5e975ef9..17c48b27a99 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext } from '../node/extHost.protocol'; @@ -51,7 +51,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { } private deriveConfigurationTarget(key: string, resource: URI): ConfigurationTarget { - if (resource && this._workspaceContextService.hasMultiFolderWorkspace()) { + if (resource && this._workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.RESOURCE) { return ConfigurationTarget.FOLDER; diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index d67da02d0a5..b1c67b005fa 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -11,7 +11,7 @@ import nls = require('vs/nls'); import { distinct } from 'vs/base/common/arrays'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import URI from 'vs/base/common/uri'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -112,7 +112,7 @@ export class AddRootFolderAction extends BaseWorkspacesAction { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); } - if (this.contextService.hasFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); } @@ -199,41 +199,34 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { } public run(): TPromise { - if (!this.contextService.hasWorkspace()) { + const workspaceState = this.contextService.getWorkspaceState(); + if (workspaceState === WorkspaceState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('saveEmptyWorkspaceNotSupported', "Please open a workspace first to save.")); return TPromise.as(null); } const configPath = this.getNewWorkspaceConfigPath(); if (configPath) { - if (this.contextService.hasFolderWorkspace()) { - return this.saveFolderWorkspace(configPath); - } + switch (workspaceState) { - if (this.contextService.hasMultiFolderWorkspace()) { - return this.saveWorkspace(configPath); + case WorkspaceState.FOLDER: + const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); + return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); + + case WorkspaceState.WORKSPACE: + return this.windowService.saveAndOpenWorkspace(configPath); } } return TPromise.as(null); } - private saveWorkspace(configPath: string): TPromise { - return this.windowService.saveAndOpenWorkspace(configPath); - } - - private saveFolderWorkspace(configPath: string): TPromise { - const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); - - return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); - } - private getNewWorkspaceConfigPath(): string { const workspace = this.contextService.getWorkspace(); let defaultPath: string; - if (this.contextService.hasMultiFolderWorkspace() && !this.isUntitledWorkspace(workspace.configuration.fsPath)) { + if (workspace.configuration && !this.isUntitledWorkspace(workspace.configuration.fsPath)) { defaultPath = workspace.configuration.fsPath; - } else if (workspace && workspace.roots.length > 0) { + } else if (workspace.roots.length > 0) { defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default } @@ -281,7 +274,8 @@ export class OpenWorkspaceConfigFileAction extends Action { ) { super(id, label); - this.enabled = this.workspaceContextService.hasMultiFolderWorkspace(); + const workspace = this.workspaceContextService.getWorkspace(); + this.enabled = workspace && !!workspace.configuration; } public run(): TPromise { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 15f9670b6c8..a0d4bee32ac 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -192,15 +192,8 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - // Compute root resource - // Single Root Workspace: always the single root workspace in this case - // Multi Root Workspace: workspace configuration file - let root: URI; - if (this.contextService.hasMultiFolderWorkspace()) { - root = workspace.configuration; - } else if (this.contextService.hasFolderWorkspace()) { - root = workspace.roots[0]; - } + // root resource is either workspace configuration file or the first root + let root: URI = workspace ? workspace.configuration || workspace.roots[0] : null; // Compute folder resource // Single Root Workspace: always the root single workspace in this case @@ -219,7 +212,7 @@ export class TitlebarPart extends Part implements ITitleService { const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; const rootName = workspace ? workspace.name : ''; - const rootPath = workspace ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const rootPath = root ? labels.getPathLabel(root, void 0, this.environmentService) : ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index fad53b83a01..e21601af993 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -16,7 +16,7 @@ import platform = require('vs/base/common/platform'); import paths = require('vs/base/common/paths'); import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); -import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, Workspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { EmptyWorkspaceServiceImpl, WorkspaceServiceImpl, WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -153,26 +153,31 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ let workspaceId: string; let secondaryWorkspaceId: number; - // in multi root workspace mode we use the provided ID as key for workspace storage - if (workspaceService.hasMultiFolderWorkspace()) { - workspaceId = uri.from({ path: workspace.id, scheme: 'root' }).toString(); - } + switch (workspaceService.getWorkspaceState()) { - // in single folder mode we use the path of the opened folder as key for workspace storage - // the ctime is used as secondary workspace id to clean up stale UI state if necessary - else if (workspaceService.hasFolderWorkspace()) { - workspaceId = workspace.roots[0].toString(); - secondaryWorkspaceId = workspace.ctime; - } + // in multi root workspace mode we use the provided ID as key for workspace storage + case WorkspaceState.WORKSPACE: + workspaceId = uri.from({ path: workspace.id, scheme: 'root' }).toString(); + break; - // finaly, if we do not have a workspace open, we need to find another identifier for the window to store - // workspace UI state. if we have a backup path in the configuration we can use that because this - // will be a unique identifier per window that is stable between restarts as long as there are - // dirty files in the workspace. - // We use basename() to produce a short identifier, we do not need the full path. We use a custom - // scheme so that we can later distinguish these identifiers from the workspace one. - else if (configuration.backupPath) { - workspaceId = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString(); + // in single folder mode we use the path of the opened folder as key for workspace storage + // the ctime is used as secondary workspace id to clean up stale UI state if necessary + case WorkspaceState.FOLDER: + workspaceId = workspace.roots[0].toString(); + secondaryWorkspaceId = workspace.ctime; + break; + + // finaly, if we do not have a workspace open, we need to find another identifier for the window to store + // workspace UI state. if we have a backup path in the configuration we can use that because this + // will be a unique identifier per window that is stable between restarts as long as there are + // dirty files in the workspace. + // We use basename() to produce a short identifier, we do not need the full path. We use a custom + // scheme so that we can later distinguish these identifiers from the workspace one. + case WorkspaceState.EMPTY: + if (configuration.backupPath) { + workspaceId = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString(); + } + break; } const disableStorage = !!environmentService.extensionTestsPath; // never keep any state when running extension tests! diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 947b60ef708..7dcdd449cae 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -39,7 +39,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { Themable } from 'vs/workbench/common/theme'; import { ipcRenderer as ipc, webFrame } from 'electron'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; const TextInputActions: IAction[] = [ @@ -288,7 +288,7 @@ export class ElectronWindow extends Themable { const foldersToAdd = request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath)); // Workspace: just add to workspace config - if (this.contextService.hasMultiFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { this.workspaceEditingService.addRoots(foldersToAdd).done(null, errors.onUnexpectedError); } @@ -297,7 +297,7 @@ export class ElectronWindow extends Themable { const workspaceFolders: URI[] = []; // Folder of workspace is the first of multi root workspace, so add it - if (this.contextService.hasFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { workspaceFolders.push(...this.contextService.getWorkspace().roots); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index 4737247e86b..682ee4afeab 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -22,7 +22,7 @@ import { DefaultController, DefaultDragAndDrop, ClickBehavior } from 'vs/base/pa import { Constants } from 'vs/editor/common/core/uint'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService, IMenu, MenuId } from 'vs/platform/actions/common/actions'; import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; @@ -524,7 +524,7 @@ export class CallStackRenderer implements IRenderer { private renderProcess(process: debug.IProcess, data: IProcessTemplateData): void { data.process.title = nls.localize({ key: 'process', comment: ['Process is a noun'] }, "Process"); - data.name.textContent = process.getName(this.contextService.hasMultiFolderWorkspace()); + data.name.textContent = process.getName(this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE); const stoppedThread = process.getAllThreads().filter(t => t.stopped).pop(); data.stateLabel.textContent = stoppedThread ? nls.localize('paused', "Paused") diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index e99e1d220a8..d642dd7adda 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -32,7 +32,7 @@ import { FileStat, Model } from 'vs/workbench/parts/files/common/explorerModel'; import { IListService } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -727,8 +727,8 @@ export class ExplorerView extends CollapsibleView { let targetsToExpand: URI[] = []; if (this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES]) { targetsToExpand = this.settings[ExplorerView.MEMENTO_EXPANDED_FOLDER_RESOURCES].map((e: string) => URI.parse(e)); - } else if (this.contextService.hasFolderWorkspace() || (this.contextService.hasMultiFolderWorkspace() && this.model.roots.length === 1)) { - targetsToExpand = this.model.roots.map(root => root.resource); // always expand single folder workspace and multi folder workspace with only 1 root + } else if (this.model.roots.length === 1) { + targetsToExpand = this.model.roots.map(root => root.resource); // always expand if there is just one root } // First time refresh: Receive target through active editor input or selection and also include settings from previous session @@ -778,7 +778,7 @@ export class ExplorerView extends CollapsibleView { // Subsequent refresh: Merge stat into our local model and refresh tree modelStats.forEach((modelStat, index) => FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index])); - const input = this.contextService.hasFolderWorkspace() ? this.model.roots[0] : this.model; + const input = this.contextService.getWorkspaceState() === WorkspaceState.FOLDER ? this.model.roots[0] : this.model; if (input === this.explorerViewer.getInput()) { return this.explorerViewer.refresh(); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index d67a2880f86..60c6519a6e2 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -35,7 +35,7 @@ import { FileStat, NewStatPlaceholder, Model } from 'vs/workbench/parts/files/co import { DragMouseEvent, IMouseEvent } from 'vs/base/browser/mouseEvent'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -829,7 +829,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // All (target = model) if (target instanceof Model) { - return this.contextService.hasMultiFolderWorkspace() ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(false) : DRAG_OVER_REJECT; // can only drop folders to workspace + return this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(false) : DRAG_OVER_REJECT; // can only drop folders to workspace } // All (target = file/folder) @@ -883,7 +883,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return void 0; // TODO@Ben multi root } - if (this.contextService.hasMultiFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { return this.workspaceEditingService.addRoots(folders); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts index 1cee1d5d6c2..d81800c8cfb 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts @@ -11,7 +11,7 @@ import { Action } from 'vs/base/common/actions'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; import { IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; export class OpenGlobalSettingsAction extends Action { @@ -101,7 +101,7 @@ export class OpenFolderSettingsAction extends Action { @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label); - this.enabled = this.workspaceContextService.hasMultiFolderWorkspace(); + this.enabled = this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE; } public run(): TPromise { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index ad7e9950cfe..85b89e72a96 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -31,7 +31,7 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; export interface IPreferencesRenderer extends IDisposable { @@ -1064,7 +1064,7 @@ class WorkspaceConfigurationRenderer extends Disposable { } public render(): void { - if (this.workspaceContextService.hasMultiFolderWorkspace()) { + if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, [])); const ranges: IRange[] = []; diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index d37e517d962..e1ce90b0cc2 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -16,7 +16,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { EditorInput } from 'vs/workbench/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { Position as EditorPosition, IEditor } from 'vs/platform/editor/common/editor'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; @@ -179,7 +179,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE, workspaceSettingsUri); } - if (this.contextService.hasMultiFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { return this.createEditableSettingsEditorModel(ConfigurationTarget.FOLDER, uri); } @@ -299,7 +299,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private resolveSettingsContentFromWorkspaceConfiguration(): TPromise { - if (this.contextService.hasMultiFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { return this.textModelResolverService.createModelReference(this.contextService.getWorkspace().configuration) .then(reference => { const model = reference.object.textEditorModel; @@ -317,13 +317,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return URI.file(this.environmentService.appSettingsPath); case ConfigurationTarget.WORKSPACE: const workspace = this.contextService.getWorkspace(); - if (this.contextService.hasFolderWorkspace()) { - return this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]); - } - if (this.contextService.hasMultiFolderWorkspace()) { - return workspace.configuration; - } - return null; + return workspace ? workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]) : null; case ConfigurationTarget.FOLDER: const root = this.contextService.getRoot(resource); return root ? this.toResource(paths.join('.vscode', 'settings.json'), root) : null; @@ -336,7 +330,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private createSettingsIfNotExists(target: ConfigurationTarget, resource: URI): TPromise { - if (this.contextService.hasMultiFolderWorkspace() && target === ConfigurationTarget.WORKSPACE) { + if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE && target === ConfigurationTarget.WORKSPACE) { if (!this.configurationService.keys().workspace.length) { return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { }); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index c2212fcb657..b6d575759aa 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -20,7 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ISettingsGroup, IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IAction, IActionRunner } from 'vs/base/common/actions'; import { attachInputBoxStyler, attachStylerCallback, attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -293,7 +293,7 @@ export class SettingsTargetsWidget extends Widget { private create(parent: HTMLElement): void { this.settingsTargetsContainer = DOM.append(parent, DOM.$('.settings-targets-widget')); - this.settingsTargetsContainer.style.width = this.workspaceContextService.hasMultiFolderWorkspace() ? '200px' : '150px'; + this.settingsTargetsContainer.style.width = this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE ? '200px' : '150px'; const targetElement = DOM.append(this.settingsTargetsContainer, DOM.$('.settings-target')); this.targetLabel = DOM.append(targetElement, DOM.$('.settings-target-label')); @@ -348,7 +348,7 @@ export class SettingsTargetsWidget extends Widget { }); } - if (this.workspaceContextService.hasMultiFolderWorkspace()) { + if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { actions.push(new Separator()); actions.push(...this.workspaceContextService.getWorkspace().roots.map((root, index) => { return { diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 6f6dce24526..6f27f6771ca 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -41,7 +41,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService, IConfirmation } from 'vs/platform/message/common/message'; import { IProgressService } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -468,7 +468,7 @@ export class SearchViewlet extends Viewlet { this.results = div; this.results.addClass('show-file-icons'); - let dataSource = new SearchDataSource(this.contextService.hasMultiFolderWorkspace()); + let dataSource = new SearchDataSource(this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE); let renderer = this.instantiationService.createInstance(SearchRenderer, this.getActionRunner(), this); let dnd = new SimpleFileResourceDragAndDrop(obj => obj instanceof FileMatch ? obj.resource() : void 0); @@ -872,7 +872,7 @@ export class SearchViewlet extends Viewlet { let folderPath = null; const workspace = this.contextService.getWorkspace(); if (workspace && resource) { - if (this.contextService.hasFolderWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { // Show relative path from the root for single-root mode folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); if (folderPath && folderPath !== '.') { diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 51e17c9a4fb..5c4ccaefcc8 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -12,7 +12,7 @@ import * as glob from 'vs/base/common/glob'; import * as paths from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import uri from 'vs/base/common/uri'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IPatternInfo, IQueryOptions, IFolderQuery, ISearchQuery, QueryType, ISearchConfiguration, getExcludes, pathIncludedInQuery } from 'vs/platform/search/common/search'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -213,7 +213,7 @@ export class QueryBuilder { } const workspace = this.workspaceContextService.getWorkspace(); - if (this.workspaceContextService.hasFolderWorkspace()) { + if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.FOLDER) { // TODO: @Sandy Try checking workspace folders length instead. return [paths.normalize( paths.join(workspace.roots[0].fsPath, searchPath))]; } else if (searchPath === './') { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 5f3349926e5..4a621ea0883 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -18,7 +18,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { readFile, stat } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import * as extfs from 'vs/base/node/extfs'; -import { IWorkspaceContextService, IWorkspace, Workspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, Workspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; @@ -198,18 +198,20 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.workspace; } + public getWorkspaceState(): WorkspaceState { + if (this.workspace) { + if (this.workspace.configuration) { + return WorkspaceState.WORKSPACE; + } + return WorkspaceState.FOLDER; + } + return WorkspaceState.EMPTY; + } + public hasWorkspace(): boolean { return !!this.workspace; } - public hasFolderWorkspace(): boolean { - return this.workspace && !this.workspace.configuration; - } - - public hasMultiFolderWorkspace(): boolean { - return this.workspace && !!this.workspace.configuration; - } - public getRoot(resource: URI): URI { return this.workspace ? this.workspace.getRoot(resource) : null; } @@ -373,7 +375,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } public getUnsupportedWorkspaceKeys(): string[] { - return this.hasFolderWorkspace() ? this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).workspaceSettingsConfig.unsupportedKeys : []; + return this.getWorkspaceState() === WorkspaceState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).workspaceSettingsConfig.unsupportedKeys : []; } public initialize(trigger: boolean = true): TPromise { @@ -382,7 +384,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { .then(() => super.initialize(trigger)); } - if (this.hasMultiFolderWorkspace()) { + if (this.workspaceConfigPath) { return this.workspaceConfiguration.load(this.workspaceConfigPath) .then(() => super.initialize(trigger)); } @@ -536,7 +538,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { private initCachesForFolders(folders: URI[]): void { for (const folder of folders) { - this.cachedFolderConfigs.set(folder, this._register(new FolderConfiguration(folder, this.workspaceSettingsRootFolder, this.hasMultiFolderWorkspace() ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW))); + this.cachedFolderConfigs.set(folder, this._register(new FolderConfiguration(folder, this.workspaceSettingsRootFolder, this.getWorkspaceState() === WorkspaceState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW))); this.updateFolderConfiguration(folder, new FolderConfigurationModel(new FolderSettingsModel(null), [], ConfigurationScope.RESOURCE), false); } } @@ -605,7 +607,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { private updateFolderConfiguration(folder: URI, folderConfiguration: FolderConfigurationModel, compare: boolean): boolean { let configurationChanged = this._configuration.updateFolderConfiguration(folder, folderConfiguration, compare); - if (this.hasFolderWorkspace()) { + if (this.getWorkspaceState() === WorkspaceState.FOLDER) { // Workspace configuration changed configurationChanged = this.updateWorkspaceConfiguration(compare) || configurationChanged; } @@ -613,7 +615,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } private updateWorkspaceConfiguration(compare: boolean): boolean { - const workspaceConfiguration = this.hasMultiFolderWorkspace() ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.roots[0]); + const workspaceConfiguration = this.getWorkspaceState() === WorkspaceState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.roots[0]); return this._configuration.updateWorkspaceConfiguration(workspaceConfiguration, compare); } diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index e4568ab9394..cc950d2e3c3 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -21,7 +21,7 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Registry } from 'vs/platform/registry/common/platform'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IConfigurationService, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; @@ -332,10 +332,10 @@ export class ConfigurationEditingService implements IConfigurationEditingService if (workspace) { if (target === ConfigurationTarget.WORKSPACE) { - return this.contextService.hasMultiFolderWorkspace() ? workspace.configuration : this.toResource(relativePath, workspace.roots[0]); + return workspace.configuration || this.toResource(relativePath, workspace.roots[0]); } - if (target === ConfigurationTarget.FOLDER && this.contextService.hasMultiFolderWorkspace()) { + if (target === ConfigurationTarget.FOLDER && this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { if (resource) { const root = this.contextService.getRoot(resource); if (root) { diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index 33cbf289a08..bd896c78398 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -53,10 +53,10 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { } private isSupported(): boolean { - // TODO@Ben multi root + const workspace = this.contextService.getWorkspace(); return ( this.environmentService.appQuality !== 'stable' // not yet enabled in stable - && this.contextService.hasMultiFolderWorkspace() // we need a multi folder workspace to begin with + && workspace && !!workspace.configuration // we need a workspace configuration file to begin with ); } diff --git a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts index 218ccc286d3..0ad6a488fae 100644 --- a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { once } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -62,7 +62,7 @@ export class WorkspaceMigrationService implements IWorkspaceMigrationService { } private migrateConfiguration(toWorkspaceId: IWorkspaceIdentifier): TPromise { - if (!this.contextService.hasFolderWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.FOLDER) { return TPromise.as(void 0); // return early if not a folder workspace is opened } diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts index effdeecbea4..95d7f71552a 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts @@ -10,7 +10,7 @@ import * as sinon from 'sinon'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { MainThreadConfiguration } from 'vs/workbench/api/electron-browser/mainThreadConfiguration'; import { ConfigurationTarget, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; @@ -56,7 +56,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); @@ -65,7 +65,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); @@ -74,7 +74,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); @@ -83,7 +83,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); @@ -92,7 +92,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -101,7 +101,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -110,7 +110,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); @@ -119,7 +119,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to folder', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); @@ -128,7 +128,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with user configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.USER, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -137,7 +137,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with workspace configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -146,7 +146,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with folder configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.FOLDER, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -155,7 +155,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); @@ -164,7 +164,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); @@ -173,7 +173,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); @@ -182,7 +182,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); @@ -191,7 +191,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); @@ -200,7 +200,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); @@ -209,7 +209,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => false }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); @@ -218,7 +218,7 @@ suite('ExtHostConfiguration', function () { }); test('remove configuration without configuration target defaults to folder', function () { - instantiationService.stub(IWorkspaceContextService, { hasMultiFolderWorkspace: () => true }); + instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index f9c8e2f2ddf..bdd3aed7bb9 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -27,7 +27,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IEditorInput, IEditorOptions, Position, Direction, IEditor, IResourceInput, ITextEditorSelection } 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 { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace, WorkspaceState } 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'; @@ -94,18 +94,20 @@ export class TestContextService implements IWorkspaceContextService { return this.workspace ? this.workspace.roots : []; } + public getWorkspaceState(): WorkspaceState { + if (this.workspace) { + if (this.workspace.configuration) { + return WorkspaceState.WORKSPACE; + } + return WorkspaceState.FOLDER; + } + return WorkspaceState.EMPTY; + } + public hasWorkspace(): boolean { return !!this.workspace; } - public hasFolderWorkspace(): boolean { - return this.workspace && !this.workspace.configuration; - } - - public hasMultiFolderWorkspace(): boolean { - return this.workspace && !!this.workspace.configuration; - } - public getWorkspace(): IWorkbenchWorkspace { return this.workspace; } From 3014483db0be67eec255c1a40d7613c9a5d4bb1d Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 12 Sep 2017 23:37:38 +0200 Subject: [PATCH 023/145] [css] update service --- extensions/css/server/npm-shrinkwrap.json | 4 ++-- extensions/css/server/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/css/server/npm-shrinkwrap.json b/extensions/css/server/npm-shrinkwrap.json index eeafae21433..2c2d280b1a2 100644 --- a/extensions/css/server/npm-shrinkwrap.json +++ b/extensions/css/server/npm-shrinkwrap.json @@ -3,9 +3,9 @@ "version": "1.0.0", "dependencies": { "vscode-css-languageservice": { - "version": "2.1.4", + "version": "2.1.6", "from": "vscode-css-languageservice@next", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-2.1.6.tgz" }, "vscode-jsonrpc": { "version": "3.3.1", diff --git a/extensions/css/server/package.json b/extensions/css/server/package.json index ad6c972e571..b62b50928bf 100644 --- a/extensions/css/server/package.json +++ b/extensions/css/server/package.json @@ -8,7 +8,7 @@ "node": "*" }, "dependencies": { - "vscode-css-languageservice": "^2.1.4", + "vscode-css-languageservice": "^2.1.6", "vscode-languageserver": "3.4.0-next.6", "vscode-languageserver-protocol": "^3.1.1" }, From 5c12dc3e1025e83975f86e2e342ee33166dbf3ca Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 12 Sep 2017 23:38:13 +0200 Subject: [PATCH 024/145] [html] update service --- extensions/html/server/npm-shrinkwrap.json | 8 ++++---- extensions/html/server/package.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/html/server/npm-shrinkwrap.json b/extensions/html/server/npm-shrinkwrap.json index 62a5bf9b691..52f9b38450f 100644 --- a/extensions/html/server/npm-shrinkwrap.json +++ b/extensions/html/server/npm-shrinkwrap.json @@ -3,14 +3,14 @@ "version": "1.0.0", "dependencies": { "vscode-css-languageservice": { - "version": "2.1.4", + "version": "2.1.6", "from": "vscode-css-languageservice@next", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-2.1.6.tgz" }, "vscode-html-languageservice": { - "version": "2.0.7", + "version": "2.0.8", "from": "vscode-html-languageservice@next", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-2.0.7.tgz" + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-2.0.8.tgz" }, "vscode-jsonrpc": { "version": "3.3.1", diff --git a/extensions/html/server/package.json b/extensions/html/server/package.json index 3cac05b7da9..8bcae7d7d90 100644 --- a/extensions/html/server/package.json +++ b/extensions/html/server/package.json @@ -8,8 +8,8 @@ "node": "*" }, "dependencies": { - "vscode-css-languageservice": "^2.1.4", - "vscode-html-languageservice": "^2.0.7", + "vscode-css-languageservice": "^2.1.6", + "vscode-html-languageservice": "^2.0.8", "vscode-languageserver": "3.4.0-next.6", "vscode-languageserver-protocol": "^3.1.1", "vscode-languageserver-types": "^3.3.0", From 440b9abf1f89ef1e10376f1eb8feda139330c001 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Sep 2017 15:07:37 -0700 Subject: [PATCH 025/145] Uplevel xterm.js Fixes #33955 --- npm-shrinkwrap.json | 2 +- src/vs/monaco.d.ts | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 24cdd888a1c..9390aaa0586 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "3.0.0", "from": "Tyriar/xterm.js#vscode-release/1.17", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#c3039b4d63b5c0e4a0c993e04714ad62fd056185" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#7e2af6fd7b740a20938a06aeaeef5056988d1b59" }, "yauzl": { "version": "2.8.0", diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 467ac20a374..6dafcfb3478 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2975,7 +2975,7 @@ declare module monaco.editor { * Accept suggestions on ENTER. * Defaults to 'on'. */ - acceptSuggestionOnEnter?: boolean | 'on' | 'smart' | 'off'; + acceptSuggestionOnEnter?: 'on' | 'smart' | 'off'; /** * Accept suggestions on provider defined characters. * Defaults to true. @@ -4459,7 +4459,7 @@ declare module monaco.languages { * The human-readable doc-comment of this signature. Will be shown * in the UI but can be omitted. */ - documentation?: string | IMarkdownString; + documentation?: string; } /** @@ -4477,7 +4477,7 @@ declare module monaco.languages { * The human-readable doc-comment of this signature. Will be shown * in the UI but can be omitted. */ - documentation?: string | IMarkdownString; + documentation?: string; /** * The parameters of this signature. */ @@ -4807,12 +4807,11 @@ declare module monaco.languages { } /** - * Represents a color format + * A color formatter. */ - export enum ColorFormat { - RGB = 0, - HEX = 1, - HSL = 2, + export interface IColorFormatter { + readonly supportsTransparency: boolean; + format(color: IColor): string; } /** @@ -4827,6 +4826,10 @@ declare module monaco.languages { * The color represented in this range. */ color: IColor; + /** + * The available formats for this specific color. + */ + formatters: IColorFormatter[]; } /** @@ -4837,10 +4840,6 @@ declare module monaco.languages { * Provides the color ranges for a specific model. */ provideColorRanges(model: editor.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable; - /** - * Provide the string representation for a color. - */ - resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable; } export interface IResourceEdit { From 246cead34f3854bb0e4a2e1101e6f4b52c6ebd25 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Tue, 12 Sep 2017 15:39:32 -0700 Subject: [PATCH 026/145] Remove duplicate event firing of onDidClose --- src/vs/editor/contrib/referenceSearch/browser/peekViewWidget.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/editor/contrib/referenceSearch/browser/peekViewWidget.ts b/src/vs/editor/contrib/referenceSearch/browser/peekViewWidget.ts index 1d912e8d055..a0a78bac128 100644 --- a/src/vs/editor/contrib/referenceSearch/browser/peekViewWidget.ts +++ b/src/vs/editor/contrib/referenceSearch/browser/peekViewWidget.ts @@ -174,7 +174,6 @@ export abstract class PeekViewWidget extends ZoneWidget { if (!this._isShowing && heightInPixel < 0) { // Looks like the view zone got folded away! this.dispose(); - this._onDidClose.fire(this); return; } From 02350be480653c4615f962e06f92d6048606c0e4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 12 Sep 2017 16:12:13 -0700 Subject: [PATCH 027/145] Bump vscode-ripgrep to get fix for quickopen+rg --- npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 9390aaa0586..a56314b4288 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -552,9 +552,9 @@ "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.23.0.tgz" }, "vscode-ripgrep": { - "version": "0.0.25", - "from": "vscode-ripgrep@0.0.25", - "resolved": "https://registry.npmjs.org/vscode-ripgrep/-/vscode-ripgrep-0.0.25.tgz" + "version": "0.0.26", + "from": "vscode-ripgrep@0.0.26", + "resolved": "https://registry.npmjs.org/vscode-ripgrep/-/vscode-ripgrep-0.0.26.tgz" }, "vscode-textmate": { "version": "3.1.5", diff --git a/package.json b/package.json index ff0d1b32979..221f7239ddf 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "semver": "4.3.6", "v8-profiler": "jrieken/v8-profiler#vscode", "vscode-debugprotocol": "1.23.0", - "vscode-ripgrep": "0.0.25", + "vscode-ripgrep": "0.0.26", "vscode-textmate": "^3.1.5", "winreg": "1.2.0", "xterm": "Tyriar/xterm.js#vscode-release/1.17", From bba374c79b6aa8c8109fb41cf3dc675ac182195a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 12 Sep 2017 18:58:53 -0700 Subject: [PATCH 028/145] Colorize python placeholders in strings --- extensions/theme-defaults/themes/dark_vs.json | 5 +++-- extensions/theme-defaults/themes/hc_black_defaults.json | 5 +++-- extensions/theme-defaults/themes/light_vs.json | 5 +++-- extensions/theme-red/themes/Red-color-theme.json | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json index 5c44ca0bbcc..91ad2adcbd7 100644 --- a/extensions/theme-defaults/themes/dark_vs.json +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -248,11 +248,12 @@ } }, { - "name": "JavaScript string interpolation ${}", + "name": "String interpolation", "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded" + "punctuation.section.embedded", + "constant.character.format.placeholder" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index be310e8addd..cd54a7bd6d2 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -237,11 +237,12 @@ } }, { - "name": "JavaScript string interpolation ${}", + "name": "String interpolation", "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded" + "punctuation.section.embedded", + "constant.character.format.placeholder" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json index 9627e324264..42fc12c88bd 100644 --- a/extensions/theme-defaults/themes/light_vs.json +++ b/extensions/theme-defaults/themes/light_vs.json @@ -244,11 +244,12 @@ } }, { - "name": "JavaScript string interpolation ${}", + "name": "String interpolation", "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded" + "punctuation.section.embedded", + "constant.character.format.placeholder" ], "settings": { "foreground": "#0000ff" diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index b7db36b8fe4..7b14c4d558d 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -387,11 +387,12 @@ } }, { - "name": "String interpolation ${}", + "name": "String interpolation", "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded" + "punctuation.section.embedded", + "constant.character.format.placeholder" ], "settings": { "foreground": "#ec0d1e" From b9e940ff1fe4f5dcca1afcb03294aaf77fd69d51 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Sep 2017 19:04:31 -0700 Subject: [PATCH 029/145] Uplevel xterm.js Improves terminal letter spacing --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a56314b4288..3e027f4d30d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "3.0.0", "from": "Tyriar/xterm.js#vscode-release/1.17", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#7e2af6fd7b740a20938a06aeaeef5056988d1b59" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#1b4af0852388a0bb99ef22812412486d53c7954c" }, "yauzl": { "version": "2.8.0", From 6d133f997c14a7faf9623d5948bf62f27f8ecb5e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Sep 2017 19:27:54 -0700 Subject: [PATCH 030/145] Uplevel xterm.js Fixes #34138 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 3e027f4d30d..3858934b86c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "3.0.0", "from": "Tyriar/xterm.js#vscode-release/1.17", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#1b4af0852388a0bb99ef22812412486d53c7954c" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#4483a2faf442101b507d033e4d25d134dddbe2ff" }, "yauzl": { "version": "2.8.0", From d5865f0f038057471a4ea29f38f9ba8339e43080 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 12 Sep 2017 20:34:24 -0700 Subject: [PATCH 031/145] Fix lines being cut off at top of terminal Fixes #34243 --- .../terminal/electron-browser/terminalInstance.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index 5ec52de5602..dd9d79a8c17 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -206,7 +206,16 @@ export class TerminalInstance implements ITerminalInstance { } const font = this._configHelper.getFont(); this._cols = Math.max(Math.floor(dimension.width / font.charWidth), 1); - this._rows = Math.max(Math.floor(dimension.height / Math.floor(font.charHeight * font.lineHeight)), 1); + + // xterm.js does the horizontal space calculation using values scaled + // with window.devicePixelRatio. In these calculations, ceil and floor + // are used which require us to check it on this side as well or we + // would lose that precision. + const scaledSpaceAvailable = dimension.height * window.devicePixelRatio; + const scaledCharHeight = Math.ceil(font.charHeight * window.devicePixelRatio); + const scaledLineHeight = Math.floor(scaledCharHeight * font.lineHeight); + this._rows = Math.floor(scaledSpaceAvailable / scaledLineHeight); + return dimension.width; } From a34cc54d2e2546d28939080bac28aafe8f708705 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 13 Sep 2017 06:38:08 +0200 Subject: [PATCH 032/145] fix compile --- src/vs/monaco.d.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 6dafcfb3478..467ac20a374 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2975,7 +2975,7 @@ declare module monaco.editor { * Accept suggestions on ENTER. * Defaults to 'on'. */ - acceptSuggestionOnEnter?: 'on' | 'smart' | 'off'; + acceptSuggestionOnEnter?: boolean | 'on' | 'smart' | 'off'; /** * Accept suggestions on provider defined characters. * Defaults to true. @@ -4459,7 +4459,7 @@ declare module monaco.languages { * The human-readable doc-comment of this signature. Will be shown * in the UI but can be omitted. */ - documentation?: string; + documentation?: string | IMarkdownString; } /** @@ -4477,7 +4477,7 @@ declare module monaco.languages { * The human-readable doc-comment of this signature. Will be shown * in the UI but can be omitted. */ - documentation?: string; + documentation?: string | IMarkdownString; /** * The parameters of this signature. */ @@ -4807,11 +4807,12 @@ declare module monaco.languages { } /** - * A color formatter. + * Represents a color format */ - export interface IColorFormatter { - readonly supportsTransparency: boolean; - format(color: IColor): string; + export enum ColorFormat { + RGB = 0, + HEX = 1, + HSL = 2, } /** @@ -4826,10 +4827,6 @@ declare module monaco.languages { * The color represented in this range. */ color: IColor; - /** - * The available formats for this specific color. - */ - formatters: IColorFormatter[]; } /** @@ -4840,6 +4837,10 @@ declare module monaco.languages { * Provides the color ranges for a specific model. */ provideColorRanges(model: editor.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable; + /** + * Provide the string representation for a color. + */ + resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable; } export interface IResourceEdit { From eb6fbe66c58dffd0457b06d4a7109fcc18d8e449 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 12 Sep 2017 20:32:42 -0700 Subject: [PATCH 033/145] Enable Ripgrep (#24074) --- .../platform/telemetry/common/experiments.ts | 6 +- .../electron-browser/mainThreadWorkspace.ts | 3 + .../services/search/node/fileSearch.ts | 16 ++-- .../services/search/test/node/search.test.ts | 74 +++++++++---------- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/vs/platform/telemetry/common/experiments.ts b/src/vs/platform/telemetry/common/experiments.ts index 103f1908f50..4a42a898e5e 100644 --- a/src/vs/platform/telemetry/common/experiments.ts +++ b/src/vs/platform/telemetry/common/experiments.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as platform from 'vs/base/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -44,10 +43,7 @@ export class ExperimentService implements IExperimentService { function loadExperiments(storageService: IStorageService, configurationService: IConfigurationService): IExperiments { const experiments = splitExperimentsRandomness(storageService); - if (platform.isWindows) { - // Ripgrep triggers MsMpEng.exe (https://github.com/BurntSushi/ripgrep/issues/600) - experiments.ripgrepQuickSearch = false; - } + experiments.ripgrepQuickSearch = true; return applyOverrides(experiments, configurationService); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index ad58576214d..8ea8a9b41d6 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -20,6 +20,7 @@ import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecyc import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService'; import { Emitter } from 'vs/base/common/event'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { IExperimentService } from 'vs/platform/telemetry/common/experiments'; @extHostNamedCustomer(MainContext.MainThreadWorkspace) export class MainThreadWorkspace implements MainThreadWorkspaceShape { @@ -35,6 +36,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { @ITextFileService private readonly _textFileService: ITextFileService, @IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService, @ITextModelService private readonly _textModelResolverService: ITextModelService, + @IExperimentService private experimentService: IExperimentService, @IFileService private readonly _fileService: IFileService ) { this._proxy = extHostContext.get(ExtHostContext.ExtHostWorkspace); @@ -70,6 +72,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { maxResults, includePattern: { [include]: true }, excludePattern: { [exclude]: true }, + useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; this._searchService.extendQuery(query); diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index 057c74b4dc7..064f8db2254 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -49,6 +49,7 @@ interface IDirectoryTree { export class FileWalker { private config: IRawSearch; + private useRipgrep: boolean; private filePattern: string; private normalizedFilePatternLowercase: string; private includePattern: glob.ParsedExpression; @@ -73,6 +74,7 @@ export class FileWalker { constructor(config: IRawSearch) { this.config = config; + this.useRipgrep = config.useRipgrep !== false; this.filePattern = config.filePattern; this.includePattern = config.includePattern && glob.parse(config.includePattern); this.maxResults = config.maxResults || null; @@ -153,7 +155,7 @@ export class FileWalker { let traverse = this.nodeJSTraversal; if (!this.maxFilesize) { - if (this.config.useRipgrep) { + if (this.useRipgrep) { this.traversal = Traversal.Ripgrep; traverse = this.cmdTraversal; } else if (platform.isMacintosh) { @@ -216,11 +218,11 @@ export class FileWalker { let first = true; const tree = this.initDirectoryTree(); - const useRipgrep = this.config.useRipgrep; + const useRipgrep = this.useRipgrep; let cmd: childProcess.ChildProcess; let noSiblingsClauses: boolean; if (useRipgrep) { - const ripgrep = spawnRipgrepCmd(folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder)); + const ripgrep = spawnRipgrepCmd(folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder).expression); cmd = ripgrep.cmd; noSiblingsClauses = !Object.keys(ripgrep.siblingClauses).length; } else { @@ -236,7 +238,7 @@ export class FileWalker { // Mac: uses NFD unicode form on disk, but we want NFC const normalized = leftover + (isMac ? strings.normalizeNFC(stdout) : stdout); const relativeFiles = normalized.split(useRipgrep ? '\n' : '\n./'); - if (first && normalized.length >= 2) { + if (!useRipgrep && first && normalized.length >= 2) { first = false; relativeFiles[0] = relativeFiles[0].trim().substr(2); } @@ -367,7 +369,7 @@ export class FileWalker { cmd.on('close', (code: number) => { if (code !== 0) { - done(new Error(`find failed with error code ${code}: ${this.decodeData(stderr, encoding)}`)); + done(new Error(`command failed with error code ${code}: ${this.decodeData(stderr, encoding)}`)); } else { done(null, '', true); } @@ -710,8 +712,8 @@ class AbsoluteAndRelativeParsedExpression { private absoluteParsedExpr: glob.ParsedExpression; private relativeParsedExpr: glob.ParsedExpression; - constructor(expr: glob.IExpression, private root: string) { - this.init(expr); + constructor(public expression: glob.IExpression, private root: string) { + this.init(expression); } /** diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 75fddf759ba..04ff7e8b61b 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -234,24 +234,24 @@ suite('FileSearchEngine', () => { }); }); - test('Files: *.* exclude with unicode', function (done: () => void) { - let engine = new FileSearchEngine({ - folderQueries: ROOT_FOLDER_QUERY, - filePattern: '*.*', - excludePattern: { '**/üm laut汉语': true } - }); + // test('Files: *.* exclude with unicode', function (done: () => void) { + // let engine = new FileSearchEngine({ + // folderQueries: ROOT_FOLDER_QUERY, + // filePattern: '*.*', + // excludePattern: { '**/üm laut汉语': true } + // }); - let count = 0; - engine.search((result) => { - if (result) { - count++; - } - }, () => { }, (error) => { - assert.ok(!error); - assert.equal(count, 13); - done(); - }); - }); + // let count = 0; + // engine.search((result) => { + // if (result) { + // count++; + // } + // }, () => { }, (error) => { + // assert.ok(!error); + // assert.equal(count, 13); + // done(); + // }); + // }); test('Files: multiroot with exclude', function (done: () => void) { const folderQueries: IFolderSearch[] = [ @@ -368,27 +368,27 @@ suite('FileSearchEngine', () => { }); }); - test('Files: relative path to file ignores excludes', function (done: () => void) { - let engine = new FileSearchEngine({ - folderQueries: ROOT_FOLDER_QUERY, - filePattern: path.normalize(path.join('examples', 'company.js')), - excludePattern: { '**/*.js': true } - }); + // test('Files: relative path to file ignores excludes', function (done: () => void) { + // let engine = new FileSearchEngine({ + // folderQueries: ROOT_FOLDER_QUERY, + // filePattern: path.normalize(path.join('examples', 'company.js')), + // excludePattern: { '**/*.js': true } + // }); - let count = 0; - let res: IRawFileMatch; - engine.search((result) => { - if (result) { - count++; - } - res = result; - }, () => { }, (error) => { - assert.ok(!error); - assert.equal(count, 1); - assert.equal(path.basename(res.relativePath), 'company.js'); - done(); - }); - }); + // let count = 0; + // let res: IRawFileMatch; + // engine.search((result) => { + // if (result) { + // count++; + // } + // res = result; + // }, () => { }, (error) => { + // assert.ok(!error); + // assert.equal(count, 1); + // assert.equal(path.basename(res.relativePath), 'company.js'); + // done(); + // }); + // }); test('Files: Include pattern, single files', function (done: () => void) { let engine = new FileSearchEngine({ From 783df422b9f0309c09cd4b791502cb7be950ad68 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 12 Sep 2017 21:35:31 -0700 Subject: [PATCH 034/145] Convert globs to NFD on Mac (#24074) --- src/vs/base/common/strings.ts | 16 +++++++-- .../services/search/node/ripgrepFileSearch.ts | 6 ++-- .../services/search/test/node/search.test.ts | 34 +++++++++---------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index 7af18aadcb6..2200f4e5721 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -238,9 +238,19 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean { * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize} */ export const canNormalize = typeof (('').normalize) === 'function'; -const nonAsciiCharactersPattern = /[^\u0000-\u0080]/; -const normalizedCache = new BoundedMap(10000); // bounded to 10000 elements + +const nfcCache = new BoundedMap(10000); // bounded to 10000 elements export function normalizeNFC(str: string): string { + return normalize(str, 'NFC', nfcCache); +} + +const nfdCache = new BoundedMap(10000); // bounded to 10000 elements +export function normalizeNFD(str: string): string { + return normalize(str, 'NFD', nfdCache); +} + +const nonAsciiCharactersPattern = /[^\u0000-\u0080]/; +function normalize(str: string, form: string, normalizedCache: BoundedMap): string { if (!canNormalize || !str) { return str; } @@ -252,7 +262,7 @@ export function normalizeNFC(str: string): string { let res: string; if (nonAsciiCharactersPattern.test(str)) { - res = (str).normalize('NFC'); + res = (str).normalize(form); } else { res = str; } diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 325a7ac554d..3dfe7f85dac 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -6,7 +6,9 @@ import * as cp from 'child_process'; import { rgPath } from 'vscode-ripgrep'; +import { isMacintosh as isMac } from 'vs/base/common/platform'; import * as glob from 'vs/base/common/glob'; +import { normalizeNFD } from 'vs/base/common/strings'; import { IFolderSearch } from './search'; import { foldersToIncludeGlobs, foldersToRgExcludeGlobs } from './ripgrepTextSearch'; @@ -24,14 +26,14 @@ function getRgArgs(folderQuery: IFolderSearch, includePattern: glob.IExpression, // includePattern can't have siblingClauses foldersToIncludeGlobs([folderQuery], includePattern, false).forEach(globArg => { - args.push('-g', globArg); + args.push('-g', isMac ? normalizeNFD(globArg) : globArg); }); let siblingClauses: glob.IExpression; const rgGlobs = foldersToRgExcludeGlobs([folderQuery], excludePattern, undefined, false); rgGlobs.globArgs - .forEach(rgGlob => args.push('-g', `!${rgGlob}`)); + .forEach(rgGlob => args.push('-g', `!${isMac ? normalizeNFD(rgGlob) : rgGlob}`)); siblingClauses = rgGlobs.siblingClauses; // Don't use .gitignore or .ignore diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 04ff7e8b61b..60ae0750d3f 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -234,24 +234,24 @@ suite('FileSearchEngine', () => { }); }); - // test('Files: *.* exclude with unicode', function (done: () => void) { - // let engine = new FileSearchEngine({ - // folderQueries: ROOT_FOLDER_QUERY, - // filePattern: '*.*', - // excludePattern: { '**/üm laut汉语': true } - // }); + test('Files: *.* exclude with unicode', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + filePattern: '*.*', + excludePattern: { '**/üm laut汉语': true } + }); - // let count = 0; - // engine.search((result) => { - // if (result) { - // count++; - // } - // }, () => { }, (error) => { - // assert.ok(!error); - // assert.equal(count, 13); - // done(); - // }); - // }); + let count = 0; + engine.search((result) => { + if (result) { + count++; + } + }, () => { }, (error) => { + assert.ok(!error); + assert.equal(count, 13); + done(); + }); + }); test('Files: multiroot with exclude', function (done: () => void) { const folderQueries: IFolderSearch[] = [ From 3307e76f765e27a9ba60794da07cd1619ac151c7 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 12 Sep 2017 21:51:34 -0700 Subject: [PATCH 035/145] Relative file match (#24074) --- scripts/test.sh | 1 + .../services/search/node/fileSearch.ts | 20 +++++++++- .../services/search/test/node/search.test.ts | 40 +++++++++---------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/scripts/test.sh b/scripts/test.sh index 0812c9345fd..ce1e5e11856 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -28,6 +28,7 @@ test -d node_modules || ./scripts/npm.sh install (test -f "$CODE" && [ $INTENDED_VERSION == $INSTALLED_VERSION ]) || ./node_modules/.bin/gulp electron # Unit Tests +export ELECTRON_ENABLE_LOGGING=1 if [[ "$OSTYPE" == "darwin"* ]]; then cd $ROOT ; ulimit -n 4096 ; \ "$CODE" \ diff --git a/src/vs/workbench/services/search/node/fileSearch.ts b/src/vs/workbench/services/search/node/fileSearch.ts index 064f8db2254..c621b8b2c48 100644 --- a/src/vs/workbench/services/search/node/fileSearch.ts +++ b/src/vs/workbench/services/search/node/fileSearch.ts @@ -221,6 +221,7 @@ export class FileWalker { const useRipgrep = this.useRipgrep; let cmd: childProcess.ChildProcess; let noSiblingsClauses: boolean; + let filePatternSeen = false; if (useRipgrep) { const ripgrep = spawnRipgrepCmd(folderQuery, this.config.includePattern, this.folderExcludePatterns.get(folderQuery.folder).expression); cmd = ripgrep.cmd; @@ -262,11 +263,28 @@ export class FileWalker { if (useRipgrep && noSiblingsClauses) { for (const relativePath of relativeFiles) { + if (relativePath === this.filePattern) { + filePatternSeen = true; + } const basename = path.basename(relativePath); this.matchFile(onResult, { base: rootFolder, relativePath, basename }); } if (last) { - done(); + if (!filePatternSeen) { + this.checkFilePatternRelativeMatch(folderQuery.folder, (match, size) => { + if (match) { + this.resultCount++; + onResult({ + base: folderQuery.folder, + relativePath: this.filePattern, + basename: path.basename(this.filePattern), + }); + } + done(); + }); + } else { + done(); + } } return; } diff --git a/src/vs/workbench/services/search/test/node/search.test.ts b/src/vs/workbench/services/search/test/node/search.test.ts index 60ae0750d3f..75fddf759ba 100644 --- a/src/vs/workbench/services/search/test/node/search.test.ts +++ b/src/vs/workbench/services/search/test/node/search.test.ts @@ -368,27 +368,27 @@ suite('FileSearchEngine', () => { }); }); - // test('Files: relative path to file ignores excludes', function (done: () => void) { - // let engine = new FileSearchEngine({ - // folderQueries: ROOT_FOLDER_QUERY, - // filePattern: path.normalize(path.join('examples', 'company.js')), - // excludePattern: { '**/*.js': true } - // }); + test('Files: relative path to file ignores excludes', function (done: () => void) { + let engine = new FileSearchEngine({ + folderQueries: ROOT_FOLDER_QUERY, + filePattern: path.normalize(path.join('examples', 'company.js')), + excludePattern: { '**/*.js': true } + }); - // let count = 0; - // let res: IRawFileMatch; - // engine.search((result) => { - // if (result) { - // count++; - // } - // res = result; - // }, () => { }, (error) => { - // assert.ok(!error); - // assert.equal(count, 1); - // assert.equal(path.basename(res.relativePath), 'company.js'); - // done(); - // }); - // }); + let count = 0; + let res: IRawFileMatch; + engine.search((result) => { + if (result) { + count++; + } + res = result; + }, () => { }, (error) => { + assert.ok(!error); + assert.equal(count, 1); + assert.equal(path.basename(res.relativePath), 'company.js'); + done(); + }); + }); test('Files: Include pattern, single files', function (done: () => void) { let engine = new FileSearchEngine({ From 06529dbcacb796d59e7fc2ca0ac5dbe7c29c099e Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 12 Sep 2017 22:10:23 -0700 Subject: [PATCH 036/145] Legacy text search (#24074) --- src/vs/workbench/services/search/node/rawSearchService.ts | 1 + .../services/search/test/node/textSearch.integrationTest.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/search/node/rawSearchService.ts b/src/vs/workbench/services/search/node/rawSearchService.ts index ebe2799e716..19d197cc750 100644 --- a/src/vs/workbench/services/search/node/rawSearchService.ts +++ b/src/vs/workbench/services/search/node/rawSearchService.ts @@ -83,6 +83,7 @@ export class SearchService implements IRawSearchService { includePattern: config.includePattern, excludePattern: config.excludePattern, filePattern: config.filePattern, + useRipgrep: false, maxFilesize: MAX_FILE_SIZE }), this.textSearchWorkerProvider); diff --git a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts index de5000fdcfe..cdc6ada67da 100644 --- a/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts +++ b/src/vs/workbench/services/search/test/node/textSearch.integrationTest.ts @@ -37,7 +37,7 @@ const textSearchWorkerProvider = new TextSearchWorkerProvider(); function doLegacySearchTest(config: IRawSearch, expectedResultCount: number | Function): TPromise { return new TPromise((resolve, reject) => { - let engine = new TextSearchEngine(config, new FileWalker(config), textSearchWorkerProvider); + let engine = new TextSearchEngine(config, new FileWalker({ ...config, useRipgrep: false }), textSearchWorkerProvider); let c = 0; engine.search((result) => { From 05846be140097587ffc72445b49ea1a9ca0a7a24 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 08:50:08 +0200 Subject: [PATCH 037/145] Use workspace state to check for empty workspace and remove hasWorkspace method --- .../standalone/browser/simpleServices.ts | 4 --- .../common/extensionEnablementService.ts | 4 +-- .../common/extensionEnablementService.test.ts | 10 +++---- .../test/common/storageService.test.ts | 6 ++--- src/vs/platform/workspace/common/workspace.ts | 17 +++++------- .../browser/actions/workspaceActions.ts | 27 ++++++++++--------- .../browser/parts/statusbar/statusbarPart.ts | 8 +++--- src/vs/workbench/browser/parts/views/views.ts | 6 ++--- src/vs/workbench/common/resources.ts | 4 +-- src/vs/workbench/electron-browser/actions.ts | 4 +-- src/vs/workbench/electron-browser/main.ts | 2 +- src/vs/workbench/electron-browser/shell.ts | 4 +-- .../workbench/electron-browser/workbench.ts | 10 +++---- .../parts/debug/browser/debugActions.ts | 6 ++--- .../parts/debug/browser/debugViewlet.ts | 8 +++--- .../debug/electron-browser/debugCommands.ts | 4 +-- .../debug/electron-browser/debugService.ts | 10 +++---- .../statusbarColorProvider.ts | 4 +-- .../extensions/browser/extensionsActions.ts | 14 +++++----- .../electron-browser/extensionTipsService.ts | 4 +-- .../node/extensionsWorkbenchService.ts | 4 +-- .../electron-browser/feedbackStatusbarItem.ts | 4 +-- .../parts/files/browser/explorerViewlet.ts | 6 ++--- .../parts/output/common/outputLinkProvider.ts | 4 +-- .../preferences/browser/preferencesActions.ts | 2 +- .../preferences/browser/preferencesService.ts | 2 +- .../preferences/browser/preferencesWidgets.ts | 2 +- .../parts/search/browser/openFileHandler.ts | 6 ++--- .../parts/search/browser/searchViewlet.ts | 10 +++---- .../parts/search/common/queryBuilder.ts | 2 +- .../electron-browser/task.contribution.ts | 12 ++++----- .../parts/tasks/node/processRunnerDetector.ts | 4 +-- .../watermark/electron-browser/watermark.ts | 4 +-- .../configuration/node/configuration.ts | 4 --- .../node/configurationEditingService.ts | 2 +- .../files/electron-browser/fileService.ts | 4 +-- .../services/files/node/fileService.ts | 6 ++--- .../services/history/browser/history.ts | 4 +-- .../textfile/common/textFileEditorModel.ts | 4 +-- .../textfile/common/textFileService.ts | 6 ++--- .../workbench/test/workbenchTestServices.ts | 4 --- 41 files changed, 116 insertions(+), 136 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 46cf48c9665..197924f0f74 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -553,10 +553,6 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME ? this.workspace.roots[0] : void 0; } - public hasWorkspace(): boolean { - return true; - } - public isInsideWorkspace(resource: URI): boolean { return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME; } diff --git a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts index 75606dd0a96..af0dedd15bf 100644 --- a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts @@ -10,7 +10,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { adoptToGalleryExtensionId, getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -35,7 +35,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService { } private get hasWorkspace(): boolean { - return this.contextService.hasWorkspace(); + return this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY; } public getGloballyDisabledExtensions(): string[] { diff --git a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts index e44ff52c8c9..12287b6bd4e 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts @@ -12,7 +12,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { Emitter } from 'vs/base/common/event'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; function storageService(instantiationService: TestInstantiationService): IStorageService { @@ -21,9 +21,7 @@ function storageService(instantiationService: TestInstantiationService): IStorag let workspaceContextService = instantiationService.get(IWorkspaceContextService); if (!workspaceContextService) { workspaceContextService = instantiationService.stub(IWorkspaceContextService, { - hasWorkspace: () => { - return true; - }, + getWorkspaceState: () => WorkspaceState.FOLDER, }); } service = instantiationService.stub(IStorageService, instantiationService.createInstance(StorageService, new InMemoryLocalStorage(), new InMemoryLocalStorage())); @@ -73,7 +71,7 @@ suite('ExtensionEnablementService Test', () => { test('test when no extensions are disabled for workspace when there is no workspace', (done) => { testObject.setEnablement('pub.a', false, true) .then(() => { - instantiationService.stub(IWorkspaceContextService, 'hasWorkspace', false); + instantiationService.stub(IWorkspaceContextService, 'getWorkspaceState', WorkspaceState.EMPTY); assert.deepEqual([], testObject.getWorkspaceDisabledExtensions()); }) .then(done, done); @@ -178,7 +176,7 @@ suite('ExtensionEnablementService Test', () => { }); test('test disable an extension for workspace when there is no workspace throws error', (done) => { - instantiationService.stub(IWorkspaceContextService, 'hasWorkspace', false); + instantiationService.stub(IWorkspaceContextService, 'getWorkspaceState', WorkspaceState.EMPTY); testObject.setEnablement('pub.a', false, true) .then(() => assert.fail('should throw an error'), error => assert.ok(error)) .then(done, done); diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index 2bd09689b54..8a7f3249e26 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { StorageScope } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; @@ -19,9 +19,7 @@ suite('Workbench StorageSevice', () => { setup(() => { instantiationService = new TestInstantiationService(); contextService = instantiationService.stub(IWorkspaceContextService, { - hasWorkspace: () => { - return true; - }, + getWorkspaceState: () => WorkspaceState.FOLDER, getWorkspace: () => { return TestWorkspace; } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index a3144892141..5afdc03d70e 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -23,6 +23,12 @@ export enum WorkspaceState { export interface IWorkspaceContextService { _serviceBrand: any; + /** + * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened + * without workspace (empty); + */ + getWorkspace(): IWorkspace; + /** * Return the state of the current workspace. * @@ -32,17 +38,6 @@ export interface IWorkspaceContextService { */ getWorkspaceState(): WorkspaceState; - /** - * Returns if the application was opened with a workspace or not. - */ - hasWorkspace(): boolean; - - /** - * Provides access to the workspace object the platform is running with. This may be null if the workbench was opened - * without workspace (empty); - */ - getWorkspace(): IWorkspace; - /** * An event which fires on workspace name changes. */ diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index b1c67b005fa..974388b03ad 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -108,22 +108,23 @@ export class AddRootFolderAction extends BaseWorkspacesAction { } public run(): TPromise { - if (!this.contextService.hasWorkspace()) { - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); - } + switch (this.contextService.getWorkspaceState()) { - if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); - } + case WorkspaceState.EMPTY: + return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); - const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); - if (!folders || !folders.length) { - return TPromise.as(null); - } + case WorkspaceState.FOLDER: + return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); - return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { - return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); - }); + case WorkspaceState.WORKSPACE: + const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); + if (!folders || !folders.length) { + return TPromise.as(null); + } + return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { + return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); + }); + } } } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 8131a18ab78..7fd8baac704 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -28,7 +28,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { Action } from 'vs/base/common/actions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { isThemeColor } from 'vs/editor/common/editorCommon'; import { Color } from 'vs/base/common/color'; @@ -141,10 +141,10 @@ export class StatusbarPart extends Part implements IStatusbarService { const container = this.getContainer(); - container.style('color', this.getColor(this.contextService.hasWorkspace() ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); - container.style('background-color', this.getColor(this.contextService.hasWorkspace() ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND)); + container.style('color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); + container.style('background-color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND)); - const borderColor = this.getColor(this.contextService.hasWorkspace() ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER) || this.getColor(contrastBorder); + const borderColor = this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER) || this.getColor(contrastBorder); container.style('border-top-width', borderColor ? '1px' : null); container.style('border-top-style', borderColor ? 'solid' : null); container.style('border-top-color', borderColor); diff --git a/src/vs/workbench/browser/parts/views/views.ts b/src/vs/workbench/browser/parts/views/views.ts index cf378b00e90..0e254b6c0ce 100644 --- a/src/vs/workbench/browser/parts/views/views.ts +++ b/src/vs/workbench/browser/parts/views/views.ts @@ -28,7 +28,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND } from 'vs/workbench/common/theme'; @@ -776,11 +776,11 @@ export class PersistentViewsViewlet extends ViewsViewlet { } }); - this.storageService.store(this.viewletStateStorageId, JSON.stringify(viewsStates), this.contextService.hasWorkspace() ? StorageScope.WORKSPACE : StorageScope.GLOBAL); + this.storageService.store(this.viewletStateStorageId, JSON.stringify(viewsStates), this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL); } private loadViewsStates(): void { - const viewsStates = JSON.parse(this.storageService.get(this.viewletStateStorageId, this.contextService.hasWorkspace() ? StorageScope.WORKSPACE : StorageScope.GLOBAL, '{}')); + const viewsStates = JSON.parse(this.storageService.get(this.viewletStateStorageId, this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL, '{}')); Object.keys(viewsStates).forEach(id => this.viewsStates.set(id, viewsStates[id])); } } \ No newline at end of file diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 830f77fd26f..d401bb087b8 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import objects = require('vs/base/common/objects'); import paths = require('vs/base/common/paths'); -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -106,7 +106,7 @@ export class ResourceGlobMatcher { let changed = false; // Add excludes per workspaces that got added - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { this.contextService.getWorkspace().roots.forEach(root => { const rootExcludes = this.globFn(root); if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index ee7d61c39a9..559f03a75c5 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -18,7 +18,7 @@ import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; import errors = require('vs/base/common/errors'); import { IMessageService, Severity } from 'vs/platform/message/common/message'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -104,7 +104,7 @@ export class CloseWorkspaceAction extends Action { } run(): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close.")); return TPromise.as(null); diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index e21601af993..95762448da1 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -79,7 +79,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { // Since the configuration service is one of the core services that is used in so many places, we initialize it // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService, mainServices.get(IWorkspacesService)).then(workspaceService => { - const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, !workspaceService.hasWorkspace()); + const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkspaceState() === WorkspaceState.EMPTY); const storageService = createStorageService(configuration, workspaceService, environmentService); timerService.beforeDOMContentLoaded = Date.now(); diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index f6bec8be10f..6b08e83a33d 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -63,7 +63,7 @@ import { ChoiceChannel } from 'vs/platform/message/common/messageIpc'; import { ISearchService } from 'vs/platform/search/common/search'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { CommandService } from 'vs/platform/commands/common/commandService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -202,7 +202,7 @@ export class WorkbenchShell { this.telemetryService.publicLog('workspaceLoad', { userAgent: navigator.userAgent, windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, - emptyWorkbench: !this.contextService.hasWorkspace(), + emptyWorkbench: this.contextService.getWorkspaceState() === WorkspaceState.EMPTY, 'workbench.filesToOpen': filesToOpen && filesToOpen.length || void 0, 'workbench.filesToCreate': filesToCreate && filesToCreate.length || void 0, 'workbench.filesToDiff': filesToDiff && filesToDiff.length || void 0, diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 6fe5bb86fa8..95add84f478 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -41,7 +41,7 @@ import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickO import { getServices } from 'vs/platform/instantiation/common/extensions'; import { WorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { Position, Parts, IPartService, ILayoutOptions } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService'; import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; @@ -444,7 +444,7 @@ export class Workbench implements IPartService { } // Empty workbench - else if (!this.contextService.hasWorkspace() && this.openUntitledFile()) { + else if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && this.openUntitledFile()) { if (this.editorPart.hasEditorsToRestore()) { return TPromise.as([]); // do not open any empty untitled file if we have editors to restore } @@ -635,7 +635,7 @@ export class Workbench implements IPartService { private initSettings(): void { // Sidebar visibility - this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenSettingKey, StorageScope.WORKSPACE, !this.contextService.hasWorkspace()); + this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenSettingKey, StorageScope.WORKSPACE, this.contextService.getWorkspaceState() === WorkspaceState.EMPTY); // Panel part visibility const panelRegistry = Registry.as(PanelExtensions.Panels); @@ -830,7 +830,7 @@ export class Workbench implements IPartService { return promise.then(() => { // Remember in settings - const defaultHidden = !this.contextService.hasWorkspace(); + const defaultHidden = this.contextService.getWorkspaceState() === WorkspaceState.EMPTY; if (hidden !== defaultHidden) { this.storageService.store(Workbench.sidebarHiddenSettingKey, hidden ? 'true' : 'false', StorageScope.WORKSPACE); } else { @@ -1054,7 +1054,7 @@ export class Workbench implements IPartService { // Close when empty: check if we should close the window based on the setting // Overruled by: window has a workspace opened or this window is for extension development // or setting is disabled. Also enabled when running with --wait from the command line. - if (visibleEditors === 0 && !this.contextService.hasWorkspace() && !this.environmentService.isExtensionDevelopment) { + if (visibleEditors === 0 && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && !this.environmentService.isExtensionDevelopment) { const closeWhenEmpty = this.configurationService.lookup(Workbench.closeWhenEmptyConfigurationKey).value; if (closeWhenEmpty || this.environmentService.args.wait) { this.closeEmptyWindowScheduler.schedule(); diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index b462d58e460..c806a37cc88 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -11,7 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IFileService } from 'vs/platform/files/common/files'; import { IMessageService } from 'vs/platform/message/common/message'; import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState } @@ -98,7 +98,7 @@ export class ConfigureAction extends AbstractDebugAction { } public run(event?: any): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); return TPromise.as(null); } @@ -140,7 +140,7 @@ export class StartAction extends AbstractDebugAction { if (state === State.Initializing) { return false; } - if (this.contextService && !this.contextService.hasWorkspace() && processes.length > 0) { + if (this.contextService && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && processes.length > 0) { return false; } if (processes.some(p => p.getName(false) === selectedName && (!launch || p.session.root.toString() === launch.workspaceUri.toString()))) { diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 98ac337283e..8061af7c180 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -16,7 +16,7 @@ import { StartDebugActionItem } from 'vs/workbench/parts/debug/browser/debugActi import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -56,7 +56,7 @@ export class DebugViewlet extends PersistentViewsViewlet { public focus(): void { super.focus(); - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.views[0].focusBody(); } @@ -69,7 +69,7 @@ export class DebugViewlet extends PersistentViewsViewlet { if (!this.actions) { this.actions = []; this.actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL)); - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { this.actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL)); } this.actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL))); @@ -83,7 +83,7 @@ export class DebugViewlet extends PersistentViewsViewlet { } public getActionItem(action: IAction): IActionItem { - if (action.id === StartAction.ID && this.contextService.hasWorkspace()) { + if (action.id === StartAction.ID && this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action); return this.startDebugActionItem; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts index c1824de5b62..bb81a501985 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts @@ -15,7 +15,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IListService } from 'vs/platform/list/browser/listService'; import { IMessageService } from 'vs/platform/message/common/message'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IDebugService, IConfig, IEnablement, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug'; import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; @@ -204,7 +204,7 @@ export function registerCommands(): void { primary: undefined, handler: (accessor, workspaceUri: string) => { const manager = accessor.get(IDebugService).getConfigurationManager(); - if (!accessor.get(IWorkspaceContextService).hasWorkspace()) { + if (accessor.get(IWorkspaceContextService).getWorkspaceState() === WorkspaceState.EMPTY) { accessor.get(IMessageService).show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); return TPromise.as(null); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 08ffc1b1b97..32c8022826d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -46,7 +46,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ILogEntry, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost'; import { IBroadcastService, IBroadcast } from 'vs/platform/broadcast/electron-browser/broadcastService'; @@ -365,7 +365,7 @@ export class DebugService implements debug.IDebugService { // 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905 const process = this.viewModel.focusedProcess; if (process && session && process.getId() === session.getId() && strings.equalsIgnoreCase(process.configuration.type, 'extensionhost') && this.sessionStates.get(session.getId()) === debug.State.Running && - process && this.contextService.hasWorkspace() && process.configuration.noDebug) { + process && this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && process.configuration.noDebug) { this.broadcastService.broadcast({ channel: EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, payload: [process.session.root.fsPath] @@ -759,7 +759,7 @@ export class DebugService implements debug.IDebugService { }); }); }, err => { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(severity.Error, nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved on disk and that you have a debug extension installed for that file type.")); return undefined; } @@ -846,7 +846,7 @@ export class DebugService implements debug.IDebugService { this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); } - if (!this.viewModel.changedWorkbenchViewState && (this.partService.isVisible(Parts.SIDEBAR_PART) || !this.contextService.hasWorkspace())) { + if (!this.viewModel.changedWorkbenchViewState && (this.partService.isVisible(Parts.SIDEBAR_PART) || this.contextService.getWorkspaceState() === WorkspaceState.EMPTY)) { // We only want to change the workbench view state on the first debug session #5738 and if the side bar is not hidden this.viewModel.changedWorkbenchViewState = true; this.viewletService.openViewlet(debug.VIEWLET_ID); @@ -866,7 +866,7 @@ export class DebugService implements debug.IDebugService { watchExpressionsCount: this.model.getWatchExpressions().length, extensionName: `${adapter.extensionDescription.publisher}.${adapter.extensionDescription.name}`, isBuiltin: adapter.extensionDescription.isBuiltin, - launchJsonExists: this.contextService.hasWorkspace() && !!this.configurationService.getConfiguration('launch', { resource: root }) + launchJsonExists: this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && !!this.configurationService.getConfiguration('launch', { resource: root }) }); }).then(() => process, (error: any) => { if (error instanceof Error && error.message === 'Canceled') { diff --git a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts index f5c8e2040ce..0ecf32ed8b1 100644 --- a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts +++ b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts @@ -9,7 +9,7 @@ import { registerColor, contrastBorder } from 'vs/platform/theme/common/colorReg import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IDebugService, State } from 'vs/workbench/parts/debug/common/debug'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_BACKGROUND, Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_BORDER } from 'vs/workbench/common/theme'; import { addClass, removeClass } from 'vs/base/browser/dom'; @@ -75,7 +75,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri // Not debugging if (!this.isDebugging()) { - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { return normalColor; } diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 0ab03cca7a8..494475b52a5 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -26,7 +26,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Query } from 'vs/workbench/parts/extensions/common/extensionQuery'; import { IFileService } from 'vs/platform/files/common/files'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IExtensionService, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import URI from 'vs/base/common/uri'; @@ -559,7 +559,7 @@ export class DisableForWorkspaceAction extends Action implements IExtensionActio private update(): void { this.enabled = false; - if (this.extension && this.workspaceContextService.hasWorkspace()) { + if (this.extension && this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { this.enabled = this.extension.type !== LocalExtensionType.System && !this.extension.disabledGlobally && !this.extension.disabledForWorkspace; } } @@ -1093,7 +1093,7 @@ export class ShowWorkspaceRecommendedExtensionsAction extends Action { @IWorkspaceContextService contextService: IWorkspaceContextService, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, contextService.hasWorkspace()); + super(id, label, null, contextService.getWorkspaceState() !== WorkspaceState.EMPTY); } run(): TPromise { @@ -1251,7 +1251,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IMessageService private messageService: IMessageService ) { - super(id, label, null, contextService.hasWorkspace()); + super(id, label, null, contextService.getWorkspaceState() !== WorkspaceState.EMPTY); } public run(event: any): TPromise { @@ -1259,7 +1259,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { } private openExtensionsFile(): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(severity.Info, localize('ConfigureWorkspaceRecommendations.noWorkspace', 'Recommendations are only available on a workspace folder.')); return TPromise.as(undefined); } @@ -1363,7 +1363,7 @@ export class DisableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.hasWorkspace() && this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && !e.disabledForWorkspace && !e.disabledGlobally); + this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && !e.disabledForWorkspace && !e.disabledGlobally); } run(): TPromise { @@ -1426,7 +1426,7 @@ export class EnableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.hasWorkspace() && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.id) && !e.disabledGlobally && e.disabledForWorkspace); + this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.id) && !e.disabledGlobally && e.disabledForWorkspace); } run(): TPromise { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index 75ef396df9d..267265b2d0f 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -19,7 +19,7 @@ import { IChoiceService, IMessageService } from 'vs/platform/message/common/mess import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import Severity from 'vs/base/common/severity'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; @@ -72,7 +72,7 @@ export class ExtensionTipsService implements IExtensionTipsService { } getWorkspaceRecommendations(): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { return TPromise.as([]); } return this.fileService.resolveContent(this.contextService.toResource(paths.join('.vscode', 'extensions.json'))).then(content => { //TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 029bed45771..7d0b6871d9b 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -34,7 +34,7 @@ import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenc import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IURLService } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import product from 'vs/platform/node/product'; interface IExtensionStateProvider { @@ -663,7 +663,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } const globalElablement = this.extensionEnablementService.setEnablement(extension.id, enable, false); - if (enable && this.workspaceContextService.hasWorkspace()) { + if (enable && this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { const workspaceEnablement = this.extensionEnablementService.setEnablement(extension.id, enable, true); return TPromise.join([globalElablement, workspaceEnablement]).then(values => values[0] || values[1]); } diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts index 7a93025af9d..cb98a1f78bd 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts @@ -13,7 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import product from 'vs/platform/node/product'; import { Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND } from 'vs/workbench/common/theme'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; class TwitterFeedbackService implements IFeedbackService { @@ -70,7 +70,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { super.updateStyles(); if (this.dropdown) { - this.dropdown.label.style('background-color', this.getColor(this.contextService.hasWorkspace() ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); + this.dropdown.label.style('background-color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); } } diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 43ab0f77d72..14ca02586b6 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -22,7 +22,7 @@ import { OpenEditorsView } from 'vs/workbench/parts/files/browser/views/openEdit import { IStorageService } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -78,7 +78,7 @@ export class ExplorerViewlet extends PersistentViewsViewlet { viewDescriptors.push(this.createOpenEditorsViewDescriptor()); - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { viewDescriptors.push(this.createExplorerViewDescriptor()); } else { viewDescriptors.push(this.createEmptyViewDescriptor()); @@ -122,7 +122,7 @@ export class ExplorerViewlet extends PersistentViewsViewlet { } private onConfigurationUpdated(): void { - this.openEditorsVisibleContextKey.set(!this.contextService.hasWorkspace() || (this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0); + this.openEditorsVisibleContextKey.set(this.contextService.getWorkspaceState() === WorkspaceState.EMPTY || (this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0); } protected createView(viewDescriptor: IViewDescriptor, initialSize: number, options: IViewletViewOptions): IView { diff --git a/src/vs/workbench/parts/output/common/outputLinkProvider.ts b/src/vs/workbench/parts/output/common/outputLinkProvider.ts index abdd048bdad..12c2c9d224d 100644 --- a/src/vs/workbench/parts/output/common/outputLinkProvider.ts +++ b/src/vs/workbench/parts/output/common/outputLinkProvider.ts @@ -10,7 +10,7 @@ import URI from 'vs/base/common/uri'; import { RunOnceScheduler, wireCancellationToken } from 'vs/base/common/async'; import { IModelService } from 'vs/editor/common/services/modelService'; import { LinkProviderRegistry, ILink } from 'vs/editor/common/modes'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { OUTPUT_MODE_ID } from 'vs/workbench/parts/output/common/output'; import { MonacoWebWorker, createWebWorker } from 'vs/editor/common/services/webWorker'; import { ICreateData, OutputLinkComputer } from 'vs/workbench/parts/output/common/outputLinkComputer'; @@ -43,7 +43,7 @@ export class OutputLinkProvider { private updateLinkProviderWorker(): void { // We have a workspace - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { // Register link provider unless done already if (!this.linkProviderRegistration) { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts index d81800c8cfb..8343d24ff77 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts @@ -80,7 +80,7 @@ export class OpenWorkspaceSettingsAction extends Action { @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(id, label); - this.enabled = this.workspaceContextService.hasWorkspace(); + this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY; } public run(event?: any): TPromise { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index e1ce90b0cc2..1702c4cb62e 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -191,7 +191,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } openWorkspaceSettings(): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); return TPromise.as(null); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index b6d575759aa..0b7e9166401 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -337,7 +337,7 @@ export class SettingsTargetsWidget extends Widget { run: () => this.onTargetClicked(userSettingsResource) }); - if (this.workspaceContextService.hasWorkspace()) { + if (this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { const workspaceSettingsResource = this.preferencesService.workspaceSettingsResource; actions.push({ id: 'workspaceSettingsTarget', diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index bb19b6d2ce7..0796ebff2bd 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -28,7 +28,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IQueryOptions, ISearchService, ISearchStats, ISearchQuery } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IRange } from 'vs/editor/common/core/range'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/parts/search/common/search'; @@ -164,7 +164,7 @@ export class OpenFileHandler extends QuickOpenHandler { iconClass = 'file'; // only use a generic file icon if we are forced to use an icon and have no icon theme set otherwise } - const folderResources = this.contextService.hasWorkspace() ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; return this.searchService.search(this.queryBuilder.file(folderResources, query)).then((complete) => { const results: QuickOpenEntry[] = []; for (let i = 0; i < complete.results.length; i++) { @@ -199,7 +199,7 @@ export class OpenFileHandler extends QuickOpenHandler { useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; - const folderResources = this.contextService.hasWorkspace() ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; const query = this.queryBuilder.file(folderResources, options); return query; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 6f27f6771ca..ae803b2c249 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -239,7 +239,7 @@ export class SearchViewlet extends Viewlet { }).getHTMLElement(); this.messages = builder.div({ 'class': 'messages' }).hide().clone(); - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.searchWithoutFolderMessage(this.clearMessage()); } @@ -753,7 +753,7 @@ export class SearchViewlet extends Viewlet { public clearSearchResults(): void { this.viewModel.searchResult.clear(); this.showEmptyStage(); - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.searchWithoutFolderMessage(this.clearMessage()); } this.searchWidget.clear(); @@ -960,7 +960,7 @@ export class SearchViewlet extends Viewlet { excludePattern, includePattern }; - const folderResources = this.contextService.hasWorkspace() ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; const onQueryValidationError = (err: Error) => { this.searchWidget.searchInput.showMessage({ content: err.message, type: MessageType.ERROR }); @@ -1123,7 +1123,7 @@ export class SearchViewlet extends Viewlet { }).on(dom.EventType.CLICK, (e: MouseEvent) => { dom.EventHelper.stop(e, false); - let editorPromise = this.contextService.hasWorkspace() ? this.preferencesService.openWorkspaceSettings() : this.preferencesService.openGlobalSettings(); + let editorPromise = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.preferencesService.openWorkspaceSettings() : this.preferencesService.openGlobalSettings(); editorPromise.done(editor => { if (editor instanceof PreferencesEditor) { editor.focusSearch('.exclude'); @@ -1148,7 +1148,7 @@ export class SearchViewlet extends Viewlet { }); } - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.searchWithoutFolderMessage(div); } } else { diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 5c4ccaefcc8..839402f295a 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -184,7 +184,7 @@ export class QueryBuilder { * Split search paths (./ or absolute paths in the includePatterns) into absolute paths and globs applied to those paths */ private expandSearchPathPatterns(searchPaths: string[]): ISearchPathPattern[] { - if (!this.workspaceContextService.hasWorkspace() || !searchPaths || !searchPaths.length) { + if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.EMPTY || !searchPaths || !searchPaths.length) { // No workspace => ignore search paths return []; } diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index a1f13668c09..374d057cf16 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -67,7 +67,7 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IConfigurationEditingService, ConfigurationTarget, IConfigurationValue } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IOutputService, IOutputChannelRegistry, Extensions as OutputExt, IOutputChannel } from 'vs/workbench/parts/output/common/output'; @@ -113,7 +113,7 @@ abstract class OpenTaskConfigurationAction extends Action { } public run(event?: any): TPromise { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('ConfigureTaskRunnerAction.noWorkspace', 'Tasks are only available on a workspace folder.')); return TPromise.as(undefined); } @@ -308,7 +308,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { super.updateStyles(); this.icons.forEach(icon => { - icon.style.backgroundColor = this.getColor(this.contextService.hasWorkspace() ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND); + icon.style.backgroundColor = this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND); }); } @@ -1547,7 +1547,7 @@ class TaskService extends EventEmitter implements ITaskService { } private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.hasWorkspace() ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; + let result = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; if (!result) { return { config: undefined, hasParseErrors: false }; } @@ -1589,7 +1589,7 @@ class TaskService extends EventEmitter implements ITaskService { } private hasDetectorSupport(config: TaskConfig.ExternalTaskRunnerConfiguration): boolean { - if (!config.command || !this.contextService.hasWorkspace()) { + if (!config.command || this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { return false; } return ProcessRunnerDetector.supports(config.command); @@ -1700,7 +1700,7 @@ class TaskService extends EventEmitter implements ITaskService { } private canRunCommand(): boolean { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('TaskService.noWorkspace', 'Tasks are only available on a workspace folder.')); return false; } diff --git a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts index 22e79fe9aa2..abb98943900 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts @@ -18,7 +18,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import * as Tasks from '../common/tasks'; import * as TaskConfig from './taskConfiguration'; @@ -156,7 +156,7 @@ export class ProcessRunnerDetector { this.taskConfiguration = config; this._stderr = []; this._stdout = []; - this._cwd = this.contextService.hasWorkspace() ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; + this._cwd = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; } public get stderr(): string[] { diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 8d108a933d7..1ab7fbaf6c7 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -14,7 +14,7 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -147,7 +147,7 @@ export class WatermarkContribution implements IWorkbenchContribution { .div({ 'class': 'watermark' }); const box = $(this.watermark) .div({ 'class': 'watermark-box' }); - const folder = this.contextService.hasWorkspace(); + const folder = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY; const selected = folder ? folderEntries : noFolderEntries .filter(entry => !('mac' in entry) || entry.mac === isMacintosh); const update = () => { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 4a621ea0883..d3c6251f960 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -208,10 +208,6 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return WorkspaceState.EMPTY; } - public hasWorkspace(): boolean { - return !!this.workspace; - } - public getRoot(resource: URI): URI { return this.workspace ? this.workspace.getRoot(resource) : null; } diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index cc950d2e3c3..65a09c09b8d 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -252,7 +252,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } // Target cannot be workspace or folder if no workspace opened - if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.FOLDER) && !this.contextService.hasWorkspace()) { + if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.FOLDER) && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED, target, operation); } diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 402c628d38c..bf6175f9cd0 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -15,7 +15,7 @@ import { toResource } from 'vs/workbench/common/editor'; import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { Action } from 'vs/base/common/actions'; import { ResourceMap } from 'vs/base/common/map'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -146,7 +146,7 @@ export class FileService implements IFileService { private getEncodingOverrides(): IEncodingOverride[] { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { this.contextService.getWorkspace().roots.forEach(root => { encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); }); diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index 942a4d1207a..6f86a23260f 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -25,7 +25,7 @@ import uri from 'vs/base/common/uri'; import nls = require('vs/nls'); import { isWindows, isLinux } from 'vs/base/common/platform'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import pfs = require('vs/base/node/pfs'); import encoding = require('vs/base/node/encoding'); @@ -101,7 +101,7 @@ export class FileService implements IFileService { this.toDispose = []; this.options = options || Object.create(null); this.tmpPath = this.options.tmpDir || os.tmpdir(); - this.currentWorkspaceRootsCount = contextService.hasWorkspace() ? contextService.getWorkspace().roots.length : 0; + this.currentWorkspaceRootsCount = contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? contextService.getWorkspace().roots.length : 0; this._onFileChanges = new Emitter(); this.toDispose.push(this._onFileChanges); @@ -129,7 +129,7 @@ export class FileService implements IFileService { } private onDidChangeWorkspaceRoots(): void { - const newRootCount = this.contextService.hasWorkspace() ? this.contextService.getWorkspace().roots.length : 0; + const newRootCount = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots.length : 0; let restartWorkspaceWatcher = false; if (this.currentWorkspaceRootsCount <= 1 && newRootCount > 1) { diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 3b55591f9ff..7620195f439 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -15,7 +15,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { FileChangesEvent, IFileService, FileChangeType } from 'vs/platform/files/common/files'; import { Selection } from 'vs/editor/common/core/selection'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -769,7 +769,7 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic } public getLastActiveWorkspaceRoot(): URI { - if (!this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { return void 0; } diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index bdfaaa0b9ba..652d5b870b3 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -19,7 +19,7 @@ import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); import { IMode } from 'vs/editor/common/modes'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; @@ -745,7 +745,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for workspace settings file - if (this.contextService.hasWorkspace()) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { return this.contextService.getWorkspace().roots.some(root => { return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); }); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index 70e7a582514..efca3d0de47 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -17,7 +17,7 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IRevertOptions, IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ConfirmResult } from 'vs/workbench/common/editor'; import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IFileService, IResolveContentOptions, IFilesConfiguration, FileOperationError, FileOperationResult, AutoSaveConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -180,7 +180,7 @@ export abstract class TextFileService implements ITextFileService { let doBackup: boolean; switch (reason) { case ShutdownReason.CLOSE: - if (this.contextService.hasWorkspace() && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { doBackup = true; // backup if a folder is open and onExitAndWindowClose is configured } else if (windowCount > 1 || platform.isMacintosh) { doBackup = false; // do not backup if a window is closed that does not cause quitting of the application @@ -198,7 +198,7 @@ export abstract class TextFileService implements ITextFileService { break; case ShutdownReason.LOAD: - if (this.contextService.hasWorkspace() && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { doBackup = true; // backup if a folder is open and onExitAndWindowClose is configured } else { doBackup = false; // do not backup because we are switching contexts diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index bdd3aed7bb9..082b2c10d57 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -104,10 +104,6 @@ export class TestContextService implements IWorkspaceContextService { return WorkspaceState.EMPTY; } - public hasWorkspace(): boolean { - return !!this.workspace; - } - public getWorkspace(): IWorkbenchWorkspace { return this.workspace; } From 3ac4826939631336f4989fa7421aad7d6258de8a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 12 Sep 2017 17:29:29 +0200 Subject: [PATCH 038/145] list: dont cancel list mouse events --- src/vs/base/browser/ui/list/listWidget.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 3a4e10f7b26..9eb101a4f35 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -348,8 +348,6 @@ class MouseController implements IDisposable { } private onMouseDown(e: IListMouseEvent): void { - e.preventDefault(); - e.stopPropagation(); this.view.domNode.focus(); let reference = this.list.getFocus()[0]; @@ -373,9 +371,6 @@ class MouseController implements IDisposable { } private onPointer(e: IListMouseEvent): void { - e.preventDefault(); - e.stopPropagation(); - if (isSelectionChangeEvent(e)) { return; } @@ -388,9 +383,6 @@ class MouseController implements IDisposable { } private onDoubleClick(e: IListMouseEvent): void { - e.preventDefault(); - e.stopPropagation(); - if (isSelectionChangeEvent(e)) { return; } From b1a7be798ed97eb9890190253af6dbf3d1874419 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 13 Sep 2017 09:18:09 +0200 Subject: [PATCH 039/145] add git.stageAll to provider menu related to #34230 --- extensions/git/package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/git/package.json b/extensions/git/package.json index bd646d7f8a6..995ac785f74 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -529,6 +529,11 @@ "group": "3_commit", "when": "config.git.enabled && scmProvider == git" }, + { + "command": "git.stageAll", + "group": "4_stage", + "when": "config.git.enabled && scmProvider == git" + }, { "command": "git.unstageAll", "group": "4_stage", From 276d5bbabaea2d54080da268bb1e47d1b81cbd7f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 13 Sep 2017 09:25:07 +0200 Subject: [PATCH 040/145] fix #34098 --- src/vs/platform/environment/node/environmentService.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 7d41a098c7a..36a1ed42492 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -10,7 +10,7 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import URI from 'vs/base/common/uri'; -import { generateUuid } from 'vs/base/common/uuid'; +import { generateUuid, isUUID } from 'vs/base/common/uuid'; import { memoize } from 'vs/base/common/decorators'; import pkg from 'vs/platform/node/package'; import product from 'vs/platform/node/product'; @@ -155,11 +155,15 @@ export class EnvironmentService implements IEnvironmentService { try { this.machineUUID = fs.readFileSync(machineIdPath, 'utf8'); + + if (!isUUID(this.machineUUID)) { + throw new Error('Not a UUID'); + } } catch (err) { this.machineUUID = generateUuid(); try { - fs.writeFileSync(machineIdPath, this.machineUUID); + fs.writeFileSync(machineIdPath, this.machineUUID, 'utf8'); } catch (err) { console.warn('Could not store machine ID'); } From f26842cb123e2564813f1327af49ee2c3bd641e2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 13 Sep 2017 09:43:04 +0200 Subject: [PATCH 041/145] config - do not report file change event for files that are unrelated --- src/vs/base/node/config.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/vs/base/node/config.ts b/src/vs/base/node/config.ts index 6d30e650d6e..4ec9fede36f 100644 --- a/src/vs/base/node/config.ts +++ b/src/vs/base/node/config.ts @@ -6,7 +6,7 @@ 'use strict'; import * as fs from 'fs'; -import * as path from 'path'; +import { dirname, basename } from 'path'; import * as objects from 'vs/base/common/objects'; import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; @@ -49,9 +49,11 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { private timeoutHandle: NodeJS.Timer; private disposables: IDisposable[]; private _onDidUpdateConfiguration: Emitter>; + private configName: string; constructor(private _path: string, private options: IConfigOptions = { changeBufferDelay: 0, defaultConfig: Object.create(null), onError: error => console.error(error) }) { this.disposables = []; + this.configName = basename(this._path); this._onDidUpdateConfiguration = new Emitter>(); this.disposables.push(this._onDidUpdateConfiguration); @@ -121,8 +123,8 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { private registerWatcher(): void { // Watch the parent of the path so that we detect ADD and DELETES - const parentFolder = path.dirname(this._path); - this.watch(parentFolder); + const parentFolder = dirname(this._path); + this.watch(parentFolder, true); // Check if the path is a symlink and watch its target if so fs.lstat(this._path, (err, stat) => { @@ -137,20 +139,20 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { return; // path is not a valid symlink } - this.watch(realPath); + this.watch(realPath, false); }); } }); } - private watch(path: string): void { + private watch(path: string, isParentFolder: boolean): void { if (this.disposed) { return; // avoid watchers that will never get disposed by checking for being disposed } try { const watcher = fs.watch(path); - watcher.on('change', () => this.onConfigFileChange()); + watcher.on('change', (type, file) => this.onConfigFileChange(type, file.toString(), isParentFolder)); watcher.on('error', (code, signal) => this.options.onError(`Error watching ${path} for configuration changes (${code}, ${signal})`)); this.disposables.push(toDisposable(() => { @@ -166,7 +168,11 @@ export class ConfigWatcher implements IConfigWatcher, IDisposable { } } - private onConfigFileChange(): void { + private onConfigFileChange(eventType: string, filename: string, isParentFolder: boolean): void { + if (isParentFolder && filename !== this.configName) { + return; // a change to a sibling file that is not our config file + } + if (this.timeoutHandle) { global.clearTimeout(this.timeoutHandle); this.timeoutHandle = null; From 292017d78ce2d9320e025875f55eaa9d53dad60b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 09:55:38 +0200 Subject: [PATCH 042/145] Avoid checking for workspace exists or not. Instead use the EMPTY workspace state --- .../api/electron-browser/mainThreadWorkspace.ts | 8 ++++---- src/vs/workbench/browser/actions/workspaceActions.ts | 8 +++++--- .../workbench/browser/parts/titlebar/titlebarPart.ts | 4 ++-- .../electron-browser/debugConfigurationManager.ts | 5 ++--- .../parts/files/browser/views/explorerViewer.ts | 3 +-- .../parts/preferences/browser/preferencesEditor.ts | 7 +++---- .../parts/preferences/browser/preferencesService.ts | 5 ++++- .../electron-browser/relauncher.contribution.ts | 10 +++++----- src/vs/workbench/parts/search/browser/searchViewlet.ts | 4 ++-- src/vs/workbench/parts/search/common/queryBuilder.ts | 5 ++--- .../configuration/node/configurationEditingService.ts | 5 +++-- .../extensions/electron-browser/extensionHost.ts | 4 ++-- .../services/telemetry/common/workspaceStats.ts | 9 +++++---- 13 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index ad58576214d..3e721a473e5 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -7,7 +7,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { ISearchService, QueryType, ISearchQuery, ISearchProgressItem, ISearchComplete } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ICommonCodeEditor, isCommonCodeEditor } from 'vs/editor/common/editorCommon'; @@ -53,17 +53,17 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- workspace --- private _onDidChangeWorkspace(): void { - this._proxy.$acceptWorkspaceData(this._contextService.getWorkspace()); + this._proxy.$acceptWorkspaceData(this._contextService.getWorkspaceState() === WorkspaceState.EMPTY ? null : this._contextService.getWorkspace()); } // --- search --- $startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable { - const workspace = this._contextService.getWorkspace(); - if (!workspace) { + if (this._contextService.getWorkspaceState() === WorkspaceState.EMPTY) { return undefined; } + const workspace = this._contextService.getWorkspace(); const query: ISearchQuery = { folderQueries: workspace.roots.map(root => ({ folder: root })), type: QueryType.File, diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 974388b03ad..5442a51b924 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -74,10 +74,12 @@ export abstract class BaseWorkspacesAction extends Action { } protected pickFolders(buttonLabel: string, title: string): string[] { - const workspace = this.contextService.getWorkspace(); let defaultPath: string; - if (workspace && workspace.roots.length > 0) { - defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + const workspace = this.contextService.getWorkspace(); + if (workspace.roots.length > 0) { + defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default + } } return this.windowService.showOpenDialog({ diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index a0d4bee32ac..719f472343f 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -27,7 +27,7 @@ import nls = require('vs/nls'); import * as labels from 'vs/base/common/labels'; import { EditorInput, toResource } from 'vs/workbench/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { Verbosity } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND, TITLE_BAR_BORDER } from 'vs/workbench/common/theme'; @@ -199,7 +199,7 @@ export class TitlebarPart extends Part implements ITitleService { // Single Root Workspace: always the root single workspace in this case // Multi Root Workspace: root folder of the currently active file if any let folder: URI; - if (workspace) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { if (workspace.roots.length === 1) { folder = workspace.roots[0]; } else { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 980714a1412..375ea4757d5 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -26,7 +26,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, DEBUG_SCHEME, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug'; @@ -353,8 +353,7 @@ export class ConfigurationManager implements IConfigurationManager { } private initLaunches(): void { - const workspace = this.contextService.getWorkspace(); - this.launches = workspace ? workspace.roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; + this.launches = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 60c6519a6e2..1a1cc1665e8 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -838,8 +838,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(true) : DRAG_OVER_ACCEPT_BUBBLE_DOWN(true); } - const workspace = this.contextService.getWorkspace(); - if (workspace && workspace.roots.every(r => r.toString() !== target.resource.toString())) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_UP_COPY : DRAG_OVER_ACCEPT_BUBBLE_UP; } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 7b92f7a36ff..4396f6183be 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -56,7 +56,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -886,9 +886,8 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return true; } - const workspace = this.workspaceContextService.getWorkspace(); - if (workspace) { - for (const root of workspace.roots) { + if (this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + for (const root of this.workspaceContextService.getWorkspace().roots) { const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { return true; diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 1702c4cb62e..fba7f931a69 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -316,8 +316,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic case ConfigurationTarget.USER: return URI.file(this.environmentService.appSettingsPath); case ConfigurationTarget.WORKSPACE: + if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + return null; + } const workspace = this.contextService.getWorkspace(); - return workspace ? workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]) : null; + return workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]); case ConfigurationTarget.FOLDER: const root = this.contextService.getRoot(resource); return root ? this.toResource(paths.join('.vscode', 'settings.json'), root) : null; diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index f83349ff4f7..a907fbb8044 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -14,7 +14,7 @@ import { IWindowsService, IWindowService, IWindowsConfiguration } from 'vs/platf import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; interface IConfiguration extends IWindowsConfiguration { @@ -43,8 +43,8 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IWorkspaceContextService private contextService: IWorkspaceContextService, @IExtensionService private extensionService: IExtensionService ) { - const workspace = this.contextService.getWorkspace(); - if (workspace) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + const workspace = this.contextService.getWorkspace(); this.rootCount = workspace.roots.length; this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; } else { @@ -102,8 +102,8 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private onDidChangeWorkspaceRoots(): void { const workspace = this.contextService.getWorkspace(); - const newRootCount = workspace ? workspace.roots.length : 0; - const newFirstRootPath = workspace && workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; + const newRootCount = workspace.roots.length; + const newFirstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; let reloadWindow = false; let reloadExtensionHost = false; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index ae803b2c249..c9c756e9859 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -870,8 +870,8 @@ export class SearchViewlet extends Viewlet { public searchInFolder(resource: URI): void { let folderPath = null; - const workspace = this.contextService.getWorkspace(); - if (workspace && resource) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && resource) { + const workspace = this.contextService.getWorkspace(); if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { // Show relative path from the root for single-root mode folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 839402f295a..4aebdf42718 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -212,17 +212,16 @@ export class QueryBuilder { return [paths.normalize(searchPath)]; } - const workspace = this.workspaceContextService.getWorkspace(); if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.FOLDER) { // TODO: @Sandy Try checking workspace folders length instead. return [paths.normalize( - paths.join(workspace.roots[0].fsPath, searchPath))]; + paths.join(this.workspaceContextService.getWorkspace().roots[0].fsPath, searchPath))]; } else if (searchPath === './') { return []; // ./ or ./**/foo makes sense for single-folder but not multi-folder workspaces } else { const relativeSearchPathMatch = searchPath.match(/\.[\/\\]([^\/\\]+)([\/\\].+)?/); if (relativeSearchPathMatch) { const searchPathRoot = relativeSearchPathMatch[1]; - const matchingRoots = workspace.roots.filter(root => paths.basename(root.fsPath) === searchPathRoot); + const matchingRoots = this.workspaceContextService.getWorkspace().roots.filter(root => paths.basename(root.fsPath) === searchPathRoot); if (matchingRoots.length) { return matchingRoots.map(root => { return relativeSearchPathMatch[2] ? diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 65a09c09b8d..40e491de3f5 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -327,9 +327,10 @@ export class ConfigurationEditingService implements IConfigurationEditingService return URI.file(this.environmentService.appSettingsPath); } - const workspace = this.contextService.getWorkspace(); - if (workspace) { + if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + + const workspace = this.contextService.getWorkspace(); if (target === ConfigurationTarget.WORKSPACE) { return workspace.configuration || this.toResource(relativePath, workspace.roots[0]); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 13137b48b4c..3e70add7ef3 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -16,7 +16,7 @@ import { findFreePort } from 'vs/base/node/ports'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { ILifecycleService, ShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ChildProcess, fork } from 'child_process'; import { ipcRenderer as ipc } from 'electron'; @@ -356,7 +356,7 @@ export class ExtensionHostProcessWorker { enableProposedApiForAll: !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0), enableProposedApiFor: this._environmentService.args['enable-proposed-api'] || [] }, - workspace: this._contextService.getWorkspace(), + workspace: this._contextService.getWorkspaceState() === WorkspaceState.EMPTY ? null : this._contextService.getWorkspace(), extensions: extensionDescriptions, configuration: this._configurationService.getConfigurationData(), telemetryInfo diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index dd8965ca6bb..4bf2393d0b6 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -11,7 +11,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; @@ -152,11 +152,12 @@ export class WorkspaceStats { tags['workbench.filesToCreate'] = filesToCreate && filesToCreate.length || undefined; tags['workbench.filesToDiff'] = filesToDiff && filesToDiff.length || undefined; + const isEmpty = this.contextService.getWorkspaceState() === WorkspaceState.EMPTY; const workspace = this.contextService.getWorkspace(); - tags['workspace.roots'] = workspace ? workspace.roots.length : 0; - tags['workspace.empty'] = !workspace; + tags['workspace.roots'] = isEmpty ? 0 : workspace.roots.length; + tags['workspace.empty'] = isEmpty; - const folders = workspace ? workspace.roots : this.environmentService.appQuality !== 'stable' && this.findFolders(configuration); + const folders = !isEmpty ? workspace.roots : this.environmentService.appQuality !== 'stable' && this.findFolders(configuration); if (folders && folders.length && this.fileService) { return this.fileService.resolveFiles(folders.map(resource => ({ resource }))).then(results => { const names = ([]).concat(...results.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); From 923c98707280efb5618f12d2e64f5f1cbf21baca Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 10:04:51 +0200 Subject: [PATCH 043/145] Rename WorkspaceState to WorkbenchState --- .../standalone/browser/simpleServices.ts | 10 ++--- .../common/extensionEnablementService.ts | 4 +- .../common/extensionEnablementService.test.ts | 8 ++-- .../test/common/storageService.test.ts | 4 +- src/vs/platform/workspace/common/workspace.ts | 12 +++--- .../mainThreadConfiguration.ts | 4 +- .../electron-browser/mainThreadWorkspace.ts | 6 +-- .../browser/actions/workspaceActions.ts | 20 +++++----- .../browser/parts/statusbar/statusbarPart.ts | 8 ++-- .../browser/parts/titlebar/titlebarPart.ts | 4 +- src/vs/workbench/browser/parts/views/views.ts | 6 +-- src/vs/workbench/common/resources.ts | 4 +- src/vs/workbench/electron-browser/actions.ts | 4 +- src/vs/workbench/electron-browser/main.ts | 12 +++--- src/vs/workbench/electron-browser/shell.ts | 4 +- src/vs/workbench/electron-browser/window.ts | 6 +-- .../workbench/electron-browser/workbench.ts | 10 ++--- .../parts/debug/browser/debugActions.ts | 6 +-- .../parts/debug/browser/debugViewlet.ts | 8 ++-- .../debug/electron-browser/debugCommands.ts | 4 +- .../debugConfigurationManager.ts | 4 +- .../debug/electron-browser/debugService.ts | 10 ++--- .../debug/electron-browser/debugViewer.ts | 4 +- .../statusbarColorProvider.ts | 4 +- .../extensions/browser/extensionsActions.ts | 14 +++---- .../electron-browser/extensionTipsService.ts | 4 +- .../node/extensionsWorkbenchService.ts | 4 +- .../electron-browser/feedbackStatusbarItem.ts | 4 +- .../parts/files/browser/explorerViewlet.ts | 6 +-- .../parts/files/browser/views/explorerView.ts | 4 +- .../files/browser/views/explorerViewer.ts | 8 ++-- .../parts/output/common/outputLinkProvider.ts | 4 +- .../preferences/browser/preferencesActions.ts | 6 +-- .../preferences/browser/preferencesEditor.ts | 4 +- .../browser/preferencesRenderers.ts | 4 +- .../preferences/browser/preferencesService.ts | 12 +++--- .../preferences/browser/preferencesWidgets.ts | 8 ++-- .../relauncher.contribution.ts | 4 +- .../parts/search/browser/openFileHandler.ts | 6 +-- .../parts/search/browser/searchViewlet.ts | 18 ++++----- .../parts/search/common/queryBuilder.ts | 6 +-- .../electron-browser/task.contribution.ts | 12 +++--- .../parts/tasks/node/processRunnerDetector.ts | 4 +- .../watermark/electron-browser/watermark.ts | 4 +- .../configuration/node/configuration.ts | 18 ++++----- .../node/configurationEditingService.ts | 8 ++-- .../electron-browser/extensionHost.ts | 4 +- .../files/electron-browser/fileService.ts | 4 +- .../services/files/node/fileService.ts | 6 +-- .../services/history/browser/history.ts | 4 +- .../telemetry/common/workspaceStats.ts | 4 +- .../textfile/common/textFileEditorModel.ts | 4 +- .../textfile/common/textFileService.ts | 6 +-- .../node/workspaceMigrationService.ts | 4 +- .../api/mainThreadConfiguration.test.ts | 40 +++++++++---------- .../workbench/test/workbenchTestServices.ts | 10 ++--- 56 files changed, 207 insertions(+), 207 deletions(-) diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 197924f0f74..228879e82dc 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -18,7 +18,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, IWorkspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, WorkbenchState } 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'; @@ -539,14 +539,14 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { return this.workspace; } - public getWorkspaceState(): WorkspaceState { + public getWorkbenchState(): WorkbenchState { if (this.workspace) { if (this.workspace.configuration) { - return WorkspaceState.WORKSPACE; + return WorkbenchState.WORKSPACE; } - return WorkspaceState.FOLDER; + return WorkbenchState.FOLDER; } - return WorkspaceState.EMPTY; + return WorkbenchState.EMPTY; } public getRoot(resource: URI): URI { diff --git a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts index af0dedd15bf..65348d5095c 100644 --- a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts @@ -10,7 +10,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { adoptToGalleryExtensionId, getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -35,7 +35,7 @@ export class ExtensionEnablementService implements IExtensionEnablementService { } private get hasWorkspace(): boolean { - return this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY; + return this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; } public getGloballyDisabledExtensions(): string[] { diff --git a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts index 12287b6bd4e..e35a98d864c 100644 --- a/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/extensionEnablementService.test.ts @@ -12,7 +12,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { Emitter } from 'vs/base/common/event'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; function storageService(instantiationService: TestInstantiationService): IStorageService { @@ -21,7 +21,7 @@ function storageService(instantiationService: TestInstantiationService): IStorag let workspaceContextService = instantiationService.get(IWorkspaceContextService); if (!workspaceContextService) { workspaceContextService = instantiationService.stub(IWorkspaceContextService, { - getWorkspaceState: () => WorkspaceState.FOLDER, + getWorkbenchState: () => WorkbenchState.FOLDER, }); } service = instantiationService.stub(IStorageService, instantiationService.createInstance(StorageService, new InMemoryLocalStorage(), new InMemoryLocalStorage())); @@ -71,7 +71,7 @@ suite('ExtensionEnablementService Test', () => { test('test when no extensions are disabled for workspace when there is no workspace', (done) => { testObject.setEnablement('pub.a', false, true) .then(() => { - instantiationService.stub(IWorkspaceContextService, 'getWorkspaceState', WorkspaceState.EMPTY); + instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY); assert.deepEqual([], testObject.getWorkspaceDisabledExtensions()); }) .then(done, done); @@ -176,7 +176,7 @@ suite('ExtensionEnablementService Test', () => { }); test('test disable an extension for workspace when there is no workspace throws error', (done) => { - instantiationService.stub(IWorkspaceContextService, 'getWorkspaceState', WorkspaceState.EMPTY); + instantiationService.stub(IWorkspaceContextService, 'getWorkbenchState', WorkbenchState.EMPTY); testObject.setEnablement('pub.a', false, true) .then(() => assert.fail('should throw an error'), error => assert.ok(error)) .then(done, done); diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index 8a7f3249e26..f51d6957118 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -8,7 +8,7 @@ import * as assert from 'assert'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { StorageScope } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService, IWorkspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common/storageService'; import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; @@ -19,7 +19,7 @@ suite('Workbench StorageSevice', () => { setup(() => { instantiationService = new TestInstantiationService(); contextService = instantiationService.stub(IWorkspaceContextService, { - getWorkspaceState: () => WorkspaceState.FOLDER, + getWorkbenchState: () => WorkbenchState.FOLDER, getWorkspace: () => { return TestWorkspace; } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index 5afdc03d70e..bd4239f560a 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -14,7 +14,7 @@ import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platf export const IWorkspaceContextService = createDecorator('contextService'); -export enum WorkspaceState { +export enum WorkbenchState { EMPTY = 1, FOLDER, WORKSPACE @@ -30,13 +30,13 @@ export interface IWorkspaceContextService { getWorkspace(): IWorkspace; /** - * Return the state of the current workspace. + * Return the state of the workbench. * - * WorkspaceState.EMPTY - if the application was opened with empty window or file - * WorkspaceState.FOLDER - if the application was opened with a folder - * WorkspaceState.WORKSPACE - if the application was opened with a workspace + * WorkbenchState.EMPTY - if the workbench was opened with empty window or file + * WorkbenchState.FOLDER - if the workbench was opened with a folder + * WorkbenchState.WORKSPACE - if the workbench was opened with a workspace */ - getWorkspaceState(): WorkspaceState; + getWorkbenchState(): WorkbenchState; /** * An event which fires on workspace name changes. diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 17c48b27a99..71f54113cfd 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext } from '../node/extHost.protocol'; @@ -51,7 +51,7 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { } private deriveConfigurationTarget(key: string, resource: URI): ConfigurationTarget { - if (resource && this._workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (resource && this._workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { const configurationProperties = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); if (configurationProperties[key] && configurationProperties[key].scope === ConfigurationScope.RESOURCE) { return ConfigurationTarget.FOLDER; diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 3e721a473e5..1f39e8c702c 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -7,7 +7,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { ISearchService, QueryType, ISearchQuery, ISearchProgressItem, ISearchComplete } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ICommonCodeEditor, isCommonCodeEditor } from 'vs/editor/common/editorCommon'; @@ -53,13 +53,13 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- workspace --- private _onDidChangeWorkspace(): void { - this._proxy.$acceptWorkspaceData(this._contextService.getWorkspaceState() === WorkspaceState.EMPTY ? null : this._contextService.getWorkspace()); + this._proxy.$acceptWorkspaceData(this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace()); } // --- search --- $startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable { - if (this._contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this._contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return undefined; } diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 5442a51b924..57a029520dc 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -11,7 +11,7 @@ import nls = require('vs/nls'); import { distinct } from 'vs/base/common/arrays'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import URI from 'vs/base/common/uri'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -75,7 +75,7 @@ export abstract class BaseWorkspacesAction extends Action { protected pickFolders(buttonLabel: string, title: string): string[] { let defaultPath: string; - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { const workspace = this.contextService.getWorkspace(); if (workspace.roots.length > 0) { defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default @@ -110,15 +110,15 @@ export class AddRootFolderAction extends BaseWorkspacesAction { } public run(): TPromise { - switch (this.contextService.getWorkspaceState()) { + switch (this.contextService.getWorkbenchState()) { - case WorkspaceState.EMPTY: + case WorkbenchState.EMPTY: return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); - case WorkspaceState.FOLDER: + case WorkbenchState.FOLDER: return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); - case WorkspaceState.WORKSPACE: + case WorkbenchState.WORKSPACE: const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); if (!folders || !folders.length) { return TPromise.as(null); @@ -202,8 +202,8 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { } public run(): TPromise { - const workspaceState = this.contextService.getWorkspaceState(); - if (workspaceState === WorkspaceState.EMPTY) { + const workspaceState = this.contextService.getWorkbenchState(); + if (workspaceState === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('saveEmptyWorkspaceNotSupported', "Please open a workspace first to save.")); return TPromise.as(null); } @@ -212,11 +212,11 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { if (configPath) { switch (workspaceState) { - case WorkspaceState.FOLDER: + case WorkbenchState.FOLDER: const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); - case WorkspaceState.WORKSPACE: + case WorkbenchState.WORKSPACE: return this.windowService.saveAndOpenWorkspace(configPath); } } diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 7fd8baac704..ea688b70089 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -28,7 +28,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { Action } from 'vs/base/common/actions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { isThemeColor } from 'vs/editor/common/editorCommon'; import { Color } from 'vs/base/common/color'; @@ -141,10 +141,10 @@ export class StatusbarPart extends Part implements IStatusbarService { const container = this.getContainer(); - container.style('color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); - container.style('background-color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND)); + container.style('color', this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); + container.style('background-color', this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BACKGROUND : STATUS_BAR_NO_FOLDER_BACKGROUND)); - const borderColor = this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER) || this.getColor(contrastBorder); + const borderColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_BORDER : STATUS_BAR_NO_FOLDER_BORDER) || this.getColor(contrastBorder); container.style('border-top-width', borderColor ? '1px' : null); container.style('border-top-style', borderColor ? 'solid' : null); container.style('border-top-color', borderColor); diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index 719f472343f..cf0c71ace23 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -27,7 +27,7 @@ import nls = require('vs/nls'); import * as labels from 'vs/base/common/labels'; import { EditorInput, toResource } from 'vs/workbench/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Verbosity } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_BACKGROUND, TITLE_BAR_BORDER } from 'vs/workbench/common/theme'; @@ -199,7 +199,7 @@ export class TitlebarPart extends Part implements ITitleService { // Single Root Workspace: always the root single workspace in this case // Multi Root Workspace: root folder of the currently active file if any let folder: URI; - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { if (workspace.roots.length === 1) { folder = workspace.roots[0]; } else { diff --git a/src/vs/workbench/browser/parts/views/views.ts b/src/vs/workbench/browser/parts/views/views.ts index 0e254b6c0ce..d50f7bde1be 100644 --- a/src/vs/workbench/browser/parts/views/views.ts +++ b/src/vs/workbench/browser/parts/views/views.ts @@ -28,7 +28,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND } from 'vs/workbench/common/theme'; @@ -776,11 +776,11 @@ export class PersistentViewsViewlet extends ViewsViewlet { } }); - this.storageService.store(this.viewletStateStorageId, JSON.stringify(viewsStates), this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL); + this.storageService.store(this.viewletStateStorageId, JSON.stringify(viewsStates), this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL); } private loadViewsStates(): void { - const viewsStates = JSON.parse(this.storageService.get(this.viewletStateStorageId, this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL, '{}')); + const viewsStates = JSON.parse(this.storageService.get(this.viewletStateStorageId, this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? StorageScope.WORKSPACE : StorageScope.GLOBAL, '{}')); Object.keys(viewsStates).forEach(id => this.viewsStates.set(id, viewsStates[id])); } } \ No newline at end of file diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index d401bb087b8..3bf29ca9d9b 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import objects = require('vs/base/common/objects'); import paths = require('vs/base/common/paths'); -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -106,7 +106,7 @@ export class ResourceGlobMatcher { let changed = false; // Add excludes per workspaces that got added - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { this.contextService.getWorkspace().roots.forEach(root => { const rootExcludes = this.globFn(root); if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 559f03a75c5..67796b9bc2f 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -18,7 +18,7 @@ import product from 'vs/platform/node/product'; import pkg from 'vs/platform/node/package'; import errors = require('vs/base/common/errors'); import { IMessageService, Severity } from 'vs/platform/message/common/message'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -104,7 +104,7 @@ export class CloseWorkspaceAction extends Action { } run(): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close.")); return TPromise.as(null); diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 95762448da1..f48b79e1522 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -16,7 +16,7 @@ import platform = require('vs/base/common/platform'); import paths = require('vs/base/common/paths'); import uri from 'vs/base/common/uri'; import strings = require('vs/base/common/strings'); -import { IWorkspaceContextService, Workspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, Workspace, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { EmptyWorkspaceServiceImpl, WorkspaceServiceImpl, WorkspaceService } from 'vs/workbench/services/configuration/node/configuration'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -79,7 +79,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { // Since the configuration service is one of the core services that is used in so many places, we initialize it // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService, mainServices.get(IWorkspacesService)).then(workspaceService => { - const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkspaceState() === WorkspaceState.EMPTY); + const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); const storageService = createStorageService(configuration, workspaceService, environmentService); timerService.beforeDOMContentLoaded = Date.now(); @@ -153,16 +153,16 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ let workspaceId: string; let secondaryWorkspaceId: number; - switch (workspaceService.getWorkspaceState()) { + switch (workspaceService.getWorkbenchState()) { // in multi root workspace mode we use the provided ID as key for workspace storage - case WorkspaceState.WORKSPACE: + case WorkbenchState.WORKSPACE: workspaceId = uri.from({ path: workspace.id, scheme: 'root' }).toString(); break; // in single folder mode we use the path of the opened folder as key for workspace storage // the ctime is used as secondary workspace id to clean up stale UI state if necessary - case WorkspaceState.FOLDER: + case WorkbenchState.FOLDER: workspaceId = workspace.roots[0].toString(); secondaryWorkspaceId = workspace.ctime; break; @@ -173,7 +173,7 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // dirty files in the workspace. // We use basename() to produce a short identifier, we do not need the full path. We use a custom // scheme so that we can later distinguish these identifiers from the workspace one. - case WorkspaceState.EMPTY: + case WorkbenchState.EMPTY: if (configuration.backupPath) { workspaceId = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString(); } diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 6b08e83a33d..e188d34337d 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -63,7 +63,7 @@ import { ChoiceChannel } from 'vs/platform/message/common/messageIpc'; import { ISearchService } from 'vs/platform/search/common/search'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { CommandService } from 'vs/platform/commands/common/commandService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -202,7 +202,7 @@ export class WorkbenchShell { this.telemetryService.publicLog('workspaceLoad', { userAgent: navigator.userAgent, windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth }, - emptyWorkbench: this.contextService.getWorkspaceState() === WorkspaceState.EMPTY, + emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY, 'workbench.filesToOpen': filesToOpen && filesToOpen.length || void 0, 'workbench.filesToCreate': filesToCreate && filesToCreate.length || void 0, 'workbench.filesToDiff': filesToDiff && filesToDiff.length || void 0, diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 7dcdd449cae..40b88cbed2c 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -39,7 +39,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { Themable } from 'vs/workbench/common/theme'; import { ipcRenderer as ipc, webFrame } from 'electron'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; const TextInputActions: IAction[] = [ @@ -288,7 +288,7 @@ export class ElectronWindow extends Themable { const foldersToAdd = request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath)); // Workspace: just add to workspace config - if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { this.workspaceEditingService.addRoots(foldersToAdd).done(null, errors.onUnexpectedError); } @@ -297,7 +297,7 @@ export class ElectronWindow extends Themable { const workspaceFolders: URI[] = []; // Folder of workspace is the first of multi root workspace, so add it - if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { workspaceFolders.push(...this.contextService.getWorkspace().roots); } diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 95add84f478..c2a5865957f 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -41,7 +41,7 @@ import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickO import { getServices } from 'vs/platform/instantiation/common/extensions'; import { WorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { Position, Parts, IPartService, ILayoutOptions } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService'; import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; @@ -444,7 +444,7 @@ export class Workbench implements IPartService { } // Empty workbench - else if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && this.openUntitledFile()) { + else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) { if (this.editorPart.hasEditorsToRestore()) { return TPromise.as([]); // do not open any empty untitled file if we have editors to restore } @@ -635,7 +635,7 @@ export class Workbench implements IPartService { private initSettings(): void { // Sidebar visibility - this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenSettingKey, StorageScope.WORKSPACE, this.contextService.getWorkspaceState() === WorkspaceState.EMPTY); + this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenSettingKey, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY); // Panel part visibility const panelRegistry = Registry.as(PanelExtensions.Panels); @@ -830,7 +830,7 @@ export class Workbench implements IPartService { return promise.then(() => { // Remember in settings - const defaultHidden = this.contextService.getWorkspaceState() === WorkspaceState.EMPTY; + const defaultHidden = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; if (hidden !== defaultHidden) { this.storageService.store(Workbench.sidebarHiddenSettingKey, hidden ? 'true' : 'false', StorageScope.WORKSPACE); } else { @@ -1054,7 +1054,7 @@ export class Workbench implements IPartService { // Close when empty: check if we should close the window based on the setting // Overruled by: window has a workspace opened or this window is for extension development // or setting is disabled. Also enabled when running with --wait from the command line. - if (visibleEditors === 0 && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && !this.environmentService.isExtensionDevelopment) { + if (visibleEditors === 0 && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && !this.environmentService.isExtensionDevelopment) { const closeWhenEmpty = this.configurationService.lookup(Workbench.closeWhenEmptyConfigurationKey).value; if (closeWhenEmpty || this.environmentService.args.wait) { this.closeEmptyWindowScheduler.schedule(); diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index c806a37cc88..4b53aa781f5 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -11,7 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IFileService } from 'vs/platform/files/common/files'; import { IMessageService } from 'vs/platform/message/common/message'; import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState } @@ -98,7 +98,7 @@ export class ConfigureAction extends AbstractDebugAction { } public run(event?: any): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); return TPromise.as(null); } @@ -140,7 +140,7 @@ export class StartAction extends AbstractDebugAction { if (state === State.Initializing) { return false; } - if (this.contextService && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY && processes.length > 0) { + if (this.contextService && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && processes.length > 0) { return false; } if (processes.some(p => p.getName(false) === selectedName && (!launch || p.session.root.toString() === launch.workspaceUri.toString()))) { diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index 8061af7c180..a97e3d17f85 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -16,7 +16,7 @@ import { StartDebugActionItem } from 'vs/workbench/parts/debug/browser/debugActi import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -56,7 +56,7 @@ export class DebugViewlet extends PersistentViewsViewlet { public focus(): void { super.focus(); - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.views[0].focusBody(); } @@ -69,7 +69,7 @@ export class DebugViewlet extends PersistentViewsViewlet { if (!this.actions) { this.actions = []; this.actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL)); - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { this.actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL)); } this.actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL))); @@ -83,7 +83,7 @@ export class DebugViewlet extends PersistentViewsViewlet { } public getActionItem(action: IAction): IActionItem { - if (action.id === StartAction.ID && this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (action.id === StartAction.ID && this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action); return this.startDebugActionItem; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts index bb81a501985..336c9d2fe87 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugCommands.ts @@ -15,7 +15,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IListService } from 'vs/platform/list/browser/listService'; import { IMessageService } from 'vs/platform/message/common/message'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IDebugService, IConfig, IEnablement, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug'; import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; @@ -204,7 +204,7 @@ export function registerCommands(): void { primary: undefined, handler: (accessor, workspaceUri: string) => { const manager = accessor.get(IDebugService).getConfigurationManager(); - if (accessor.get(IWorkspaceContextService).getWorkspaceState() === WorkspaceState.EMPTY) { + if (accessor.get(IWorkspaceContextService).getWorkbenchState() === WorkbenchState.EMPTY) { accessor.get(IMessageService).show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration.")); return TPromise.as(null); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 375ea4757d5..6de54d487cc 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -26,7 +26,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, DEBUG_SCHEME, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug'; @@ -353,7 +353,7 @@ export class ConfigurationManager implements IConfigurationManager { } private initLaunches(): void { - this.launches = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; + this.launches = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 32c8022826d..953b094abc8 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -46,7 +46,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ILogEntry, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost'; import { IBroadcastService, IBroadcast } from 'vs/platform/broadcast/electron-browser/broadcastService'; @@ -365,7 +365,7 @@ export class DebugService implements debug.IDebugService { // 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905 const process = this.viewModel.focusedProcess; if (process && session && process.getId() === session.getId() && strings.equalsIgnoreCase(process.configuration.type, 'extensionhost') && this.sessionStates.get(session.getId()) === debug.State.Running && - process && this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && process.configuration.noDebug) { + process && this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && process.configuration.noDebug) { this.broadcastService.broadcast({ channel: EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, payload: [process.session.root.fsPath] @@ -759,7 +759,7 @@ export class DebugService implements debug.IDebugService { }); }); }, err => { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(severity.Error, nls.localize('noFolderWorkspaceDebugError', "The active file can not be debugged. Make sure it is saved on disk and that you have a debug extension installed for that file type.")); return undefined; } @@ -846,7 +846,7 @@ export class DebugService implements debug.IDebugService { this.panelService.openPanel(debug.REPL_ID, false).done(undefined, errors.onUnexpectedError); } - if (!this.viewModel.changedWorkbenchViewState && (this.partService.isVisible(Parts.SIDEBAR_PART) || this.contextService.getWorkspaceState() === WorkspaceState.EMPTY)) { + if (!this.viewModel.changedWorkbenchViewState && (this.partService.isVisible(Parts.SIDEBAR_PART) || this.contextService.getWorkbenchState() === WorkbenchState.EMPTY)) { // We only want to change the workbench view state on the first debug session #5738 and if the side bar is not hidden this.viewModel.changedWorkbenchViewState = true; this.viewletService.openViewlet(debug.VIEWLET_ID); @@ -866,7 +866,7 @@ export class DebugService implements debug.IDebugService { watchExpressionsCount: this.model.getWatchExpressions().length, extensionName: `${adapter.extensionDescription.publisher}.${adapter.extensionDescription.name}`, isBuiltin: adapter.extensionDescription.isBuiltin, - launchJsonExists: this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && !!this.configurationService.getConfiguration('launch', { resource: root }) + launchJsonExists: this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && !!this.configurationService.getConfiguration('launch', { resource: root }) }); }).then(() => process, (error: any) => { if (error instanceof Error && error.message === 'Canceled') { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index 682ee4afeab..31a521431e2 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -22,7 +22,7 @@ import { DefaultController, DefaultDragAndDrop, ClickBehavior } from 'vs/base/pa import { Constants } from 'vs/editor/common/core/uint'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService, IMenu, MenuId } from 'vs/platform/actions/common/actions'; import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem'; @@ -524,7 +524,7 @@ export class CallStackRenderer implements IRenderer { private renderProcess(process: debug.IProcess, data: IProcessTemplateData): void { data.process.title = nls.localize({ key: 'process', comment: ['Process is a noun'] }, "Process"); - data.name.textContent = process.getName(this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE); + data.name.textContent = process.getName(this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE); const stoppedThread = process.getAllThreads().filter(t => t.stopped).pop(); data.stateLabel.textContent = stoppedThread ? nls.localize('paused', "Paused") diff --git a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts index 0ecf32ed8b1..c4a2925e667 100644 --- a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts +++ b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts @@ -9,7 +9,7 @@ import { registerColor, contrastBorder } from 'vs/platform/theme/common/colorReg import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IPartService, Parts } from 'vs/workbench/services/part/common/partService'; import { IDebugService, State } from 'vs/workbench/parts/debug/common/debug'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_BACKGROUND, Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER, STATUS_BAR_BORDER } from 'vs/workbench/common/theme'; import { addClass, removeClass } from 'vs/base/browser/dom'; @@ -75,7 +75,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri // Not debugging if (!this.isDebugging()) { - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { return normalColor; } diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index 494475b52a5..b035130333e 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -26,7 +26,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Query } from 'vs/workbench/parts/extensions/common/extensionQuery'; import { IFileService } from 'vs/platform/files/common/files'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { IExtensionService, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import URI from 'vs/base/common/uri'; @@ -559,7 +559,7 @@ export class DisableForWorkspaceAction extends Action implements IExtensionActio private update(): void { this.enabled = false; - if (this.extension && this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.extension && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { this.enabled = this.extension.type !== LocalExtensionType.System && !this.extension.disabledGlobally && !this.extension.disabledForWorkspace; } } @@ -1093,7 +1093,7 @@ export class ShowWorkspaceRecommendedExtensionsAction extends Action { @IWorkspaceContextService contextService: IWorkspaceContextService, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, contextService.getWorkspaceState() !== WorkspaceState.EMPTY); + super(id, label, null, contextService.getWorkbenchState() !== WorkbenchState.EMPTY); } run(): TPromise { @@ -1251,7 +1251,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IMessageService private messageService: IMessageService ) { - super(id, label, null, contextService.getWorkspaceState() !== WorkspaceState.EMPTY); + super(id, label, null, contextService.getWorkbenchState() !== WorkbenchState.EMPTY); } public run(event: any): TPromise { @@ -1259,7 +1259,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { } private openExtensionsFile(): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(severity.Info, localize('ConfigureWorkspaceRecommendations.noWorkspace', 'Recommendations are only available on a workspace folder.')); return TPromise.as(undefined); } @@ -1363,7 +1363,7 @@ export class DisableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && !e.disabledForWorkspace && !e.disabledGlobally); + this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && !e.disabledForWorkspace && !e.disabledGlobally); } run(): TPromise { @@ -1426,7 +1426,7 @@ export class EnableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.id) && !e.disabledGlobally && e.disabledForWorkspace); + this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.id) && !e.disabledGlobally && e.disabledForWorkspace); } run(): TPromise { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index 267265b2d0f..cedea9bb663 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -19,7 +19,7 @@ import { IChoiceService, IMessageService } from 'vs/platform/message/common/mess import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions'; import Severity from 'vs/base/common/severity'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions'; @@ -72,7 +72,7 @@ export class ExtensionTipsService implements IExtensionTipsService { } getWorkspaceRecommendations(): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return TPromise.as([]); } return this.fileService.resolveContent(this.contextService.toResource(paths.join('.vscode', 'extensions.json'))).then(content => { //TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 7d0b6871d9b..192350635c5 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -34,7 +34,7 @@ import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenc import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IURLService } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import product from 'vs/platform/node/product'; interface IExtensionStateProvider { @@ -663,7 +663,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { } const globalElablement = this.extensionEnablementService.setEnablement(extension.id, enable, false); - if (enable && this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (enable && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { const workspaceEnablement = this.extensionEnablementService.setEnablement(extension.id, enable, true); return TPromise.join([globalElablement, workspaceEnablement]).then(values => values[0] || values[1]); } diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts index cb98a1f78bd..bbd3755b8be 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts @@ -13,7 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import product from 'vs/platform/node/product'; import { Themable, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND } from 'vs/workbench/common/theme'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; class TwitterFeedbackService implements IFeedbackService { @@ -70,7 +70,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { super.updateStyles(); if (this.dropdown) { - this.dropdown.label.style('background-color', this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); + this.dropdown.label.style('background-color', this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND)); } } diff --git a/src/vs/workbench/parts/files/browser/explorerViewlet.ts b/src/vs/workbench/parts/files/browser/explorerViewlet.ts index 14ca02586b6..40a8ad2b434 100644 --- a/src/vs/workbench/parts/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/parts/files/browser/explorerViewlet.ts @@ -22,7 +22,7 @@ import { OpenEditorsView } from 'vs/workbench/parts/files/browser/views/openEdit import { IStorageService } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -78,7 +78,7 @@ export class ExplorerViewlet extends PersistentViewsViewlet { viewDescriptors.push(this.createOpenEditorsViewDescriptor()); - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { viewDescriptors.push(this.createExplorerViewDescriptor()); } else { viewDescriptors.push(this.createEmptyViewDescriptor()); @@ -122,7 +122,7 @@ export class ExplorerViewlet extends PersistentViewsViewlet { } private onConfigurationUpdated(): void { - this.openEditorsVisibleContextKey.set(this.contextService.getWorkspaceState() === WorkspaceState.EMPTY || (this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0); + this.openEditorsVisibleContextKey.set(this.contextService.getWorkbenchState() === WorkbenchState.EMPTY || (this.configurationService.getConfiguration()).explorer.openEditors.visible !== 0); } protected createView(viewDescriptor: IViewDescriptor, initialSize: number, options: IViewletViewOptions): IView { diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index d642dd7adda..33672313a9d 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -32,7 +32,7 @@ import { FileStat, Model } from 'vs/workbench/parts/files/common/explorerModel'; import { IListService } from 'vs/platform/list/browser/listService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -778,7 +778,7 @@ export class ExplorerView extends CollapsibleView { // Subsequent refresh: Merge stat into our local model and refresh tree modelStats.forEach((modelStat, index) => FileStat.mergeLocalWithDisk(modelStat, this.model.roots[index])); - const input = this.contextService.getWorkspaceState() === WorkspaceState.FOLDER ? this.model.roots[0] : this.model; + const input = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? this.model.roots[0] : this.model; if (input === this.explorerViewer.getInput()) { return this.explorerViewer.refresh(); } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 1a1cc1665e8..02f40b0c980 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -35,7 +35,7 @@ import { FileStat, NewStatPlaceholder, Model } from 'vs/workbench/parts/files/co import { DragMouseEvent, IMouseEvent } from 'vs/base/browser/mouseEvent'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPartService } from 'vs/workbench/services/part/common/partService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -829,7 +829,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // All (target = model) if (target instanceof Model) { - return this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(false) : DRAG_OVER_REJECT; // can only drop folders to workspace + return this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(false) : DRAG_OVER_REJECT; // can only drop folders to workspace } // All (target = file/folder) @@ -838,7 +838,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(true) : DRAG_OVER_ACCEPT_BUBBLE_DOWN(true); } - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_UP_COPY : DRAG_OVER_ACCEPT_BUBBLE_UP; } } @@ -882,7 +882,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return void 0; // TODO@Ben multi root } - if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { return this.workspaceEditingService.addRoots(folders); } diff --git a/src/vs/workbench/parts/output/common/outputLinkProvider.ts b/src/vs/workbench/parts/output/common/outputLinkProvider.ts index 12c2c9d224d..6279ac099c1 100644 --- a/src/vs/workbench/parts/output/common/outputLinkProvider.ts +++ b/src/vs/workbench/parts/output/common/outputLinkProvider.ts @@ -10,7 +10,7 @@ import URI from 'vs/base/common/uri'; import { RunOnceScheduler, wireCancellationToken } from 'vs/base/common/async'; import { IModelService } from 'vs/editor/common/services/modelService'; import { LinkProviderRegistry, ILink } from 'vs/editor/common/modes'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { OUTPUT_MODE_ID } from 'vs/workbench/parts/output/common/output'; import { MonacoWebWorker, createWebWorker } from 'vs/editor/common/services/webWorker'; import { ICreateData, OutputLinkComputer } from 'vs/workbench/parts/output/common/outputLinkComputer'; @@ -43,7 +43,7 @@ export class OutputLinkProvider { private updateLinkProviderWorker(): void { // We have a workspace - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { // Register link provider unless done already if (!this.linkProviderRegistration) { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts index 8343d24ff77..8e13d25f3b8 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts @@ -11,7 +11,7 @@ import { Action } from 'vs/base/common/actions'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IQuickOpenService, IPickOpenEntry, IFilePickOpenEntry } from 'vs/platform/quickOpen/common/quickOpen'; import { IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; export class OpenGlobalSettingsAction extends Action { @@ -80,7 +80,7 @@ export class OpenWorkspaceSettingsAction extends Action { @IWorkspaceContextService private workspaceContextService: IWorkspaceContextService ) { super(id, label); - this.enabled = this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY; + this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY; } public run(event?: any): TPromise { @@ -101,7 +101,7 @@ export class OpenFolderSettingsAction extends Action { @IQuickOpenService private quickOpenService: IQuickOpenService ) { super(id, label); - this.enabled = this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE; + this.enabled = this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE; } public run(): TPromise { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index 4396f6183be..d0b1b0e5e16 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -56,7 +56,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -886,7 +886,7 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return true; } - if (this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { for (const root of this.workspaceContextService.getWorkspace().roots) { const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 85b89e72a96..142d611efc6 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -31,7 +31,7 @@ import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; export interface IPreferencesRenderer extends IDisposable { @@ -1064,7 +1064,7 @@ class WorkspaceConfigurationRenderer extends Disposable { } public render(): void { - if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, [])); const ranges: IRange[] = []; diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index fba7f931a69..75dfb54e9d3 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -16,7 +16,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; import { EditorInput } from 'vs/workbench/common/editor'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { Position as EditorPosition, IEditor } from 'vs/platform/editor/common/editor'; import { ICommonCodeEditor } from 'vs/editor/common/editorCommon'; @@ -179,7 +179,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return this.createEditableSettingsEditorModel(ConfigurationTarget.WORKSPACE, workspaceSettingsUri); } - if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { return this.createEditableSettingsEditorModel(ConfigurationTarget.FOLDER, uri); } @@ -191,7 +191,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } openWorkspaceSettings(): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings")); return TPromise.as(null); } @@ -299,7 +299,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private resolveSettingsContentFromWorkspaceConfiguration(): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { return this.textModelResolverService.createModelReference(this.contextService.getWorkspace().configuration) .then(reference => { const model = reference.object.textEditorModel; @@ -316,7 +316,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic case ConfigurationTarget.USER: return URI.file(this.environmentService.appSettingsPath); case ConfigurationTarget.WORKSPACE: - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return null; } const workspace = this.contextService.getWorkspace(); @@ -333,7 +333,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic } private createSettingsIfNotExists(target: ConfigurationTarget, resource: URI): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE && target === ConfigurationTarget.WORKSPACE) { + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && target === ConfigurationTarget.WORKSPACE) { if (!this.configurationService.keys().workspace.length) { return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { }); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 0b7e9166401..6c02f39fd6c 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -20,7 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ISettingsGroup, IPreferencesService, getSettingsTargetName } from 'vs/workbench/parts/preferences/common/preferences'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IAction, IActionRunner } from 'vs/base/common/actions'; import { attachInputBoxStyler, attachStylerCallback, attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -293,7 +293,7 @@ export class SettingsTargetsWidget extends Widget { private create(parent: HTMLElement): void { this.settingsTargetsContainer = DOM.append(parent, DOM.$('.settings-targets-widget')); - this.settingsTargetsContainer.style.width = this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE ? '200px' : '150px'; + this.settingsTargetsContainer.style.width = this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? '200px' : '150px'; const targetElement = DOM.append(this.settingsTargetsContainer, DOM.$('.settings-target')); this.targetLabel = DOM.append(targetElement, DOM.$('.settings-target-label')); @@ -337,7 +337,7 @@ export class SettingsTargetsWidget extends Widget { run: () => this.onTargetClicked(userSettingsResource) }); - if (this.workspaceContextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { const workspaceSettingsResource = this.preferencesService.workspaceSettingsResource; actions.push({ id: 'workspaceSettingsTarget', @@ -348,7 +348,7 @@ export class SettingsTargetsWidget extends Widget { }); } - if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { actions.push(new Separator()); actions.push(...this.workspaceContextService.getWorkspace().roots.map((root, index) => { return { diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index a907fbb8044..ba472378c0e 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -14,7 +14,7 @@ import { IWindowsService, IWindowService, IWindowsConfiguration } from 'vs/platf import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; interface IConfiguration extends IWindowsConfiguration { @@ -43,7 +43,7 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IWorkspaceContextService private contextService: IWorkspaceContextService, @IExtensionService private extensionService: IExtensionService ) { - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { const workspace = this.contextService.getWorkspace(); this.rootCount = workspace.roots.length; this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index 0796ebff2bd..09f7ea977af 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -28,7 +28,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IQueryOptions, ISearchService, ISearchStats, ISearchQuery } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IRange } from 'vs/editor/common/core/range'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/parts/search/common/search'; @@ -164,7 +164,7 @@ export class OpenFileHandler extends QuickOpenHandler { iconClass = 'file'; // only use a generic file icon if we are forced to use an icon and have no icon theme set otherwise } - const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; return this.searchService.search(this.queryBuilder.file(folderResources, query)).then((complete) => { const results: QuickOpenEntry[] = []; for (let i = 0; i < complete.results.length; i++) { @@ -199,7 +199,7 @@ export class OpenFileHandler extends QuickOpenHandler { useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; - const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; const query = this.queryBuilder.file(folderResources, options); return query; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index c9c756e9859..c1e493bb0b2 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -41,7 +41,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService, IConfirmation } from 'vs/platform/message/common/message'; import { IProgressService } from 'vs/platform/progress/common/progress'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -239,7 +239,7 @@ export class SearchViewlet extends Viewlet { }).getHTMLElement(); this.messages = builder.div({ 'class': 'messages' }).hide().clone(); - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.searchWithoutFolderMessage(this.clearMessage()); } @@ -468,7 +468,7 @@ export class SearchViewlet extends Viewlet { this.results = div; this.results.addClass('show-file-icons'); - let dataSource = new SearchDataSource(this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE); + let dataSource = new SearchDataSource(this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE); let renderer = this.instantiationService.createInstance(SearchRenderer, this.getActionRunner(), this); let dnd = new SimpleFileResourceDragAndDrop(obj => obj instanceof FileMatch ? obj.resource() : void 0); @@ -753,7 +753,7 @@ export class SearchViewlet extends Viewlet { public clearSearchResults(): void { this.viewModel.searchResult.clear(); this.showEmptyStage(); - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.searchWithoutFolderMessage(this.clearMessage()); } this.searchWidget.clear(); @@ -870,9 +870,9 @@ export class SearchViewlet extends Viewlet { public searchInFolder(resource: URI): void { let folderPath = null; - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && resource) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && resource) { const workspace = this.contextService.getWorkspace(); - if (this.contextService.getWorkspaceState() === WorkspaceState.FOLDER) { + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { // Show relative path from the root for single-root mode folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); if (folderPath && folderPath !== '.') { @@ -960,7 +960,7 @@ export class SearchViewlet extends Viewlet { excludePattern, includePattern }; - const folderResources = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; const onQueryValidationError = (err: Error) => { this.searchWidget.searchInput.showMessage({ content: err.message, type: MessageType.ERROR }); @@ -1123,7 +1123,7 @@ export class SearchViewlet extends Viewlet { }).on(dom.EventType.CLICK, (e: MouseEvent) => { dom.EventHelper.stop(e, false); - let editorPromise = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.preferencesService.openWorkspaceSettings() : this.preferencesService.openGlobalSettings(); + let editorPromise = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.preferencesService.openWorkspaceSettings() : this.preferencesService.openGlobalSettings(); editorPromise.done(editor => { if (editor instanceof PreferencesEditor) { editor.focusSearch('.exclude'); @@ -1148,7 +1148,7 @@ export class SearchViewlet extends Viewlet { }); } - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.searchWithoutFolderMessage(div); } } else { diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 4aebdf42718..9acbb706f52 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -12,7 +12,7 @@ import * as glob from 'vs/base/common/glob'; import * as paths from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; import uri from 'vs/base/common/uri'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IPatternInfo, IQueryOptions, IFolderQuery, ISearchQuery, QueryType, ISearchConfiguration, getExcludes, pathIncludedInQuery } from 'vs/platform/search/common/search'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -184,7 +184,7 @@ export class QueryBuilder { * Split search paths (./ or absolute paths in the includePatterns) into absolute paths and globs applied to those paths */ private expandSearchPathPatterns(searchPaths: string[]): ISearchPathPattern[] { - if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.EMPTY || !searchPaths || !searchPaths.length) { + if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.EMPTY || !searchPaths || !searchPaths.length) { // No workspace => ignore search paths return []; } @@ -212,7 +212,7 @@ export class QueryBuilder { return [paths.normalize(searchPath)]; } - if (this.workspaceContextService.getWorkspaceState() === WorkspaceState.FOLDER) { // TODO: @Sandy Try checking workspace folders length instead. + if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.FOLDER) { // TODO: @Sandy Try checking workspace folders length instead. return [paths.normalize( paths.join(this.workspaceContextService.getWorkspace().roots[0].fsPath, searchPath))]; } else if (searchPath === './') { diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 374d057cf16..001b0ed44c1 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -67,7 +67,7 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IConfigurationEditingService, ConfigurationTarget, IConfigurationValue } from 'vs/workbench/services/configuration/common/configurationEditing'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IOutputService, IOutputChannelRegistry, Extensions as OutputExt, IOutputChannel } from 'vs/workbench/parts/output/common/output'; @@ -113,7 +113,7 @@ abstract class OpenTaskConfigurationAction extends Action { } public run(event?: any): TPromise { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('ConfigureTaskRunnerAction.noWorkspace', 'Tasks are only available on a workspace folder.')); return TPromise.as(undefined); } @@ -308,7 +308,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { super.updateStyles(); this.icons.forEach(icon => { - icon.style.backgroundColor = this.getColor(this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND); + icon.style.backgroundColor = this.getColor(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? STATUS_BAR_FOREGROUND : STATUS_BAR_NO_FOLDER_FOREGROUND); }); } @@ -1547,7 +1547,7 @@ class TaskService extends EventEmitter implements ITaskService { } private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; + let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; if (!result) { return { config: undefined, hasParseErrors: false }; } @@ -1589,7 +1589,7 @@ class TaskService extends EventEmitter implements ITaskService { } private hasDetectorSupport(config: TaskConfig.ExternalTaskRunnerConfiguration): boolean { - if (!config.command || this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (!config.command || this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return false; } return ProcessRunnerDetector.supports(config.command); @@ -1700,7 +1700,7 @@ class TaskService extends EventEmitter implements ITaskService { } private canRunCommand(): boolean { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.messageService.show(Severity.Info, nls.localize('TaskService.noWorkspace', 'Tasks are only available on a workspace folder.')); return false; } diff --git a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts index abb98943900..931567edb21 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts @@ -18,7 +18,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import * as Tasks from '../common/tasks'; import * as TaskConfig from './taskConfiguration'; @@ -156,7 +156,7 @@ export class ProcessRunnerDetector { this.taskConfiguration = config; this._stderr = []; this._stdout = []; - this._cwd = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; + this._cwd = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; } public get stderr(): string[] { diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 1ab7fbaf6c7..96585270fa8 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -14,7 +14,7 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -147,7 +147,7 @@ export class WatermarkContribution implements IWorkbenchContribution { .div({ 'class': 'watermark' }); const box = $(this.watermark) .div({ 'class': 'watermark-box' }); - const folder = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY; + const folder = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; const selected = folder ? folderEntries : noFolderEntries .filter(entry => !('mac' in entry) || entry.mac === isMacintosh); const update = () => { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index d3c6251f960..599deb6e35c 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -18,7 +18,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { readFile, stat } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import * as extfs from 'vs/base/node/extfs'; -import { IWorkspaceContextService, IWorkspace, Workspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace, Workspace, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files'; import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; @@ -198,14 +198,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return this.workspace; } - public getWorkspaceState(): WorkspaceState { + public getWorkbenchState(): WorkbenchState { if (this.workspace) { if (this.workspace.configuration) { - return WorkspaceState.WORKSPACE; + return WorkbenchState.WORKSPACE; } - return WorkspaceState.FOLDER; + return WorkbenchState.FOLDER; } - return WorkspaceState.EMPTY; + return WorkbenchState.EMPTY; } public getRoot(resource: URI): URI { @@ -371,7 +371,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } public getUnsupportedWorkspaceKeys(): string[] { - return this.getWorkspaceState() === WorkspaceState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).workspaceSettingsConfig.unsupportedKeys : []; + return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).workspaceSettingsConfig.unsupportedKeys : []; } public initialize(trigger: boolean = true): TPromise { @@ -534,7 +534,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { private initCachesForFolders(folders: URI[]): void { for (const folder of folders) { - this.cachedFolderConfigs.set(folder, this._register(new FolderConfiguration(folder, this.workspaceSettingsRootFolder, this.getWorkspaceState() === WorkspaceState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW))); + this.cachedFolderConfigs.set(folder, this._register(new FolderConfiguration(folder, this.workspaceSettingsRootFolder, this.getWorkbenchState() === WorkbenchState.WORKSPACE ? ConfigurationScope.RESOURCE : ConfigurationScope.WINDOW))); this.updateFolderConfiguration(folder, new FolderConfigurationModel(new FolderSettingsModel(null), [], ConfigurationScope.RESOURCE), false); } } @@ -603,7 +603,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { private updateFolderConfiguration(folder: URI, folderConfiguration: FolderConfigurationModel, compare: boolean): boolean { let configurationChanged = this._configuration.updateFolderConfiguration(folder, folderConfiguration, compare); - if (this.getWorkspaceState() === WorkspaceState.FOLDER) { + if (this.getWorkbenchState() === WorkbenchState.FOLDER) { // Workspace configuration changed configurationChanged = this.updateWorkspaceConfiguration(compare) || configurationChanged; } @@ -611,7 +611,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } private updateWorkspaceConfiguration(compare: boolean): boolean { - const workspaceConfiguration = this.getWorkspaceState() === WorkspaceState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.roots[0]); + const workspaceConfiguration = this.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.roots[0]); return this._configuration.updateWorkspaceConfiguration(workspaceConfiguration, compare); } diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 40e491de3f5..3e974c0487f 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -21,7 +21,7 @@ import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Registry } from 'vs/platform/registry/common/platform'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IConfigurationService, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration'; @@ -252,7 +252,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } // Target cannot be workspace or folder if no workspace opened - if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.FOLDER) && this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if ((target === ConfigurationTarget.WORKSPACE || target === ConfigurationTarget.FOLDER) && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return this.wrapError(ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED, target, operation); } @@ -328,7 +328,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { const workspace = this.contextService.getWorkspace(); @@ -336,7 +336,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService return workspace.configuration || this.toResource(relativePath, workspace.roots[0]); } - if (target === ConfigurationTarget.FOLDER && this.contextService.getWorkspaceState() === WorkspaceState.WORKSPACE) { + if (target === ConfigurationTarget.FOLDER && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { if (resource) { const root = this.contextService.getRoot(resource); if (root) { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 3e70add7ef3..cee692ce0e6 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -16,7 +16,7 @@ import { findFreePort } from 'vs/base/node/ports'; import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { ILifecycleService, ShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ChildProcess, fork } from 'child_process'; import { ipcRenderer as ipc } from 'electron'; @@ -356,7 +356,7 @@ export class ExtensionHostProcessWorker { enableProposedApiForAll: !this._environmentService.isBuilt || (!!this._environmentService.extensionDevelopmentPath && product.nameLong.indexOf('Insiders') >= 0), enableProposedApiFor: this._environmentService.args['enable-proposed-api'] || [] }, - workspace: this._contextService.getWorkspaceState() === WorkspaceState.EMPTY ? null : this._contextService.getWorkspace(), + workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace(), extensions: extensionDescriptions, configuration: this._configurationService.getConfigurationData(), telemetryInfo diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index bf6175f9cd0..d5ce241b833 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -15,7 +15,7 @@ import { toResource } from 'vs/workbench/common/editor'; import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Action } from 'vs/base/common/actions'; import { ResourceMap } from 'vs/base/common/map'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -146,7 +146,7 @@ export class FileService implements IFileService { private getEncodingOverrides(): IEncodingOverride[] { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { this.contextService.getWorkspace().roots.forEach(root => { encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); }); diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index 6f86a23260f..a22c3d618cb 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -25,7 +25,7 @@ import uri from 'vs/base/common/uri'; import nls = require('vs/nls'); import { isWindows, isLinux } from 'vs/base/common/platform'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import pfs = require('vs/base/node/pfs'); import encoding = require('vs/base/node/encoding'); @@ -101,7 +101,7 @@ export class FileService implements IFileService { this.toDispose = []; this.options = options || Object.create(null); this.tmpPath = this.options.tmpDir || os.tmpdir(); - this.currentWorkspaceRootsCount = contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? contextService.getWorkspace().roots.length : 0; + this.currentWorkspaceRootsCount = contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? contextService.getWorkspace().roots.length : 0; this._onFileChanges = new Emitter(); this.toDispose.push(this._onFileChanges); @@ -129,7 +129,7 @@ export class FileService implements IFileService { } private onDidChangeWorkspaceRoots(): void { - const newRootCount = this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY ? this.contextService.getWorkspace().roots.length : 0; + const newRootCount = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.length : 0; let restartWorkspaceWatcher = false; if (this.currentWorkspaceRootsCount <= 1 && newRootCount > 1) { diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 7620195f439..9cb7d80137c 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -15,7 +15,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { FileChangesEvent, IFileService, FileChangeType } from 'vs/platform/files/common/files'; import { Selection } from 'vs/editor/common/core/selection'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; @@ -769,7 +769,7 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic } public getLastActiveWorkspaceRoot(): URI { - if (this.contextService.getWorkspaceState() === WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { return void 0; } diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index 4bf2393d0b6..6c2386e8b25 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -11,7 +11,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import URI from 'vs/base/common/uri'; import { IFileService, IFileStat } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; @@ -152,7 +152,7 @@ export class WorkspaceStats { tags['workbench.filesToCreate'] = filesToCreate && filesToCreate.length || undefined; tags['workbench.filesToDiff'] = filesToDiff && filesToDiff.length || undefined; - const isEmpty = this.contextService.getWorkspaceState() === WorkspaceState.EMPTY; + const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; const workspace = this.contextService.getWorkspace(); tags['workspace.roots'] = isEmpty ? 0 : workspace.roots.length; tags['workspace.empty'] = isEmpty; diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 652d5b870b3..e172715a3d6 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -19,7 +19,7 @@ import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); import { IMode } from 'vs/editor/common/modes'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; @@ -745,7 +745,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for workspace settings file - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { return this.contextService.getWorkspace().roots.some(root => { return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); }); diff --git a/src/vs/workbench/services/textfile/common/textFileService.ts b/src/vs/workbench/services/textfile/common/textFileService.ts index efca3d0de47..33f5ee1e9d1 100644 --- a/src/vs/workbench/services/textfile/common/textFileService.ts +++ b/src/vs/workbench/services/textfile/common/textFileService.ts @@ -17,7 +17,7 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IRevertOptions, IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ConfirmResult } from 'vs/workbench/common/editor'; import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IFileService, IResolveContentOptions, IFilesConfiguration, FileOperationError, FileOperationResult, AutoSaveConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -180,7 +180,7 @@ export abstract class TextFileService implements ITextFileService { let doBackup: boolean; switch (reason) { case ShutdownReason.CLOSE: - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { doBackup = true; // backup if a folder is open and onExitAndWindowClose is configured } else if (windowCount > 1 || platform.isMacintosh) { doBackup = false; // do not backup if a window is closed that does not cause quitting of the application @@ -198,7 +198,7 @@ export abstract class TextFileService implements ITextFileService { break; case ShutdownReason.LOAD: - if (this.contextService.getWorkspaceState() !== WorkspaceState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.configuredHotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) { doBackup = true; // backup if a folder is open and onExitAndWindowClose is configured } else { doBackup = false; // do not backup because we are switching contexts diff --git a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts index 0ad6a488fae..5fc35fecbd8 100644 --- a/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceMigrationService.ts @@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import URI from 'vs/base/common/uri'; import { once } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -62,7 +62,7 @@ export class WorkspaceMigrationService implements IWorkspaceMigrationService { } private migrateConfiguration(toWorkspaceId: IWorkspaceIdentifier): TPromise { - if (this.contextService.getWorkspaceState() !== WorkspaceState.FOLDER) { + if (this.contextService.getWorkbenchState() !== WorkbenchState.FOLDER) { return TPromise.as(void 0); // return early if not a folder workspace is opened } diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts index 95d7f71552a..425dd180872 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadConfiguration.test.ts @@ -10,7 +10,7 @@ import * as sinon from 'sinon'; import URI from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { MainThreadConfiguration } from 'vs/workbench/api/electron-browser/mainThreadConfiguration'; import { ConfigurationTarget, IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing'; @@ -56,7 +56,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); @@ -65,7 +65,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); @@ -74,7 +74,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null); @@ -83,7 +83,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); @@ -92,7 +92,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -101,7 +101,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -110,7 +110,7 @@ suite('ExtHostConfiguration', function () { }); test('update window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null); @@ -119,7 +119,7 @@ suite('ExtHostConfiguration', function () { }); test('update resource configuration without configuration target defaults to folder', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc')); @@ -128,7 +128,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with user configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.USER, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -137,7 +137,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with workspace configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -146,7 +146,7 @@ suite('ExtHostConfiguration', function () { }); test('update configuration with folder configuration target', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$updateConfigurationOption(ConfigurationTarget.FOLDER, 'extHostConfiguration.window', 'value', URI.file('abc')); @@ -155,7 +155,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); @@ -164,7 +164,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); @@ -173,7 +173,7 @@ suite('ExtHostConfiguration', function () { }); test('remove resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null); @@ -182,7 +182,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); @@ -191,7 +191,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); @@ -200,7 +200,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc')); @@ -209,7 +209,7 @@ suite('ExtHostConfiguration', function () { }); test('remove window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.FOLDER }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.FOLDER }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null); @@ -218,7 +218,7 @@ suite('ExtHostConfiguration', function () { }); test('remove configuration without configuration target defaults to folder', function () { - instantiationService.stub(IWorkspaceContextService, { getWorkspaceState: () => WorkspaceState.WORKSPACE }); + instantiationService.stub(IWorkspaceContextService, { getWorkbenchState: () => WorkbenchState.WORKSPACE }); const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, OneGetThreadService(null)); testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc')); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 082b2c10d57..18c26611255 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -27,7 +27,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { IEditorInput, IEditorOptions, Position, Direction, IEditor, IResourceInput, ITextEditorSelection } 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 { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace, WorkspaceState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService, IWorkspace as IWorkbenchWorkspace, WorkbenchState } 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'; @@ -94,14 +94,14 @@ export class TestContextService implements IWorkspaceContextService { return this.workspace ? this.workspace.roots : []; } - public getWorkspaceState(): WorkspaceState { + public getWorkbenchState(): WorkbenchState { if (this.workspace) { if (this.workspace.configuration) { - return WorkspaceState.WORKSPACE; + return WorkbenchState.WORKSPACE; } - return WorkspaceState.FOLDER; + return WorkbenchState.FOLDER; } - return WorkspaceState.EMPTY; + return WorkbenchState.EMPTY; } public getWorkspace(): IWorkbenchWorkspace { From 4608d968dcba53c8316d6d9645b29866eff64375 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 13 Sep 2017 11:14:37 +0200 Subject: [PATCH 044/145] [loc query] Typo in source string. Fixes #34266 --- src/vs/platform/theme/common/colorExtensionPoint.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/theme/common/colorExtensionPoint.ts b/src/vs/platform/theme/common/colorExtensionPoint.ts index f42ffb926a3..51a47fdb4bb 100644 --- a/src/vs/platform/theme/common/colorExtensionPoint.ts +++ b/src/vs/platform/theme/common/colorExtensionPoint.ts @@ -93,7 +93,7 @@ export class ColorExtensionPoint { extensionValue.forEach(extension => { if (typeof extension.id !== 'string' || extension.id.length === 0) { - collector.error(nls.localize('invalid.id', "'configuration.colors.id' must be defined an can not be empty")); + collector.error(nls.localize('invalid.id', "'configuration.colors.id' must be defined and can not be empty")); return; } if (!extension.id.match(colorIdPattern)) { @@ -101,7 +101,7 @@ export class ColorExtensionPoint { return; } if (typeof extension.description !== 'string' || extension.id.length === 0) { - collector.error(nls.localize('invalid.description', "'configuration.colors.description' must be defined an can not be empty")); + collector.error(nls.localize('invalid.description', "'configuration.colors.description' must be defined and can not be empty")); return; } let defaults = extension.defaults; From 6b16f46c8302715365283fb815b95b7c4a2d0fc4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 13 Sep 2017 11:28:54 +0200 Subject: [PATCH 045/145] :lipstick: --- src/vs/code/electron-main/keyboard.ts | 5 +++++ src/vs/platform/configuration/node/configurationService.ts | 4 ++-- .../workbench/services/configuration/node/configuration.ts | 4 ++-- .../keybinding/electron-browser/keybindingService.ts | 3 +-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/vs/code/electron-main/keyboard.ts b/src/vs/code/electron-main/keyboard.ts index 73c3289adf6..3b19f2fea15 100644 --- a/src/vs/code/electron-main/keyboard.ts +++ b/src/vs/code/electron-main/keyboard.ts @@ -174,4 +174,9 @@ export class KeybindingsResolver { return this.keybindings[commandId]; } + + public dispose(): void { + this._onKeybindingsChanged.dispose(); + this.keybindingsWatcher.dispose(); + } } \ No newline at end of file diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 2eff5bb204f..8f6005c6430 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, ConfigurationModel, IConfigurationOverrides, Configuration, IConfigurationValues, IConfigurationData } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; import Event, { Emitter } from 'vs/base/common/event'; @@ -37,7 +37,7 @@ export class ConfigurationService extends Disposable implements IConfiguratio return userConfigModel; } }); - this._register(toDisposable(() => this.userConfigModelWatcher.dispose())); + this._register(this.userConfigModelWatcher); // Listeners this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User))); diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 0f45a64cd69..53de4e182aa 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -13,7 +13,7 @@ import { equals, coalesce } from 'vs/base/common/arrays'; import * as objects from 'vs/base/common/objects'; import * as errors from 'vs/base/common/errors'; import * as collections from 'vs/base/common/collections'; -import { Disposable, toDisposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; import { readFile, stat } from 'vs/base/node/pfs'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; @@ -631,7 +631,7 @@ class WorkspaceConfiguration extends Disposable { return workspaceConfigurationModel; }, initCallback: () => c(null) }); - this._workspaceConfigurationWatcherDisposables.push(toDisposable(() => this._workspaceConfigurationWatcher.dispose())); + this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); }); } diff --git a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts index e374bd0a2a3..4d7dfa3e616 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts @@ -8,7 +8,6 @@ import * as nls from 'vs/nls'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { ResolvedKeybinding, Keybinding } from 'vs/base/common/keyCodes'; import { OS, OperatingSystem } from 'vs/base/common/platform'; -import { toDisposable } from 'vs/base/common/lifecycle'; import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService'; @@ -296,7 +295,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { this._firstTimeComputingResolver = true; this.userKeybindings = new ConfigWatcher(environmentService.appKeybindingsPath, { defaultConfig: [], onError: error => onUnexpectedError(error) }); - this.toDispose.push(toDisposable(() => this.userKeybindings.dispose())); + this.toDispose.push(this.userKeybindings); keybindingsExtPoint.setHandler((extensions) => { let commandAdded = false; From d45c0ca64ef5030b1332ce9f07c4b40cf251985c Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 11:32:38 +0200 Subject: [PATCH 046/145] debug: do not colorize in repl based on heuristics fixes #34043 --- .../debug/electron-browser/debugHover.ts | 3 ++- .../debug/electron-browser/debugViewer.ts | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts index 3af92756683..9dec498f49a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugHover.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugHover.ts @@ -254,7 +254,8 @@ export class DebugHoverWidget implements IContentWidget { this.valueContainer.hidden = false; renderExpressionValue(expression, this.valueContainer, { showChanged: false, - preserveWhitespace: true + preserveWhitespace: true, + colorize: true }); this.valueContainer.title = ''; this.editor.layoutContentWidget(this); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index f069333aeea..b986c6cfe43 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -48,6 +48,7 @@ export interface IRenderValueOptions { showChanged?: boolean; maxValueLength?: number; showHover?: boolean; + colorize?: boolean; } function replaceWhitespace(value: string): string { @@ -66,12 +67,16 @@ export function renderExpressionValue(expressionOrValue: debug.IExpression | str if (value !== Expression.DEFAULT_VALUE) { dom.addClass(container, 'error'); } - } else if (!isNaN(+value)) { - dom.addClass(container, 'number'); - } else if (booleanRegex.test(value)) { - dom.addClass(container, 'boolean'); - } else if (stringRegex.test(value)) { - dom.addClass(container, 'string'); + } + + if (options.colorize) { + if (!isNaN(+value)) { + dom.addClass(container, 'number'); + } else if (booleanRegex.test(value)) { + dom.addClass(container, 'boolean'); + } else if (stringRegex.test(value)) { + dom.addClass(container, 'string'); + } } if (options.showChanged && (expressionOrValue).valueChanged && value !== Expression.DEFAULT_VALUE) { @@ -104,7 +109,8 @@ export function renderVariable(tree: ITree, variable: Variable, data: IVariableT showChanged, maxValueLength: MAX_VALUE_RENDER_LENGTH_IN_VIEWLET, preserveWhitespace: false, - showHover: true + showHover: true, + colorize: true }); } else { data.value.textContent = ''; @@ -944,7 +950,8 @@ export class WatchExpressionsRenderer implements IRenderer { showChanged: true, maxValueLength: MAX_VALUE_RENDER_LENGTH_IN_VIEWLET, preserveWhitespace: false, - showHover: true + showHover: true, + colorize: true }); data.name.title = watchExpression.type ? watchExpression.type : watchExpression.value; } From aa6936c1623b7bd55617182b585dfeb6f118fd84 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 12:22:41 +0200 Subject: [PATCH 047/145] fix smoke test for debug console --- test/smoke/src/areas/debug/debug.test.ts | 2 +- test/smoke/src/areas/debug/debug.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 47c46599cad..7c039187c9d 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -115,7 +115,7 @@ describe('Debug', () => { }); it('debug console', async function () { - const result = await app.workbench.debug.console('2 + 2 \n', 'number'); + const result = await app.workbench.debug.console('2 + 2 \n'); assert.equal(result, '4'); }); diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index 6a515e67346..0e3702de5eb 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -24,7 +24,7 @@ const TOOLBAR_HIDDEN = `.debug-actions-widget.builder-hidden`; const STACK_FRAME = `${VIEWLET} .monaco-tree-row .stack-frame`; const VARIABLE = `${VIEWLET} .debug-variables .monaco-tree-row .expression`; const CONSOLE_OUTPUT = `.repl .output.expression`; -const CONSOLE_INPUT_OUTPUT = `.repl .input-output-pair .output.expression`; +const CONSOLE_INPUT_OUTPUT = `.repl .input-output-pair .output.expression .value`; const SCOPE = `${VIEWLET} .debug-variables .scope`; const REPL_FOCUSED = '.repl-input-wrapper .monaco-editor.focused'; @@ -103,11 +103,11 @@ export class Debug extends Viewlet { await this.spectron.workbench.waitForOpen(name); } - async console(text: string, type: string): Promise { + async console(text: string): Promise { await this.spectron.workbench.quickopen.runCommand('Debug: Focus Debug Console'); await this.spectron.client.waitForElement(REPL_FOCUSED); await this.spectron.client.type(text); - await this.spectron.client.waitForElement(CONSOLE_INPUT_OUTPUT + ` .${type}`); + await this.spectron.client.waitForElement(CONSOLE_INPUT_OUTPUT); const result = await this.getConsoleOutput(); return result[result.length - 1] || ''; From 46c8ce6df5248fa206ac123bf83578dc355696ee Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 13 Sep 2017 12:38:21 +0200 Subject: [PATCH 048/145] configuration contribution point: support for array of settings sections, deprecate the 'allOf' trick used in CSS. --- extensions/css/package.json | 1355 ++++++++--------- extensions/css/package.nls.json | 3 + .../configuration/node/configuration.ts | 45 +- 3 files changed, 702 insertions(+), 701 deletions(-) diff --git a/extensions/css/package.json b/extensions/css/package.json index 6ace6ad649a..1f7e0681b1e 100644 --- a/extensions/css/package.json +++ b/extensions/css/package.json @@ -50,694 +50,677 @@ "path": "./snippets/css.json" } ], - "configuration": { - "order": 20, - "allOf": [ - { - "id": "css", - "title": "CSS", - "allOf": [ - { - "title": "%css.validate.title%", - "properties": { - "css.validate": { - "type": "boolean", - "scope": "resource", - "default": true, - "description": "%css.validate.desc%" - }, - "css.colorDecorators.enable": { - "type": "boolean", - "scope": "window", - "default": true, - "description": "%css.colorDecorators.enable.desc%", - "deprecationMessage": "%css.colorDecorators.enable.deprecationMessage%" - }, - "css.lint.compatibleVendorPrefixes": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.compatibleVendorPrefixes.desc%" - }, - "css.lint.vendorPrefix": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%css.lint.vendorPrefix.desc%" - }, - "css.lint.duplicateProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.duplicateProperties.desc%" - }, - "css.lint.emptyRules": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%css.lint.emptyRules.desc%" - }, - "css.lint.importStatement": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.importStatement.desc%" - }, - "css.lint.boxModel": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.boxModel.desc%" - }, - "css.lint.universalSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.universalSelector.desc%" - }, - "css.lint.zeroUnits": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.zeroUnits.desc%" - }, - "css.lint.fontFaceProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%css.lint.fontFaceProperties.desc%" - }, - "css.lint.hexColorLength": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%css.lint.hexColorLength.desc%" - }, - "css.lint.argumentsInColorFunction": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%css.lint.argumentsInColorFunction.desc%" - }, - "css.lint.unknownProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%css.lint.unknownProperties.desc%" - }, - "css.lint.ieHack": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.ieHack.desc%" - }, - "css.lint.unknownVendorSpecificProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.unknownVendorSpecificProperties.desc%" - }, - "css.lint.propertyIgnoredDueToDisplay": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%css.lint.propertyIgnoredDueToDisplay.desc%" - }, - "css.lint.important": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.important.desc%" - }, - "css.lint.float": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.float.desc%" - }, - "css.lint.idSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%css.lint.idSelector.desc%" - }, - "css.trace.server": { - "type": "string", - "scope": "window", - "enum": [ - "off", - "messages", - "verbose" - ], - "default": "off", - "description": "%css.trace.server.desc%" - } - } - } - ] - }, - { - "id": "scss", - "order": 24, - "title": "SCSS (Sass)", - "allOf": [ - { - "title": "%scss.validate.title%", - "properties": { - "scss.validate": { - "type": "boolean", - "scope": "resource", - "default": true, - "description": "%scss.validate.desc%" - }, - "scss.colorDecorators.enable": { - "type": "boolean", - "scope": "window", - "default": true, - "description": "%scss.colorDecorators.enable.desc%", - "deprecationMessage": "%scss.colorDecorators.enable.deprecationMessage%" - }, - "scss.lint.compatibleVendorPrefixes": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.compatibleVendorPrefixes.desc%" - }, - "scss.lint.vendorPrefix": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%scss.lint.vendorPrefix.desc%" - }, - "scss.lint.duplicateProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.duplicateProperties.desc%" - }, - "scss.lint.emptyRules": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%scss.lint.emptyRules.desc%" - }, - "scss.lint.importStatement": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.importStatement.desc%" - }, - "scss.lint.boxModel": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.boxModel.desc%" - }, - "scss.lint.universalSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.universalSelector.desc%" - }, - "scss.lint.zeroUnits": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.zeroUnits.desc%" - }, - "scss.lint.fontFaceProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%scss.lint.fontFaceProperties.desc%" - }, - "scss.lint.hexColorLength": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%scss.lint.hexColorLength.desc%" - }, - "scss.lint.argumentsInColorFunction": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%scss.lint.argumentsInColorFunction.desc%" - }, - "scss.lint.unknownProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%scss.lint.unknownProperties.desc%" - }, - "scss.lint.ieHack": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.ieHack.desc%" - }, - "scss.lint.unknownVendorSpecificProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.unknownVendorSpecificProperties.desc%" - }, - "scss.lint.propertyIgnoredDueToDisplay": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%scss.lint.propertyIgnoredDueToDisplay.desc%" - }, - "scss.lint.important": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.important.desc%" - }, - "scss.lint.float": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.float.desc%" - }, - "scss.lint.idSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%scss.lint.idSelector.desc%" - } - } - } - ] - }, - { - "id": "less", - "order": 22, - "type": "object", - "title": "LESS", - "allOf": [ - { - "title": "%less.validate.title%", - "properties": { - "less.validate": { - "type": "boolean", - "scope": "resource", - "default": true, - "description": "%less.validate.desc%" - }, - "less.colorDecorators.enable": { - "type": "boolean", - "scope": "window", - "default": true, - "description": "%less.colorDecorators.enable.desc%", - "deprecationMessage": "%less.colorDecorators.enable.deprecationMessage%" - }, - "less.lint.compatibleVendorPrefixes": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.compatibleVendorPrefixes.desc%" - }, - "less.lint.vendorPrefix": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%less.lint.vendorPrefix.desc%" - }, - "less.lint.duplicateProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.duplicateProperties.desc%" - }, - "less.lint.emptyRules": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%less.lint.emptyRules.desc%" - }, - "less.lint.importStatement": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.importStatement.desc%" - }, - "less.lint.boxModel": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.boxModel.desc%" - }, - "less.lint.universalSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.universalSelector.desc%" - }, - "less.lint.zeroUnits": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.zeroUnits.desc%" - }, - "less.lint.fontFaceProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%less.lint.fontFaceProperties.desc%" - }, - "less.lint.hexColorLength": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%less.lint.hexColorLength.desc%" - }, - "less.lint.argumentsInColorFunction": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "error", - "description": "%less.lint.argumentsInColorFunction.desc%" - }, - "less.lint.unknownProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%less.lint.unknownProperties.desc%" - }, - "less.lint.ieHack": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.ieHack.desc%" - }, - "less.lint.unknownVendorSpecificProperties": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.unknownVendorSpecificProperties.desc%" - }, - "less.lint.propertyIgnoredDueToDisplay": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "warning", - "description": "%less.lint.propertyIgnoredDueToDisplay.desc%" - }, - "less.lint.important": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.important.desc%" - }, - "less.lint.float": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.float.desc%" - }, - "less.lint.idSelector": { - "type": "string", - "scope": "resource", - "enum": [ - "ignore", - "warning", - "error" - ], - "default": "ignore", - "description": "%less.lint.idSelector.desc%" - } - } - } - ] + "configuration": [ + { + "order": 22, + "id": "css", + "title": "%css.title%", + "properties": { + "css.validate": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%css.validate.desc%" + }, + "css.colorDecorators.enable": { + "type": "boolean", + "scope": "window", + "default": true, + "description": "%css.colorDecorators.enable.desc%", + "deprecationMessage": "%css.colorDecorators.enable.deprecationMessage%" + }, + "css.lint.compatibleVendorPrefixes": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.compatibleVendorPrefixes.desc%" + }, + "css.lint.vendorPrefix": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%css.lint.vendorPrefix.desc%" + }, + "css.lint.duplicateProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.duplicateProperties.desc%" + }, + "css.lint.emptyRules": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%css.lint.emptyRules.desc%" + }, + "css.lint.importStatement": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.importStatement.desc%" + }, + "css.lint.boxModel": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.boxModel.desc%" + }, + "css.lint.universalSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.universalSelector.desc%" + }, + "css.lint.zeroUnits": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.zeroUnits.desc%" + }, + "css.lint.fontFaceProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%css.lint.fontFaceProperties.desc%" + }, + "css.lint.hexColorLength": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%css.lint.hexColorLength.desc%" + }, + "css.lint.argumentsInColorFunction": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%css.lint.argumentsInColorFunction.desc%" + }, + "css.lint.unknownProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%css.lint.unknownProperties.desc%" + }, + "css.lint.ieHack": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.ieHack.desc%" + }, + "css.lint.unknownVendorSpecificProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.unknownVendorSpecificProperties.desc%" + }, + "css.lint.propertyIgnoredDueToDisplay": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%css.lint.propertyIgnoredDueToDisplay.desc%" + }, + "css.lint.important": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.important.desc%" + }, + "css.lint.float": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.float.desc%" + }, + "css.lint.idSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%css.lint.idSelector.desc%" + }, + "css.trace.server": { + "type": "string", + "scope": "window", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "%css.trace.server.desc%" + } } - ] - } + }, + { + "id": "scss", + "order": 24, + "title": "%scss.title%", + "properties": { + "scss.validate": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%scss.validate.desc%" + }, + "scss.colorDecorators.enable": { + "type": "boolean", + "scope": "window", + "default": true, + "description": "%scss.colorDecorators.enable.desc%", + "deprecationMessage": "%scss.colorDecorators.enable.deprecationMessage%" + }, + "scss.lint.compatibleVendorPrefixes": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.compatibleVendorPrefixes.desc%" + }, + "scss.lint.vendorPrefix": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%scss.lint.vendorPrefix.desc%" + }, + "scss.lint.duplicateProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.duplicateProperties.desc%" + }, + "scss.lint.emptyRules": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%scss.lint.emptyRules.desc%" + }, + "scss.lint.importStatement": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.importStatement.desc%" + }, + "scss.lint.boxModel": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.boxModel.desc%" + }, + "scss.lint.universalSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.universalSelector.desc%" + }, + "scss.lint.zeroUnits": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.zeroUnits.desc%" + }, + "scss.lint.fontFaceProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%scss.lint.fontFaceProperties.desc%" + }, + "scss.lint.hexColorLength": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%scss.lint.hexColorLength.desc%" + }, + "scss.lint.argumentsInColorFunction": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%scss.lint.argumentsInColorFunction.desc%" + }, + "scss.lint.unknownProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%scss.lint.unknownProperties.desc%" + }, + "scss.lint.ieHack": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.ieHack.desc%" + }, + "scss.lint.unknownVendorSpecificProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.unknownVendorSpecificProperties.desc%" + }, + "scss.lint.propertyIgnoredDueToDisplay": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%scss.lint.propertyIgnoredDueToDisplay.desc%" + }, + "scss.lint.important": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.important.desc%" + }, + "scss.lint.float": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.float.desc%" + }, + "scss.lint.idSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%scss.lint.idSelector.desc%" + } + } + }, + { + "id": "less", + "order": 23, + "type": "object", + "title": "%less.title%", + "properties": { + "less.validate": { + "type": "boolean", + "scope": "resource", + "default": true, + "description": "%less.validate.desc%" + }, + "less.colorDecorators.enable": { + "type": "boolean", + "scope": "window", + "default": true, + "description": "%less.colorDecorators.enable.desc%", + "deprecationMessage": "%less.colorDecorators.enable.deprecationMessage%" + }, + "less.lint.compatibleVendorPrefixes": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.compatibleVendorPrefixes.desc%" + }, + "less.lint.vendorPrefix": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%less.lint.vendorPrefix.desc%" + }, + "less.lint.duplicateProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.duplicateProperties.desc%" + }, + "less.lint.emptyRules": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%less.lint.emptyRules.desc%" + }, + "less.lint.importStatement": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.importStatement.desc%" + }, + "less.lint.boxModel": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.boxModel.desc%" + }, + "less.lint.universalSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.universalSelector.desc%" + }, + "less.lint.zeroUnits": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.zeroUnits.desc%" + }, + "less.lint.fontFaceProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%less.lint.fontFaceProperties.desc%" + }, + "less.lint.hexColorLength": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%less.lint.hexColorLength.desc%" + }, + "less.lint.argumentsInColorFunction": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "error", + "description": "%less.lint.argumentsInColorFunction.desc%" + }, + "less.lint.unknownProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%less.lint.unknownProperties.desc%" + }, + "less.lint.ieHack": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.ieHack.desc%" + }, + "less.lint.unknownVendorSpecificProperties": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.unknownVendorSpecificProperties.desc%" + }, + "less.lint.propertyIgnoredDueToDisplay": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "warning", + "description": "%less.lint.propertyIgnoredDueToDisplay.desc%" + }, + "less.lint.important": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.important.desc%" + }, + "less.lint.float": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.float.desc%" + }, + "less.lint.idSelector": { + "type": "string", + "scope": "resource", + "enum": [ + "ignore", + "warning", + "error" + ], + "default": "ignore", + "description": "%less.lint.idSelector.desc%" + } + } + } + ] }, "dependencies": { - "color-convert": "^0.5.3", + "color-convert": "^0.5.3", "vscode-languageclient": "3.4.0-next.17", "vscode-languageserver-protocol": "^3.1.1", "vscode-nls": "^2.0.2" @@ -745,4 +728,4 @@ "devDependencies": { "@types/node": "^6.0.51" } -} +} \ No newline at end of file diff --git a/extensions/css/package.nls.json b/extensions/css/package.nls.json index b2a7126c30d..33fbf6d5c28 100644 --- a/extensions/css/package.nls.json +++ b/extensions/css/package.nls.json @@ -1,4 +1,5 @@ { + "css.title": "CSS", "css.lint.argumentsInColorFunction.desc": "Invalid number of parameters", "css.lint.boxModel.desc": "Do not use width or height when using padding or border", "css.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties", @@ -20,6 +21,7 @@ "css.trace.server.desc": "Traces the communication between VS Code and the CSS language server.", "css.validate.title": "Controls CSS validation and problem severities.", "css.validate.desc": "Enables or disables all validations", + "less.title": "LESS", "less.lint.argumentsInColorFunction.desc": "Invalid number of parameters", "less.lint.boxModel.desc": "Do not use width or height when using padding or border", "less.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties", @@ -40,6 +42,7 @@ "less.lint.zeroUnits.desc": "No unit for zero needed", "less.validate.title": "Controls LESS validation and problem severities.", "less.validate.desc": "Enables or disables all validations", + "scss.title": "SCSS (Sass)", "scss.lint.argumentsInColorFunction.desc": "Invalid number of parameters", "scss.lint.boxModel.desc": "Do not use width or height when using padding or border", "scss.lint.compatibleVendorPrefixes.desc": "When using a vendor-specific prefix make sure to also include all other vendor-specific properties", diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 53de4e182aa..052f21b88e2 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -34,6 +34,7 @@ import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/exten import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, schemaId } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; +import { IJSONSchema } from 'vs/base/common/jsonSchema'; interface IStat { resource: URI; @@ -55,9 +56,7 @@ type IWorkspaceFoldersConfiguration = { [rootFolder: string]: { folders: string[ const configurationRegistry = Registry.as(Extensions.Configuration); -// BEGIN VSCode extension point `configuration` -const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configuration', [], { - description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'), +const configurationEntrySchema: IJSONSchema = { type: 'object', defaultSnippets: [{ body: { title: '', properties: {} } }], properties: { @@ -93,20 +92,25 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configuration', [], { + description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'), + oneOf: [ + configurationEntrySchema, + { + type: 'array', + items: configurationEntrySchema + } + ] }); configurationExtPoint.setHandler(extensions => { const configurations: IConfigurationNode[] = []; - - for (let i = 0; i < extensions.length; i++) { - const configuration = objects.clone(extensions[i].value); - const collector = extensions[i].collector; - - if (configuration.type && configuration.type !== 'object') { - collector.warn(nls.localize('invalid.type', "if set, 'configuration.type' must be set to 'object")); - } else { - configuration.type = 'object'; - } + function handleConfiguration(node: IConfigurationNode, id: string, collector: ExtensionMessageCollector) { + let configuration = objects.clone(node); if (configuration.title && (typeof configuration.title !== 'string')) { collector.error(nls.localize('invalid.title', "'configuration.title' must be a string")); @@ -114,10 +118,20 @@ configurationExtPoint.setHandler(extensions => { validateProperties(configuration, collector); - configuration.id = extensions[i].description.id; + configuration.id = id; configurations.push(configuration); - } + }; + for (let extension of extensions) { + const collector = extension.collector; + const value = extension.value; + const id = extension.description.id; + if (!Array.isArray(value)) { + handleConfiguration(value, id, collector); + } else { + value.forEach(v => handleConfiguration(v, id, collector)); + } + } configurationRegistry.registerConfigurations(configurations, false); }); // END VSCode extension point `configuration` @@ -167,6 +181,7 @@ function validateProperties(configuration: IConfigurationNode, collector: Extens } let subNodes = configuration.allOf; if (subNodes) { + collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point.")); for (let node of subNodes) { validateProperties(node, collector); } From b72963d5069cdca71a2db2b814cb8a06c55f8e58 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 13 Sep 2017 12:49:36 +0200 Subject: [PATCH 049/145] [json] Provide a flag in json schema to ignore a property in proposals. For #33083 --- src/vs/base/common/jsonSchema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/common/jsonSchema.ts b/src/vs/base/common/jsonSchema.ts index 1405eee19a5..44496dbcfb1 100644 --- a/src/vs/base/common/jsonSchema.ts +++ b/src/vs/base/common/jsonSchema.ts @@ -45,6 +45,7 @@ export interface IJSONSchema { patternErrorMessage?: string; // VSCode extension deprecationMessage?: string; // VSCode extension enumDescriptions?: string[]; // VSCode extension + doNotSuggest?: boolean; // VSCode extension } export interface IJSONSchemaMap { From 8351891a17d12891bb827ef17dc2ef4bca6f9ca9 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 13 Sep 2017 16:00:45 +0200 Subject: [PATCH 050/145] [html] remove console log --- extensions/html/server/src/htmlServerMain.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/html/server/src/htmlServerMain.ts b/extensions/html/server/src/htmlServerMain.ts index 9b53da722a2..14ea13ba25c 100644 --- a/extensions/html/server/src/htmlServerMain.ts +++ b/extensions/html/server/src/htmlServerMain.ts @@ -54,7 +54,6 @@ documents.onDidClose(e => { }); function getDocumentSettings(textDocument: TextDocument, needsDocumentSettings: () => boolean): Thenable { - console.log('scopedSettingsSupport ' + scopedSettingsSupport + 'needsSettings ' + needsDocumentSettings()); if (scopedSettingsSupport && needsDocumentSettings()) { let promise = documentSettings[textDocument.uri]; if (!promise) { From fb5cdf0948d0f60c10628bb2b6193d002ee9e341 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 13 Sep 2017 16:31:34 +0200 Subject: [PATCH 051/145] [html] change default of html.format.unformatted to empty --- extensions/html/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/html/package.json b/extensions/html/package.json index a5ebee09dd3..240cb7d8d9f 100644 --- a/extensions/html/package.json +++ b/extensions/html/package.json @@ -92,7 +92,7 @@ "null" ], "scope": "resource", - "default": "a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, select, small, span, strong, sub, sup, textarea, tt, var", + "default": "", "description": "%html.format.unformatted.desc%" }, "html.format.contentUnformatted": { @@ -101,7 +101,7 @@ "null" ], "scope": "resource", - "default": "pre", + "default": "pre,code,textarea", "description": "%html.format.contentUnformatted.desc%" }, "html.format.indentInnerHtml": { From 7ecb3f9feb10a0fc28ee95be278273c70e78530a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Wed, 13 Sep 2017 16:52:09 +0200 Subject: [PATCH 052/145] smoke: fix typo --- build/tfs/win32/smoketest.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tfs/win32/smoketest.ps1 b/build/tfs/win32/smoketest.ps1 index 072707d0432..65f6896806d 100644 --- a/build/tfs/win32/smoketest.ps1 +++ b/build/tfs/win32/smoketest.ps1 @@ -38,7 +38,7 @@ step "Build minified" { } step "Run smoke test" { - $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketests-screenshots" + $Screenshots = "$env:AGENT_BUILDDIRECTORY\smoketest-screenshots" Remove-Item -Recurse -Force -ErrorAction Ignore $Screenshots exec { & Push-Location test\smoke } From a400e3a2399072b0cfaa746bb0c9b25915db0e98 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 17:08:28 +0200 Subject: [PATCH 053/145] #33963 Revert the changes 1c7479e970499383d292e1264cfaeda794a24864 --- src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index 53c35db2f3b..f2ebd600999 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -7,7 +7,6 @@ import 'vs/css!./zoneWidget'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Widget } from 'vs/base/browser/ui/widget'; import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; import { Sash, Orientation, IHorizontalSashLayoutProvider, ISashEvent } from 'vs/base/browser/ui/sash/sash'; @@ -157,7 +156,7 @@ class Arrow { } } -export abstract class ZoneWidget extends Widget implements IHorizontalSashLayoutProvider { +export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { private _arrow: Arrow; private _overlayWidget: OverlayWidgetDelegate; @@ -174,7 +173,6 @@ export abstract class ZoneWidget extends Widget implements IHorizontalSashLayout constructor(editor: ICodeEditor, options: IOptions = {}) { - super(); this.editor = editor; this.options = objects.clone(options); objects.mixin(this.options, defaultOptions, false); From 1ecdf0a54c569a74f31562aa92783be1911d4471 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 17:18:21 +0200 Subject: [PATCH 054/145] debug: exceptino widget background non transparent fixes #32093 --- src/vs/workbench/parts/debug/browser/exceptionWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/debug/browser/exceptionWidget.ts b/src/vs/workbench/parts/debug/browser/exceptionWidget.ts index 3719a86393b..cbb4c4e8bd9 100644 --- a/src/vs/workbench/parts/debug/browser/exceptionWidget.ts +++ b/src/vs/workbench/parts/debug/browser/exceptionWidget.ts @@ -21,7 +21,7 @@ const $ = dom.$; // theming export const debugExceptionWidgetBorder = registerColor('debugExceptionWidget.border', { dark: '#a31515', light: '#a31515', hc: '#a31515' }, nls.localize('debugExceptionWidgetBorder', 'Exception widget border color.')); -export const debugExceptionWidgetBackground = registerColor('debugExceptionWidget.background', { dark: '#a3151540', light: '#a315150d', hc: '#a3151573' }, nls.localize('debugExceptionWidgetBackground', 'Exception widget background color.')); +export const debugExceptionWidgetBackground = registerColor('debugExceptionWidget.background', { dark: '#420b0d', light: '#f1dfde', hc: '#420b0d' }, nls.localize('debugExceptionWidgetBackground', 'Exception widget background color.')); export class ExceptionWidget extends ZoneWidget { From 15ddfb708586097d611d407b5c4937e67b3d63fa Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 17:27:22 +0200 Subject: [PATCH 055/145] debug smoke test tidbits --- test/smoke/src/areas/debug/debug.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 7c039187c9d..ca9e4e046bc 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -45,6 +45,7 @@ describe('Debug', () => { await app.workbench.debug.openDebugViewlet(); await app.workbench.openFile('app.js'); await app.workbench.debug.configure(); + await app.screenCapturer.capture('launch.json file'); const content = await app.workbench.editor.getEditorVisibleText(); // TODO@isidor: sometimes on the linux build agent, @@ -74,7 +75,7 @@ describe('Debug', () => { http.get(`http://localhost:3000`) .on('error', e => void 0); c(); - }, 400); + }, 600); }); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); @@ -108,7 +109,7 @@ describe('Debug', () => { http.get(`http://localhost:3000`) .on('error', e => void 0); c(); - }, 400); + }, 600); }); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); From af56569a339415a2f80fb94ef549b38b53f3d69b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 13 Sep 2017 18:42:54 +0200 Subject: [PATCH 056/145] fix issue with editor history navigation merging --- .../services/history/browser/history.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 3b55591f9ff..228871a54f0 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -174,7 +174,6 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic private static MAX_HISTORY_ITEMS = 200; private static MAX_STACK_ITEMS = 20; private static MAX_RECENTLY_CLOSED_EDITORS = 20; - private static MERGE_EVENT_CHANGES_THRESHOLD = 300; private stack: IStackEntry[]; private index: number; @@ -545,19 +544,12 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic // on the stack. // We can also be instructed to force replace the last entry. let replace = false; - if (this.stack[this.index]) { + const currentEntry = this.stack[this.index]; + if (currentEntry) { if (forceReplace) { - replace = true; - } else { - const currentEntry = this.stack[this.index]; - if (this.matches(input, currentEntry.input) && // and: entry of same input - ( - this.sameSelection(currentEntry.selection, selection) || // and: entry has same selection - (Date.now() - currentEntry.timestamp < HistoryService.MERGE_EVENT_CHANGES_THRESHOLD) // or: entry occured very fast and is likely not human - ) - ) { - replace = true; - } + replace = true; // replace if we are forced to + } else if (this.matches(input, currentEntry.input) && this.sameSelection(currentEntry.selection, selection)) { + replace = true; // replace if the input is the same as the current one and the selection as well } } From 47cfc8bf7aa3778e358c15d0cfa483eb0e637522 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 13 Sep 2017 18:57:12 +0200 Subject: [PATCH 057/145] ImportFileAction doesn't use URI (fixes #34235) --- .../parts/files/browser/fileActions.ts | 17 ++++++++--------- .../parts/files/browser/views/explorerViewer.ts | 5 ++--- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 3c609e62030..9a2ab3ea142 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -798,10 +798,9 @@ export class ImportFileAction extends BaseFileAction { return this.tree; } - public run(context?: any): TPromise { + public run(resources: URI[]): TPromise { const importPromise = TPromise.as(null).then(() => { - const input = context.input as { paths: string[] }; - if (input.paths && input.paths.length > 0) { + if (resources && resources.length > 0) { // Find parent for import let targetElement: FileStat; @@ -826,8 +825,8 @@ export class ImportFileAction extends BaseFileAction { }); let overwrite = true; - if (input.paths.some(path => { - return !!targetNames[isLinux ? paths.basename(path) : paths.basename(path).toLowerCase()]; + if (resources.some(resource => { + return !!targetNames[isLinux ? paths.basename(resource.fsPath) : paths.basename(resource.fsPath).toLowerCase()]; })) { const confirm: IConfirmation = { message: nls.localize('confirmOverwrite', "A file or folder with the same name already exists in the destination folder. Do you want to replace it?"), @@ -845,10 +844,10 @@ export class ImportFileAction extends BaseFileAction { // Run import in sequence const importPromisesFactory: ITask>[] = []; - input.paths.forEach(path => { + resources.forEach(resource => { importPromisesFactory.push(() => { - const sourceFile = URI.file(path); - const targetFile = URI.file(paths.join(targetElement.resource.fsPath, paths.basename(path))); + const sourceFile = resource; + const targetFile = targetElement.resource.with({ path: paths.join(targetElement.resource.fsPath, paths.basename(sourceFile.fsPath)) }); // if the target exists and is dirty, make sure to revert it. otherwise the dirty contents // of the target file would replace the contents of the imported file. since we already @@ -862,7 +861,7 @@ export class ImportFileAction extends BaseFileAction { return this.fileService.importFile(sourceFile, targetElement.resource).then(res => { // if we only import one file, just open it directly - if (input.paths.length === 1) { + if (resources.length === 1) { this.editorService.openEditor({ resource: res.stat.resource, options: { pinned: true } }).done(null, errors.onUnexpectedError); } }, error => this.onError(error)); diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 3622e0e1ba4..b1b520c78a4 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -910,9 +910,8 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // Handle dropped files (only support FileStat as target) else if (target instanceof FileStat) { const importAction = this.instantiationService.createInstance(ImportFileAction, tree, target, null); - return importAction.run({ - input: { paths: droppedResources.map(res => res.resource.fsPath) } - }); + + return importAction.run(droppedResources.map(res => res.resource)); } return void 0; From f44271187fcd1283f2b63e1e7f0029682b6d508b Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 19:06:32 +0200 Subject: [PATCH 058/145] debug smoke polish --- test/smoke/src/areas/debug/debug.test.ts | 26 +++++++++--------------- test/smoke/src/areas/debug/debug.ts | 4 ++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index ca9e4e046bc..b5486fbe9b9 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -46,12 +46,14 @@ describe('Debug', () => { await app.workbench.openFile('app.js'); await app.workbench.debug.configure(); await app.screenCapturer.capture('launch.json file'); - const content = await app.workbench.editor.getEditorVisibleText(); - - // TODO@isidor: sometimes on the linux build agent, - // you get the contents of app.js here, so everything - // blows up - const json = JSON.parse(stripJsonComments(content)); + let json; + await app.client.waitFor(async () => { + const content = await app.workbench.editor.getEditorVisibleText(); + try { + json = JSON.parse(stripJsonComments(content)); + return true; + } catch (e) { return false; } + }, result => result); assert.equal(json.configurations[0].request, 'launch'); assert.equal(json.configurations[0].type, 'node'); @@ -75,7 +77,7 @@ describe('Debug', () => { http.get(`http://localhost:3000`) .on('error', e => void 0); c(); - }, 600); + }, 400); }); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); @@ -103,15 +105,7 @@ describe('Debug', () => { it('continue', async function () { await app.workbench.debug.continue(); - - await new Promise(c => { - setTimeout(() => { - http.get(`http://localhost:3000`) - .on('error', e => void 0); - c(); - }, 600); - }); - + http.get(`http://localhost:3000`).on('error', e => void 0); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); }); diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index 0e3702de5eb..17718fe93d9 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -61,6 +61,10 @@ export class Debug extends Viewlet { await this.spectron.client.waitAndClick(START); await this.spectron.client.waitForElement(PAUSE); await this.spectron.client.waitForElement(DEBUG_STATUS_BAR); + await this.spectron.client.waitFor(async () => { + const output = await this.getConsoleOutput(); + return output.pop(); + }, text => text === 'Debugger attached.'); } async stepOver(): Promise { From 75c1feb7dcd8a46475edc54cd60f7cdc11311672 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 10:13:45 -0700 Subject: [PATCH 059/145] Add editor.lightbulb.enabed setting (#33982) Fixes #27961 Adds a new `editor.lightbulb.enabled` setting to enable/disable the code actions lighbulb. You can still trigger code actions manually --- .../common/config/commonEditorConfig.ts | 5 ++ src/vs/editor/common/config/editorOptions.ts | 24 +++++- .../quickFix/browser/lightBulbWidget.ts | 6 +- .../quickFix/browser/quickFixCommands.ts | 86 +++++++++++++------ src/vs/monaco.d.ts | 16 ++++ 5 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 14d3ec12623..d00a0e2365b 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -598,6 +598,11 @@ const editorConfiguration: IConfigurationNode = { 'default': EDITOR_DEFAULTS.contribInfo.colorDecorators, 'description': nls.localize('colorDecorators', "Controls whether the editor should render the inline color decorators and color picker.") }, + 'editor.lightbulb.enabled': { + 'type': 'boolean', + 'default': EDITOR_DEFAULTS.contribInfo.lightbulbEnabled, + 'description': nls.localize('codeActions', "Enables the code action lightbulb") + }, 'diffEditor.renderSideBySide': { 'type': 'boolean', 'default': true, diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index d3a94dcc623..e1c77e1f78a 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -114,6 +114,17 @@ export interface IEditorMinimapOptions { maxColumn?: number; } +/** + * Configuration options for editor minimap + */ +export interface IEditorLightbulbOptions { + /** + * Enable the lightbulb code action. + * Defaults to true. + */ + enabled?: boolean; +} + /** * Configuration options for the editor. */ @@ -462,6 +473,10 @@ export interface IEditorOptions { * @internal */ referenceInfos?: boolean; + /** + * Control the behavior and rendering of the code action lightbulb. + */ + lightbulb?: IEditorLightbulbOptions; /** * Enable code folding * Defaults to true in vscode and to false in monaco-editor. @@ -795,6 +810,7 @@ export interface EditorContribOptions { readonly matchBrackets: boolean; readonly find: InternalEditorFindOptions; readonly colorDecorators: boolean; + readonly lightbulbEnabled: boolean; } /** @@ -1140,6 +1156,7 @@ export class InternalEditorOptions { && a.matchBrackets === b.matchBrackets && this._equalFindOptions(a.find, b.find) && a.colorDecorators === b.colorDecorators + && a.lightbulbEnabled === b.lightbulbEnabled ); } @@ -1669,6 +1686,7 @@ export class EditorOptionsValidator { matchBrackets: _boolean(opts.matchBrackets, defaults.matchBrackets), find: find, colorDecorators: _boolean(opts.colorDecorators, defaults.colorDecorators), + lightbulbEnabled: _boolean(opts.lightbulb.enabled, defaults.lightbulbEnabled) }; } } @@ -1766,7 +1784,8 @@ export class InternalEditorOptionsFactory { showFoldingControls: opts.contribInfo.showFoldingControls, matchBrackets: (accessibilityIsOn ? false : opts.contribInfo.matchBrackets), // DISABLED WHEN SCREEN READER IS ATTACHED find: opts.contribInfo.find, - colorDecorators: opts.contribInfo.colorDecorators + colorDecorators: opts.contribInfo.colorDecorators, + lightbulbEnabled: opts.contribInfo.lightbulbEnabled } }; } @@ -2205,6 +2224,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { seedSearchStringFromSelection: true, autoFindInSelection: false }, - colorDecorators: true + colorDecorators: true, + lightbulbEnabled: true }, }; diff --git a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts index 8bb2b4c2f02..c25c621b809 100644 --- a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts @@ -29,12 +29,12 @@ export class LightBulbWidget implements IDisposable, IContentWidget { private _futureFixes = new CancellationTokenSource(); constructor(editor: ICodeEditor) { - this._editor = editor; - this._editor.addContentWidget(this); - this._domNode = document.createElement('div'); this._domNode.className = 'lightbulb-glyph'; + this._editor = editor; + this._editor.addContentWidget(this); + this._disposables.push(dom.addStandardDisposableListener(this._domNode, 'click', e => { // a bit of extra work to make sure the menu // doesn't cover the line-text diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts b/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts index 605591babeb..e6a1ef98e96 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts @@ -9,7 +9,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IMarkerService } from 'vs/platform/markers/common/markers'; import { ICommonCodeEditor, IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -32,30 +32,28 @@ export class QuickFixController implements IEditorContribution { private _editor: ICodeEditor; private _model: QuickFixModel; - private _quickFixContextMenu: QuickFixContextMenu; - private _lightBulbWidget: LightBulbWidget; + private _quickFixContextMenu: QuickFixContextMenu | undefined; + private _lightBulbWidget: LightBulbWidget | undefined; private _disposables: IDisposable[] = []; + private enabled: boolean = false; - constructor(editor: ICodeEditor, + + constructor( + editor: ICodeEditor, @IMarkerService markerService: IMarkerService, - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService, - @IContextMenuService contextMenuService: IContextMenuService, - @IKeybindingService private _keybindingService: IKeybindingService + @ICommandService private readonly _commandService: ICommandService, + @IContextMenuService private readonly _contextMenuService: IContextMenuService, + @IKeybindingService private readonly _keybindingService: IKeybindingService ) { this._editor = editor; this._model = new QuickFixModel(this._editor, markerService); - this._quickFixContextMenu = new QuickFixContextMenu(editor, contextMenuService, commandService); - this._lightBulbWidget = new LightBulbWidget(editor); - - this._updateLightBulbTitle(); this._disposables.push( - this._quickFixContextMenu.onDidExecuteCodeAction(_ => this._model.trigger('auto')), - this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), - this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)), - this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) + this._editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()), + this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)) ); + + this.onEditorConfigurationChange(); } public dispose(): void { @@ -63,21 +61,46 @@ export class QuickFixController implements IEditorContribution { dispose(this._disposables); } + private get lightBulbWidget(): LightBulbWidget { + if (!this._lightBulbWidget) { + this._lightBulbWidget = new LightBulbWidget(this._editor); + this._disposables.push( + this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), + this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) + ); + this._updateLightBulbTitle(); + } + return this._lightBulbWidget; + } + + private get quickFixContextMenu(): QuickFixContextMenu { + if (!this._quickFixContextMenu) { + this._quickFixContextMenu = new QuickFixContextMenu(this._editor, this._contextMenuService, this._commandService); + this._disposables.push(this._quickFixContextMenu.onDidExecuteCodeAction(_ => { + this._model.trigger('auto'); + })); + } + return this._quickFixContextMenu; + } + private _onQuickFixEvent(e: QuickFixComputeEvent): void { if (e && e.type === 'manual') { - this._quickFixContextMenu.show(e.fixes, e.position); - + this.quickFixContextMenu.show(e.fixes, e.position); } else if (e && e.fixes) { // auto magically triggered // * update an existing list of code actions // * manage light bulb - if (this._quickFixContextMenu.isVisible) { - this._quickFixContextMenu.show(e.fixes, e.position); + if (this.quickFixContextMenu.isVisible) { + this.quickFixContextMenu.show(e.fixes, e.position); } else { - this._lightBulbWidget.model = e; + if (this.enabled) { + this.lightBulbWidget.model = e; + } } } else { - this._lightBulbWidget.hide(); + if (this._lightBulbWidget) { + this._lightBulbWidget.hide(); + } } } @@ -86,7 +109,7 @@ export class QuickFixController implements IEditorContribution { } private _handleLightBulbSelect(coords: { x: number, y: number }): void { - this._quickFixContextMenu.show(this._lightBulbWidget.model.fixes, coords); + this.quickFixContextMenu.show(this.lightBulbWidget.model.fixes, coords); } public triggerFromEditorSelection(): void { @@ -94,6 +117,10 @@ export class QuickFixController implements IEditorContribution { } private _updateLightBulbTitle(): void { + if (!this._lightBulbWidget) { + return; + } + const kb = this._keybindingService.lookupKeybinding(QuickFixAction.Id); let title: string; if (kb) { @@ -101,7 +128,18 @@ export class QuickFixController implements IEditorContribution { } else { title = nls.localize('quickFix', "Show Fixes"); } - this._lightBulbWidget.title = title; + this.lightBulbWidget.title = title; + } + + private onEditorConfigurationChange(): void { + this.enabled = this._editor.getConfiguration().contribInfo.lightbulbEnabled; + + if (!this.enabled) { + if (this._lightBulbWidget) { + this._lightBulbWidget.dispose(); + this._lightBulbWidget = undefined; + } + } } } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 467ac20a374..194484f2618 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2683,6 +2683,17 @@ declare module monaco.editor { maxColumn?: number; } + /** + * Configuration options for editor minimap + */ + export interface IEditorLightbulbOptions { + /** + * Enable the lightbulb code action. + * Defaults to true. + */ + enabled?: boolean; + } + /** * Configuration options for the editor. */ @@ -3018,6 +3029,10 @@ declare module monaco.editor { * Defaults to true. */ codeLens?: boolean; + /** + * Control the behavior and rendering of the code action lightbulb. + */ + lightbulb?: IEditorLightbulbOptions; /** * Enable code folding * Defaults to true in vscode and to false in monaco-editor. @@ -3296,6 +3311,7 @@ declare module monaco.editor { readonly matchBrackets: boolean; readonly find: InternalEditorFindOptions; readonly colorDecorators: boolean; + readonly lightbulbEnabled: boolean; } /** From 43cb3b41ac032855631dc2956569c4f7290b851c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 10:39:54 -0700 Subject: [PATCH 060/145] Continue tweaking default dark and light colorization for escape characters and regular expressions --- .../colorize-results/test-regex_coffee.json | 6 +- .../test/colorize-results/test_coffee.json | 12 ++-- .../fsharp/test/colorize-results/test_fs.json | 6 +- .../json/test/colorize-results/test_json.json | 6 +- .../make/test/colorize-results/makefile.json | 30 ++++----- .../perl/test/colorize-results/test2_pl.json | 24 +++---- .../perl/test/colorize-results/test_pl.json | 54 ++++++++-------- .../colorize-results/issue-28354_php.json | 12 ++-- .../python/test/colorize-results/test_py.json | 62 +++++++++---------- .../ruby/test/colorize-results/test_rb.json | 24 +++---- .../scss/test/colorize-results/test_scss.json | 18 +++--- .../theme-defaults/themes/dark_plus.json | 17 ++++- extensions/theme-defaults/themes/dark_vs.json | 8 ++- .../themes/hc_black_defaults.json | 9 ++- .../theme-defaults/themes/light_plus.json | 16 ++++- .../theme-defaults/themes/light_vs.json | 3 +- .../theme-red/themes/Red-color-theme.json | 14 ++++- 17 files changed, 182 insertions(+), 139 deletions(-) diff --git a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json index cc3f1d3d7ab..909a6112f35 100644 --- a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json @@ -80,11 +80,11 @@ "c": "\\d", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/coffeescript/test/colorize-results/test_coffee.json b/extensions/coffeescript/test/colorize-results/test_coffee.json index 8c1254dfa9f..4320ae579e6 100644 --- a/extensions/coffeescript/test/colorize-results/test_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test_coffee.json @@ -1389,11 +1389,11 @@ "c": "\\d", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -1477,11 +1477,11 @@ "c": "\\w", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/fsharp/test/colorize-results/test_fs.json b/extensions/fsharp/test/colorize-results/test_fs.json index 2f161a6fccc..ee0ae2ca9c1 100644 --- a/extensions/fsharp/test/colorize-results/test_fs.json +++ b/extensions/fsharp/test/colorize-results/test_fs.json @@ -1026,11 +1026,11 @@ "c": "\\n", "t": "source.fsharp string.quoted.double.fsharp constant.character.string.escape.fsharp", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/json/test/colorize-results/test_json.json b/extensions/json/test/colorize-results/test_json.json index 5f9b48b1ea0..facb8d52a57 100644 --- a/extensions/json/test/colorize-results/test_json.json +++ b/extensions/json/test/colorize-results/test_json.json @@ -388,11 +388,11 @@ "c": "\\u0056", "t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json constant.character.escape.json", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/make/test/colorize-results/makefile.json b/extensions/make/test/colorize-results/makefile.json index b91562aaa2f..1fb93bab87c 100644 --- a/extensions/make/test/colorize-results/makefile.json +++ b/extensions/make/test/colorize-results/makefile.json @@ -135,11 +135,11 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "constant.character: #569CD6" } }, { @@ -278,11 +278,11 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "constant.character: #569CD6" } }, { @@ -322,11 +322,11 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "comment: #608B4E", "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" + "hc_black": "constant.character: #569CD6" } }, { @@ -377,11 +377,11 @@ "c": "\\", "t": "source.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "comment: #608B4E", - "light_plus": "comment: #008000", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "comment: #608B4E", "light_vs": "comment: #008000", - "hc_black": "comment: #7CA668" + "hc_black": "constant.character: #569CD6" } }, { @@ -553,11 +553,11 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/perl/test/colorize-results/test2_pl.json b/extensions/perl/test/colorize-results/test2_pl.json index ef4bcabf439..af312ff8930 100644 --- a/extensions/perl/test/colorize-results/test2_pl.json +++ b/extensions/perl/test/colorize-results/test2_pl.json @@ -1301,11 +1301,11 @@ "c": "\\d\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -1323,11 +1323,11 @@ "c": "\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -1345,11 +1345,11 @@ "c": "\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -1774,11 +1774,11 @@ "c": "\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/perl/test/colorize-results/test_pl.json b/extensions/perl/test/colorize-results/test_pl.json index dd6dc702ac1..8062166dc5c 100644 --- a/extensions/perl/test/colorize-results/test_pl.json +++ b/extensions/perl/test/colorize-results/test_pl.json @@ -388,11 +388,11 @@ "c": "\\s", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -410,11 +410,11 @@ "c": "\\s", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -432,11 +432,11 @@ "c": "\\(", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -454,11 +454,11 @@ "c": "\\)", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -476,11 +476,11 @@ "c": "\\)", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -674,11 +674,11 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -949,11 +949,11 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -1444,11 +1444,11 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -2280,11 +2280,11 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/php/test/colorize-results/issue-28354_php.json b/extensions/php/test/colorize-results/issue-28354_php.json index d9f870d7f85..d55a914a79b 100644 --- a/extensions/php/test/colorize-results/issue-28354_php.json +++ b/extensions/php/test/colorize-results/issue-28354_php.json @@ -278,11 +278,11 @@ "c": "\\'", "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -377,11 +377,11 @@ "c": "\\'", "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/python/test/colorize-results/test_py.json b/extensions/python/test/colorize-results/test_py.json index 4c183d734fa..ef8d364c52b 100644 --- a/extensions/python/test/colorize-results/test_py.json +++ b/extensions/python/test/colorize-results/test_py.json @@ -5294,8 +5294,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5305,8 +5305,8 @@ "c": "[", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "meta.character.set.regexp: #D7BA7D", + "light_plus": "meta.character.set.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5316,19 +5316,19 @@ "c": "0-9-", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { "c": "]", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "meta.character.set.regexp: #D7BA7D", + "light_plus": "meta.character.set.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5349,8 +5349,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5382,8 +5382,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5393,8 +5393,8 @@ "c": "[", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "meta.character.set.regexp: #D7BA7D", + "light_plus": "meta.character.set.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5404,19 +5404,19 @@ "c": "A-Za-z", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { "c": "]", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "meta.character.set.regexp: #D7BA7D", + "light_plus": "meta.character.set.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5437,8 +5437,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5481,8 +5481,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5514,8 +5514,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", + "light_plus": "support.other.parenthesis.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -6504,8 +6504,8 @@ "c": "[", "t": "source.python string.regexp.quoted.multi.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "meta.character.set.regexp: #D7BA7D", + "light_plus": "meta.character.set.regexp: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -6515,11 +6515,11 @@ "c": "1,2)`` leads to", "t": "source.python string.regexp.quoted.multi.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character: #569CD6", + "light_plus": "constant.character: #0000FF", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/ruby/test/colorize-results/test_rb.json b/extensions/ruby/test/colorize-results/test_rb.json index be7150a63e0..005f04f37c3 100644 --- a/extensions/ruby/test/colorize-results/test_rb.json +++ b/extensions/ruby/test/colorize-results/test_rb.json @@ -2500,11 +2500,11 @@ "c": "\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -2522,11 +2522,11 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -2544,11 +2544,11 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { @@ -2577,11 +2577,11 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "string.regexp: #D16969", - "light_plus": "string.regexp: #811F3F", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", - "hc_black": "string.regexp: #D16969" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/scss/test/colorize-results/test_scss.json b/extensions/scss/test/colorize-results/test_scss.json index 961c9da0912..301d6fc35fd 100644 --- a/extensions/scss/test/colorize-results/test_scss.json +++ b/extensions/scss/test/colorize-results/test_scss.json @@ -20716,11 +20716,11 @@ "c": "\\\\", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -20837,11 +20837,11 @@ "c": "\\'", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { @@ -20914,11 +20914,11 @@ "c": "\\\"", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.double.scss constant.character.escape.scss", "r": { - "dark_plus": "string: #CE9178", - "light_plus": "string: #A31515", + "dark_plus": "constant.character.escape: #C586C0", + "light_plus": "constant.character.escape: #FF0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", - "hc_black": "string: #CE9178" + "hc_black": "constant.character: #569CD6" } }, { diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index 64ba03b2576..55052a69d66 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -107,7 +107,9 @@ "punctuation.definition.group.regexp", "punctuation.definition.group.assertion.regexp", "punctuation.definition.character-class.regexp", - "keyword.operator.negation.regexp" + "keyword.operator.negation.regexp", + "support.other.parenthesis.regexp", + "meta.character.set.regexp" ], "settings": { "foreground": "#d7ba7d" @@ -124,6 +126,19 @@ "settings": { "foreground": "#C586C0" } + }, + { + "scope": "constant.character", + "settings": { + "foreground": "#569cd6" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#C586C0" + } } + ] } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/dark_vs.json b/extensions/theme-defaults/themes/dark_vs.json index 91ad2adcbd7..084720561d0 100644 --- a/extensions/theme-defaults/themes/dark_vs.json +++ b/extensions/theme-defaults/themes/dark_vs.json @@ -10,7 +10,10 @@ } }, { - "scope": ["meta.embedded", "source.groovy.embedded"], + "scope": [ + "meta.embedded", + "source.groovy.embedded" + ], "settings": { "foreground": "#D4D4D4", "background": "#1E1E1E" @@ -252,8 +255,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded", - "constant.character.format.placeholder" + "punctuation.section.embedded" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/hc_black_defaults.json b/extensions/theme-defaults/themes/hc_black_defaults.json index cd54a7bd6d2..8833ff32c1f 100644 --- a/extensions/theme-defaults/themes/hc_black_defaults.json +++ b/extensions/theme-defaults/themes/hc_black_defaults.json @@ -71,6 +71,12 @@ "foreground": "#b46695" } }, + { + "scope": "constant.character", + "settings": { + "foreground": "#569cd6" + } + }, { "scope": "entity.name.tag", "settings": { @@ -241,8 +247,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded", - "constant.character.format.placeholder" + "punctuation.section.embedded" ], "settings": { "foreground": "#569cd6" diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index a1dc19560a7..b533627c9f2 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -107,7 +107,9 @@ "punctuation.definition.group.regexp", "punctuation.definition.group.assertion.regexp", "punctuation.definition.character-class.regexp", - "keyword.operator.negation.regexp" + "keyword.operator.negation.regexp", + "support.other.parenthesis.regexp", + "meta.character.set.regexp" ], "settings": { "foreground": "#ff0000" @@ -124,6 +126,18 @@ "settings": { "foreground": "#09885a" } + }, + { + "scope": "constant.character", + "settings": { + "foreground": "#0000ff" + } + }, + { + "scope": "constant.character.escape", + "settings": { + "foreground": "#ff0000" + } } ] } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json index 42fc12c88bd..883d88347dc 100644 --- a/extensions/theme-defaults/themes/light_vs.json +++ b/extensions/theme-defaults/themes/light_vs.json @@ -248,8 +248,7 @@ "scope": [ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", - "punctuation.section.embedded", - "constant.character.format.placeholder" + "punctuation.section.embedded" ], "settings": { "foreground": "#0000ff" diff --git a/extensions/theme-red/themes/Red-color-theme.json b/extensions/theme-red/themes/Red-color-theme.json index 7b14c4d558d..df3b63b3792 100644 --- a/extensions/theme-red/themes/Red-color-theme.json +++ b/extensions/theme-red/themes/Red-color-theme.json @@ -170,8 +170,16 @@ } }, { - "name": "String constant", - "scope": "string constant", + "scope": "constant.character", + "settings": { + "foreground": "#ec0d1e" + } + }, + { + "scope": [ + "string constant", + "constant.character.escape" + ], "settings": { "fontStyle": "", "foreground": "#ffe862ff" @@ -392,7 +400,7 @@ "punctuation.definition.template-expression.begin", "punctuation.definition.template-expression.end", "punctuation.section.embedded", - "constant.character.format.placeholder" + ".format.placeholder" ], "settings": { "foreground": "#ec0d1e" From f9c49d7df6bbe4f2c000122f394cbb2e0ecdf9c5 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 13 Sep 2017 19:43:29 +0200 Subject: [PATCH 061/145] debug smoke test --- test/smoke/src/areas/debug/debug.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index 17718fe93d9..b103775c3c6 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -63,8 +63,8 @@ export class Debug extends Viewlet { await this.spectron.client.waitForElement(DEBUG_STATUS_BAR); await this.spectron.client.waitFor(async () => { const output = await this.getConsoleOutput(); - return output.pop(); - }, text => text === 'Debugger attached.'); + return output.join(''); + }, text => text.indexOf('Debugger listening on') >= 0); } async stepOver(): Promise { From 7e1f12fef9a526279c3f821901e173d03b85802d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 19:44:08 +0200 Subject: [PATCH 062/145] smoke test - improve waiting for active editor --- test/smoke/src/areas/debug/debug.ts | 2 +- test/smoke/src/areas/editor/editor.test.ts | 2 +- test/smoke/src/areas/quickopen/quickopen.ts | 3 +-- test/smoke/src/areas/workbench/data-loss.test.ts | 4 ++-- .../smoke/src/areas/workbench/data-migration.test.ts | 12 ++++++------ test/smoke/src/areas/workbench/workbench.ts | 10 ++++------ 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index b103775c3c6..a119b6b4921 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -104,7 +104,7 @@ export class Debug extends Viewlet { async focusStackFrame(name: string): Promise { const stackFrame = await this.waitForStackFrame(sf => sf.name === name); await this.spectron.client.spectron.client.elementIdClick(stackFrame.id); - await this.spectron.workbench.waitForOpen(name); + await this.spectron.workbench.waitForTab(name); } async console(text: string): Promise { diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index bbabe64e456..caee9d9b152 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -64,7 +64,7 @@ describe('Editor', () => { await app.workbench.editor.gotoDefinition('express', 11); - await app.workbench.waitForActiveOpen('index.d.ts'); + await app.workbench.waitForActiveTab('index.d.ts'); }); it(`verifies that 'Peek Definition' works`, async function () { diff --git a/test/smoke/src/areas/quickopen/quickopen.ts b/test/smoke/src/areas/quickopen/quickopen.ts index 23053718da6..63da04fa8ec 100644 --- a/test/smoke/src/areas/quickopen/quickopen.ts +++ b/test/smoke/src/areas/quickopen/quickopen.ts @@ -52,8 +52,7 @@ export class QuickOpen { await this.getQuickOpenElements(); await this.spectron.client.keys(['Enter', 'NULL']); - await this.spectron.client.waitForElement(`.tabs-container div[aria-selected="true"][aria-label="${fileName}, tab"]`); - await this.spectron.client.waitForElement(`div.editor-container[aria-label="${fileName}. Text file editor., Group 1."]`); + await this.spectron.workbench.waitForActiveTab(fileName); await this.spectron.workbench.waitForEditorFocus(fileName); } diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 01e79a8acc7..62c4fde7667 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -25,12 +25,12 @@ describe('Dataloss', () => { await app.reload(); await app.screenCapturer.capture('After reload'); - await app.workbench.waitForActiveOpen(fileName, true); + await app.workbench.waitForActiveTab(fileName, true); await app.screenCapturer.capture(`${fileName} after reload`); let actual = await app.workbench.editor.getEditorFirstLineText(); assert.ok(actual.startsWith(textToType), `${actual} did not start with ${textToType}`); - await app.workbench.waitForOpen(untitled, true); + await app.workbench.waitForTab(untitled, true); await app.workbench.selectTab('Untitled-1', true); await app.screenCapturer.capture('Untitled file after reload'); actual = await app.workbench.editor.getEditorFirstLineText(); diff --git a/test/smoke/src/areas/workbench/data-migration.test.ts b/test/smoke/src/areas/workbench/data-migration.test.ts index d4a785d74e6..4156ad0501a 100644 --- a/test/smoke/src/areas/workbench/data-migration.test.ts +++ b/test/smoke/src/areas/workbench/data-migration.test.ts @@ -36,7 +36,7 @@ describe('Data Migration', () => { await app.start('Data Migration'); app.screenCapturer.testName = 'Untitled is restorted'; - assert.ok(await app.workbench.waitForActiveOpen('Untitled-1', true), `Untitled-1 tab is not present after migration.`); + assert.ok(await app.workbench.waitForActiveTab('Untitled-1', true), `Untitled-1 tab is not present after migration.`); const actual = await app.workbench.editor.getEditorFirstLineText(); await app.screenCapturer.capture('Untitled file text'); assert.ok(actual.startsWith(textToType), `${actual} did not start with ${textToType}`); @@ -52,7 +52,7 @@ describe('Data Migration', () => { await app.start('Data Migration'); app.screenCapturer.testName = 'Newly created dirty file is restorted'; - await app.workbench.waitForActiveOpen(fileName); + await app.workbench.waitForActiveTab(fileName); await app.client.type(firstTextPart); await app.workbench.saveOpenedFile(); await app.client.type(secondTextPart); @@ -65,7 +65,7 @@ describe('Data Migration', () => { await app.start('Data Migration'); app.screenCapturer.testName = 'Newly created dirty file is restorted'; - assert.ok(await app.workbench.waitForActiveOpen(fileName.split('/')[1]), `Untitled-1 tab is not present after migration.`); + assert.ok(await app.workbench.waitForActiveTab(fileName.split('/')[1]), `Untitled-1 tab is not present after migration.`); const actual = await app.workbench.editor.getEditorFirstLineText(); await app.screenCapturer.capture(fileName + ' text'); assert.ok(actual.startsWith(firstTextPart.concat(secondTextPart)), `${actual} did not start with ${firstTextPart.concat(secondTextPart)}`); @@ -88,8 +88,8 @@ describe('Data Migration', () => { await app.start('Data Migration'); app.screenCapturer.testName = 'Opened tabs are restored'; - assert.ok(await app.workbench.waitForOpen(fileName1), `${fileName1} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForOpen(fileName2), `${fileName2} tab was not restored after migration.`); - assert.ok(await app.workbench.waitForOpen(fileName3), `${fileName3} tab was not restored after migration.`); + assert.ok(await app.workbench.waitForTab(fileName1), `${fileName1} tab was not restored after migration.`); + assert.ok(await app.workbench.waitForTab(fileName2), `${fileName2} tab was not restored after migration.`); + assert.ok(await app.workbench.waitForTab(fileName3), `${fileName3} tab was not restored after migration.`); }); }); \ No newline at end of file diff --git a/test/smoke/src/areas/workbench/workbench.ts b/test/smoke/src/areas/workbench/workbench.ts index 8700a83ec97..bf8743e6d8f 100644 --- a/test/smoke/src/areas/workbench/workbench.ts +++ b/test/smoke/src/areas/workbench/workbench.ts @@ -63,30 +63,28 @@ export class Workbench { public async selectTab(tabName: string, untitled: boolean = false): Promise { await this.spectron.client.waitAndClick(`.tabs-container div.tab[aria-label="${tabName}, tab"]`); - await this.waitForActiveOpen(tabName); await this.waitForEditorFocus(tabName, untitled); } public async waitForEditorFocus(fileName: string, untitled: boolean = false): Promise { - await this.spectron.client.waitForElement(`.editor-container[aria-label="${fileName}. ${untitled ? 'Untitled file text editor.' : 'Text file editor.'}, Group 1."] .monaco-editor.focused`); + await this.waitForActiveTab(fileName); + await this.spectron.client.waitForElement(`.editor-container[aria-label="${fileName}. ${untitled ? 'Untitled file text editor.' : 'Text file editor.'}, Group 1."] .monaco-editor textarea:focus`); } - public async waitForActiveOpen(fileName: string, isDirty: boolean = false): Promise { + public async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { return this.spectron.client.waitForElement(`.tabs-container div.tab.active${isDirty ? '.dirty' : ''}[aria-selected="true"][aria-label="${fileName}, tab"]`).then(() => true); } - public async waitForOpen(fileName: string, isDirty: boolean = false): Promise { + public async waitForTab(fileName: string, isDirty: boolean = false): Promise { return this.spectron.client.waitForElement(`.tabs-container div.tab${isDirty ? '.dirty' : ''}[aria-label="${fileName}, tab"]`).then(() => true); } public async newUntitledFile(): Promise { await this.spectron.command('workbench.action.files.newUntitledFile'); - await this.waitForActiveOpen('Untitled-1'); await this.waitForEditorFocus('Untitled-1', true); } async openFile(fileName: string): Promise { await this.quickopen.openFile(fileName); - await this.spectron.client.waitForElement(`.monaco-editor.focused`); } } From 43f8f0806c9147072aa4f0332a1452b6f8a63823 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 20:07:06 +0200 Subject: [PATCH 063/145] smoke: improve status bar tests --- test/smoke/src/areas/problems/problems.ts | 6 +++++- test/smoke/src/areas/quickopen/quickopen.ts | 9 ++------- test/smoke/src/areas/statusbar/statusbar.test.ts | 16 ++++++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/test/smoke/src/areas/problems/problems.ts b/test/smoke/src/areas/problems/problems.ts index ec05cd4a025..43548fc490a 100644 --- a/test/smoke/src/areas/problems/problems.ts +++ b/test/smoke/src/areas/problems/problems.ts @@ -21,7 +21,7 @@ export class Problems { public async showProblemsView(): Promise { if (!await this.isVisible()) { await this.spectron.command('workbench.actions.view.problems'); - await this.spectron.client.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR); + await this.waitForProblemsView(); } } @@ -37,6 +37,10 @@ export class Problems { return !!element; } + public async waitForProblemsView(): Promise { + await this.spectron.client.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR); + } + public static getSelectorInProblemsView(problemType: ProblemSeverity): string { let selector = problemType === ProblemSeverity.WARNING ? 'warning' : 'error'; return `div[aria-label="Problems grouped by files"] .icon.${selector}`; diff --git a/test/smoke/src/areas/quickopen/quickopen.ts b/test/smoke/src/areas/quickopen/quickopen.ts index 63da04fa8ec..9f91b96f1ae 100644 --- a/test/smoke/src/areas/quickopen/quickopen.ts +++ b/test/smoke/src/areas/quickopen/quickopen.ts @@ -69,19 +69,14 @@ export class QuickOpen { await this.spectron.client.waitAndClick(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT); } - protected waitForQuickOpenOpened(): Promise { + public waitForQuickOpenOpened(): Promise { return this.spectron.client.waitForElement(QuickOpen.QUICK_OPEN_FOCUSSED_INPUT); } - protected waitForQuickOpenClosed(): Promise { + public waitForQuickOpenClosed(): Promise { return this.spectron.client.waitForElement(QuickOpen.QUICK_OPEN_HIDDEN); } - public async isQuickOpenVisible(): Promise { - await this.waitForQuickOpenOpened(); - return true; - } - public async submit(text: string): Promise { await this.spectron.client.type(text); await this.spectron.client.keys(['Enter', 'NULL']); diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 37221970fa1..42a71882469 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -33,27 +33,27 @@ describe('Statusbar', () => { it(`verifies that 'quick open' opens when clicking on status bar elements`, async function () { await app.workbench.statusbar.clickOn(StatusBarElement.BRANCH_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened for branch indicator.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.closeQuickOpen(); await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.INDENTATION_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened for indentation indicator.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.closeQuickOpen(); await app.workbench.statusbar.clickOn(StatusBarElement.ENCODING_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened for encoding indicator.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.closeQuickOpen(); await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened for EOL indicator.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.closeQuickOpen(); await app.workbench.statusbar.clickOn(StatusBarElement.LANGUAGE_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened for language indicator.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.closeQuickOpen(); }); it(`verifies that 'Problems View' appears when clicking on 'Problems' status element`, async function () { await app.workbench.statusbar.clickOn(StatusBarElement.PROBLEMS_STATUS); - assert.ok(await app.workbench.problems.isVisible()); + await app.workbench.problems.waitForProblemsView(); }); if (app.build !== VSCODE_BUILD.DEV) { @@ -67,7 +67,7 @@ describe('Statusbar', () => { await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened line number selection.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); await app.workbench.quickopen.submit('15'); await app.workbench.editor.waitForHighlightingLine(15); @@ -77,7 +77,7 @@ describe('Statusbar', () => { await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.EOL_STATUS); - assert.ok(await app.workbench.quickopen.isQuickOpenVisible(), 'Quick open is not opened line number selection.'); + await app.workbench.quickopen.waitForQuickOpenOpened(); app.workbench.quickopen.selectQuickOpenElement(1); await app.workbench.statusbar.waitForEOL('CRLF'); From 70a14d8a54e01582fabc8ab3cde6ce45f554e666 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Wed, 13 Sep 2017 11:08:31 -0700 Subject: [PATCH 064/145] Use dp0 instead of ROOT in test-integration.bat --- scripts/test-integration.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 31e14284571..0a2b92e00d7 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -12,7 +12,7 @@ set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5% .\scripts\code.bat %~dp0\..\extensions\vscode-api-tests\testWorkspace --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% .\scripts\code.bat %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --user-data-dir=%VSCODEUSERDATADIR% .\scripts\test-int-mocha.bat -.\scripts\code.bat $ROOT\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% +.\scripts\code.bat $%~dp0\..\extensions\emmet\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disableExtensions --user-data-dir=%VSCODEUSERDATADIR% rmdir /s /q %VSCODEUSERDATADIR% From 8625945db5b5f70e1abce9ae54ac75cdccb739e5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Sep 2017 21:26:14 +0200 Subject: [PATCH 065/145] Create workspace object always and adopt accordingly --- .../electron-browser/mainThreadWorkspace.ts | 5 +- .../browser/actions/workspaceActions.ts | 36 +++++--------- .../browser/parts/titlebar/titlebarPart.ts | 18 ++----- src/vs/workbench/common/resources.ts | 20 ++++---- src/vs/workbench/electron-browser/main.ts | 17 +++---- src/vs/workbench/electron-browser/window.ts | 7 +-- .../debugConfigurationManager.ts | 4 +- .../files/browser/views/explorerViewer.ts | 2 +- .../preferences/browser/preferencesEditor.ts | 12 ++--- .../relauncher.contribution.ts | 12 ++--- .../parts/search/browser/openFileHandler.ts | 6 +-- .../parts/search/browser/searchViewlet.ts | 6 +-- .../configuration/node/configuration.ts | 40 ++++++++-------- .../node/configurationEditingService.ts | 6 +-- .../node/configurationEditingService.test.ts | 47 ++++++++++--------- .../files/electron-browser/fileService.ts | 10 ++-- .../services/files/node/fileService.ts | 6 +-- .../telemetry/common/workspaceStats.ts | 3 +- .../textfile/common/textFileEditorModel.ts | 11 ++--- .../workspace/node/workspaceEditingService.ts | 3 +- 20 files changed, 116 insertions(+), 155 deletions(-) diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index 1f39e8c702c..d58ce7c1744 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -59,11 +59,10 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { // --- search --- $startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable { - if (this._contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + const workspace = this._contextService.getWorkspace(); + if (!workspace.roots.length) { return undefined; } - - const workspace = this._contextService.getWorkspace(); const query: ISearchQuery = { folderQueries: workspace.roots.map(root => ({ folder: root })), type: QueryType.File, diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 57a029520dc..ee384bf7d00 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -75,11 +75,9 @@ export abstract class BaseWorkspacesAction extends Action { protected pickFolders(buttonLabel: string, title: string): string[] { let defaultPath: string; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - const workspace = this.contextService.getWorkspace(); - if (workspace.roots.length > 0) { - defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default - } + const workspace = this.contextService.getWorkspace(); + if (workspace.roots.length > 0) { + defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default } return this.windowService.showOpenDialog({ @@ -110,23 +108,16 @@ export class AddRootFolderAction extends BaseWorkspacesAction { } public run(): TPromise { - switch (this.contextService.getWorkbenchState()) { - - case WorkbenchState.EMPTY: - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, []).run(); - - case WorkbenchState.FOLDER: - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); - - case WorkbenchState.WORKSPACE: - const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); - if (!folders || !folders.length) { - return TPromise.as(null); - } - return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { - return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); - }); + if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + const folders = super.pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace")); + if (!folders || !folders.length) { + return TPromise.as(null); + } + return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { + return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); + }); } + return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); } } @@ -277,8 +268,7 @@ export class OpenWorkspaceConfigFileAction extends Action { ) { super(id, label); - const workspace = this.workspaceContextService.getWorkspace(); - this.enabled = workspace && !!workspace.configuration; + this.enabled = !!this.workspaceContextService.getWorkspace().configuration; } public run(): TPromise { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index cf0c71ace23..ab03feddd0b 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -192,27 +192,17 @@ export class TitlebarPart extends Part implements ITitleService { const input = this.editorService.getActiveEditorInput(); const workspace = this.contextService.getWorkspace(); - // root resource is either workspace configuration file or the first root - let root: URI = workspace ? workspace.configuration || workspace.roots[0] : null; - // Compute folder resource // Single Root Workspace: always the root single workspace in this case - // Multi Root Workspace: root folder of the currently active file if any - let folder: URI; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - if (workspace.roots.length === 1) { - folder = workspace.roots[0]; - } else { - folder = this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); - } - } + // Otherwise: root folder of the currently active file if any + let folder: URI = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.roots[0] : this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); // Variables const activeEditorShort = input ? input.getTitle(Verbosity.SHORT) : ''; const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; - const rootName = workspace ? workspace.name : ''; - const rootPath = root ? labels.getPathLabel(root, void 0, this.environmentService) : ''; + const rootName = workspace.name; + const rootPath = labels.getPathLabel(workspace.configuration || workspace.roots[0], void 0, this.environmentService) || ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 3bf29ca9d9b..7ee3341fcac 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri'; import objects = require('vs/base/common/objects'); import paths = require('vs/base/common/paths'); -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import Event, { Emitter } from 'vs/base/common/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -106,17 +106,15 @@ export class ResourceGlobMatcher { let changed = false; // Add excludes per workspaces that got added - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - this.contextService.getWorkspace().roots.forEach(root => { - const rootExcludes = this.globFn(root); - if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { - changed = true; + this.contextService.getWorkspace().roots.forEach(root => { + const rootExcludes = this.globFn(root); + if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { + changed = true; - this.mapRootToParsedExpression.set(root.toString(), this.parseFn(rootExcludes)); - this.mapRootToExpressionConfig.set(root.toString(), objects.clone(rootExcludes)); - } - }); - } + this.mapRootToParsedExpression.set(root.toString(), this.parseFn(rootExcludes)); + this.mapRootToExpressionConfig.set(root.toString(), objects.clone(rootExcludes)); + } + }); // Remove excludes per workspace no longer present this.mapRootToExpressionConfig.forEach((value, root) => { diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index f48b79e1522..7d00adf6ec4 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -22,7 +22,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { realpath } from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import path = require('path'); import gracefulFs = require('graceful-fs'); import { IInitData } from 'vs/workbench/services/timer/common/timerService'; import { TimerService } from 'vs/workbench/services/timer/node/timerService'; @@ -80,7 +79,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService, mainServices.get(IWorkspacesService)).then(workspaceService => { const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); - const storageService = createStorageService(configuration, workspaceService, environmentService); + const storageService = createStorageService(workspaceService, environmentService); timerService.beforeDOMContentLoaded = Date.now(); @@ -116,10 +115,10 @@ function createAndInitializeWorkspaceService(configuration: IWindowConfiguration if (configuration.workspace || configuration.folderPath) { workspaceService = new WorkspaceServiceImpl(configuration.workspace || configuration.folderPath, environmentService, workspacesService); } else { - workspaceService = new EmptyWorkspaceServiceImpl(environmentService); + workspaceService = new EmptyWorkspaceServiceImpl(configuration, environmentService); } - return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(environmentService)); + return workspaceService.initialize().then(() => workspaceService, error => new EmptyWorkspaceServiceImpl(configuration, environmentService)); }); } @@ -147,8 +146,7 @@ function validateWorkspacePath(configuration: IWindowConfiguration): TPromiseworkspaceService.getWorkspace(); +function createStorageService(workspaceService: IWorkspaceContextService, environmentService: IEnvironmentService): IStorageService { let workspaceId: string; let secondaryWorkspaceId: number; @@ -157,12 +155,13 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // in multi root workspace mode we use the provided ID as key for workspace storage case WorkbenchState.WORKSPACE: - workspaceId = uri.from({ path: workspace.id, scheme: 'root' }).toString(); + workspaceId = uri.from({ path: workspaceService.getWorkspace().id, scheme: 'root' }).toString(); break; // in single folder mode we use the path of the opened folder as key for workspace storage // the ctime is used as secondary workspace id to clean up stale UI state if necessary case WorkbenchState.FOLDER: + const workspace: Workspace = workspaceService.getWorkspace(); workspaceId = workspace.roots[0].toString(); secondaryWorkspaceId = workspace.ctime; break; @@ -174,9 +173,7 @@ function createStorageService(configuration: IWindowConfiguration, workspaceServ // We use basename() to produce a short identifier, we do not need the full path. We use a custom // scheme so that we can later distinguish these identifiers from the workspace one. case WorkbenchState.EMPTY: - if (configuration.backupPath) { - workspaceId = uri.from({ path: path.basename(configuration.backupPath), scheme: 'empty' }).toString(); - } + workspaceId = workspaceService.getWorkspace().id; break; } diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 40b88cbed2c..9940e015191 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -294,12 +294,7 @@ export class ElectronWindow extends Themable { // Single folder or no workspace: create workspace and open else { - const workspaceFolders: URI[] = []; - - // Folder of workspace is the first of multi root workspace, so add it - if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { - workspaceFolders.push(...this.contextService.getWorkspace().roots); - } + const workspaceFolders: URI[] = [...this.contextService.getWorkspace().roots]; // Fill in remaining ones from request workspaceFolders.push(...request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath))); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 6de54d487cc..0fa50d596b8 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -26,7 +26,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IFileService } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, DEBUG_SCHEME, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug'; @@ -353,7 +353,7 @@ export class ConfigurationManager implements IConfigurationManager { } private initLaunches(): void { - this.launches = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : []; + this.launches = this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)); if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 02f40b0c980..5f07e5d0f04 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -838,7 +838,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(true) : DRAG_OVER_ACCEPT_BUBBLE_DOWN(true); } - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { + if (this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_UP_COPY : DRAG_OVER_ACCEPT_BUBBLE_UP; } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index d0b1b0e5e16..d0872cca42f 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -56,7 +56,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { attachStylerCallback } from 'vs/platform/theme/common/styler'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import Event, { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -886,12 +886,10 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return true; } - if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - for (const root of this.workspaceContextService.getWorkspace().roots) { - const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); - if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { - return true; - } + for (const root of this.workspaceContextService.getWorkspace().roots) { + const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); + if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { + return true; } } diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index ba472378c0e..eaa5f82e0e7 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -14,7 +14,7 @@ import { IWindowsService, IWindowService, IWindowsConfiguration } from 'vs/platf import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; interface IConfiguration extends IWindowsConfiguration { @@ -43,13 +43,9 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IWorkspaceContextService private contextService: IWorkspaceContextService, @IExtensionService private extensionService: IExtensionService ) { - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - const workspace = this.contextService.getWorkspace(); - this.rootCount = workspace.roots.length; - this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; - } else { - this.rootCount = 0; - } + const workspace = this.contextService.getWorkspace(); + this.rootCount = workspace.roots.length; + this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; this.onConfigurationChange(configurationService.getConfiguration(), false); diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index 09f7ea977af..e25d03cd56d 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -28,7 +28,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IQueryOptions, ISearchService, ISearchStats, ISearchQuery } from 'vs/platform/search/common/search'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IRange } from 'vs/editor/common/core/range'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/parts/search/common/search'; @@ -164,7 +164,7 @@ export class OpenFileHandler extends QuickOpenHandler { iconClass = 'file'; // only use a generic file icon if we are forced to use an icon and have no icon theme set otherwise } - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; return this.searchService.search(this.queryBuilder.file(folderResources, query)).then((complete) => { const results: QuickOpenEntry[] = []; for (let i = 0; i < complete.results.length; i++) { @@ -199,7 +199,7 @@ export class OpenFileHandler extends QuickOpenHandler { useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; const query = this.queryBuilder.file(folderResources, options); return query; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index c1e493bb0b2..27a1845e66c 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -870,8 +870,8 @@ export class SearchViewlet extends Viewlet { public searchInFolder(resource: URI): void { let folderPath = null; - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && resource) { - const workspace = this.contextService.getWorkspace(); + const workspace = this.contextService.getWorkspace(); + if (resource) { if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { // Show relative path from the root for single-root mode folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); @@ -960,7 +960,7 @@ export class SearchViewlet extends Viewlet { excludePattern, includePattern }; - const folderResources = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots : []; + const folderResources = this.contextService.getWorkspace().roots; const onQueryValidationError = (err: Error) => { this.searchWidget.searchInput.showMessage({ content: err.message, type: MessageType.ERROR }); diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 599deb6e35c..7e811f487fc 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -34,6 +34,7 @@ import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/platform/exten import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope, schemaId } from 'vs/platform/configuration/common/configurationRegistry'; import { createHash } from 'crypto'; import { getWorkspaceLabel, IWorkspacesService, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IStoredWorkspaceFolder, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; interface IStat { resource: URI; @@ -199,21 +200,22 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public getWorkbenchState(): WorkbenchState { - if (this.workspace) { - if (this.workspace.configuration) { - return WorkbenchState.WORKSPACE; - } + // Workspace has configuration file + if (this.workspace.configuration) { + return WorkbenchState.WORKSPACE; + } + + // Folder has single root + if (this.workspace.roots.length === 1) { return WorkbenchState.FOLDER; } + + // Empty return WorkbenchState.EMPTY; } public getRoot(resource: URI): URI { - return this.workspace ? this.workspace.getRoot(resource) : null; - } - - private get workspaceUri(): URI { - return this.workspace ? this.workspace.roots[0] : null; + return this.workspace.getRoot(resource); } public isInsideWorkspace(resource: URI): boolean { @@ -221,19 +223,17 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { - if (!this.workspace) { - return false; + switch (this.getWorkbenchState()) { + case WorkbenchState.FOLDER: + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + case WorkbenchState.WORKSPACE: + return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; } - - if (this.workspace.configuration) { - return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; - } - - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + return false; } public toResource(workspaceRelativePath: string): URI { - if (this.workspace && this.workspace.roots.length) { + if (this.workspace.roots.length) { return URI.file(paths.join(this.workspace.roots[0].fsPath, workspaceRelativePath)); } return null; @@ -312,8 +312,10 @@ export class EmptyWorkspaceServiceImpl extends WorkspaceService { private baseConfigurationService: GlobalConfigurationService; - constructor(environmentService: IEnvironmentService) { + constructor(configuration: IWindowConfiguration, environmentService: IEnvironmentService) { super(); + let id = configuration.backupPath ? URI.from({ path: paths.basename(configuration.backupPath), scheme: 'empty' }).toString() : ''; + this.workspace = new Workspace(id, '', []); this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); this.resetCaches(); diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index 3e974c0487f..c08df2e04c3 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -296,14 +296,14 @@ export class ConfigurationEditingService implements IConfigurationEditingService // Check for prefix if (config.key === key) { - const jsonPath = workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key] : []; + const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key] : []; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, isWorkspaceStandalone: true }; } // Check for prefix. const keyPrefix = `${key}.`; if (config.key.indexOf(keyPrefix) === 0) { - const jsonPath = workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; + const jsonPath = workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)]; return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, isWorkspaceStandalone: true }; } } @@ -316,7 +316,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService } const resource = this.getConfigurationFileResource(target, WORKSPACE_CONFIG_DEFAULT_PATH, overrides.resource); - if (workspace && workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) { + if (workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath) { jsonPath = ['settings', ...jsonPath]; } return { key, jsonPath, value: config.value, resource }; diff --git a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts index d6bf47c961c..358c6d64603 100644 --- a/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/node/configurationEditingService.test.ts @@ -45,6 +45,7 @@ import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; import { IChoiceService, IMessageService } from 'vs/platform/message/common/message'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; class SettingsTestEnvironmentService extends EnvironmentService { @@ -117,30 +118,32 @@ suite('ConfigurationEditingService', () => { const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile); instantiationService.stub(IEnvironmentService, environmentService); const workspacesService = instantiationService.stub(IWorkspacesService, {}); - const workspaceService = noWorkspace ? new EmptyWorkspaceServiceImpl(environmentService) : new WorkspaceServiceImpl(workspaceDir, environmentService, workspacesService); + const workspaceService = noWorkspace ? new EmptyWorkspaceServiceImpl({}, environmentService) : new WorkspaceServiceImpl(workspaceDir, environmentService, workspacesService); instantiationService.stub(IWorkspaceContextService, workspaceService); - instantiationService.stub(IConfigurationService, workspaceService); - instantiationService.stub(ILifecycleService, new TestLifecycleService()); - instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); - instantiationService.stub(ITelemetryService, NullTelemetryService); - instantiationService.stub(IModeService, ModeServiceImpl); - instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); - instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true })); - instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); - instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); - instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); - instantiationService.stub(IBackupFileService, new TestBackupFileService()); - choiceService = instantiationService.stub(IChoiceService, { - choose: (severity, message, options, cancelId): TPromise => { - return TPromise.as(cancelId); - } - }); - instantiationService.stub(IMessageService, { - show: (severity, message, options, cancelId): void => { } - }); + return workspaceService.initialize().then(() => { + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(ILifecycleService, new TestLifecycleService()); + instantiationService.stub(IEditorGroupService, new TestEditorGroupService()); + instantiationService.stub(ITelemetryService, NullTelemetryService); + instantiationService.stub(IModeService, ModeServiceImpl); + instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl)); + instantiationService.stub(IFileService, new FileService(workspaceService, new TestTextResourceConfigurationService(), new TestConfigurationService(), { disableWatcher: true })); + instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + instantiationService.stub(IBackupFileService, new TestBackupFileService()); + choiceService = instantiationService.stub(IChoiceService, { + choose: (severity, message, options, cancelId): TPromise => { + return TPromise.as(cancelId); + } + }); + instantiationService.stub(IMessageService, { + show: (severity, message, options, cancelId): void => { } + }); - testObject = instantiationService.createInstance(ConfigurationEditingService); - return workspaceService.initialize(); + testObject = instantiationService.createInstance(ConfigurationEditingService); + return workspaceService.initialize(); + }); } teardown(() => { diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index d5ce241b833..c6b81d34478 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -15,7 +15,7 @@ import { toResource } from 'vs/workbench/common/editor'; import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { Action } from 'vs/base/common/actions'; import { ResourceMap } from 'vs/base/common/map'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -146,11 +146,9 @@ export class FileService implements IFileService { private getEncodingOverrides(): IEncodingOverride[] { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - this.contextService.getWorkspace().roots.forEach(root => { - encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); - }); - } + this.contextService.getWorkspace().roots.forEach(root => { + encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); + }); return encodingOverride; } diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index a22c3d618cb..59010bd922b 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -25,7 +25,7 @@ import uri from 'vs/base/common/uri'; import nls = require('vs/nls'); import { isWindows, isLinux } from 'vs/base/common/platform'; import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import pfs = require('vs/base/node/pfs'); import encoding = require('vs/base/node/encoding'); @@ -101,7 +101,7 @@ export class FileService implements IFileService { this.toDispose = []; this.options = options || Object.create(null); this.tmpPath = this.options.tmpDir || os.tmpdir(); - this.currentWorkspaceRootsCount = contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? contextService.getWorkspace().roots.length : 0; + this.currentWorkspaceRootsCount = contextService.getWorkspace().roots.length; this._onFileChanges = new Emitter(); this.toDispose.push(this._onFileChanges); @@ -129,7 +129,7 @@ export class FileService implements IFileService { } private onDidChangeWorkspaceRoots(): void { - const newRootCount = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.contextService.getWorkspace().roots.length : 0; + const newRootCount = this.contextService.getWorkspace().roots.length; let restartWorkspaceWatcher = false; if (this.currentWorkspaceRootsCount <= 1 && newRootCount > 1) { diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index 6c2386e8b25..6246daee2b6 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -324,8 +324,7 @@ export class WorkspaceStats { } public reportCloudStats(): void { - const workspace = this.contextService.getWorkspace(); - const uris = workspace && workspace.roots; + const uris = this.contextService.getWorkspace().roots; if (uris && uris.length && this.fileService) { this.reportRemoteDomains(uris); this.reportRemotes(uris); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index e172715a3d6..364f9b8c6dd 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -19,7 +19,7 @@ import diagnostics = require('vs/base/common/diagnostics'); import types = require('vs/base/common/types'); import { IMode } from 'vs/editor/common/modes'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles'; import { EncodingMode } from 'vs/workbench/common/editor'; @@ -745,13 +745,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for workspace settings file - if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY) { - return this.contextService.getWorkspace().roots.some(root => { - return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); - }); - } + return this.contextService.getWorkspace().roots.some(root => { + return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); + }); - return false; } private doTouch(): TPromise { diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index bd896c78398..d851cd92cce 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -53,10 +53,9 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { } private isSupported(): boolean { - const workspace = this.contextService.getWorkspace(); return ( this.environmentService.appQuality !== 'stable' // not yet enabled in stable - && workspace && !!workspace.configuration // we need a workspace configuration file to begin with + && !!this.contextService.getWorkspace().configuration // we need a workspace configuration file to begin with ); } From 20036898cbca1cec2a9157b7ad12d8a2f30f5e44 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 13 Sep 2017 22:03:28 +0200 Subject: [PATCH 066/145] node-debug@1.17.4 --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 8915457164b..bfa2a0bd8a3 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -43,7 +43,7 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.17.3' }, + { name: 'ms-vscode.node-debug', version: '1.17.4' }, { name: 'ms-vscode.node-debug2', version: '1.17.1' } ]; From 0edc09f89e0cee76e53693c227cf2f335139df39 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 13 Sep 2017 14:05:34 -0700 Subject: [PATCH 067/145] Uplevel xterm.js Fixes an exception with selection in the terminal, see sourcelair/xterm.js#989 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 3858934b86c..295d0b2cd71 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "3.0.0", "from": "Tyriar/xterm.js#vscode-release/1.17", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#4483a2faf442101b507d033e4d25d134dddbe2ff" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#28fb0977e904861237ad5d7c0abd8ced9583db7b" }, "yauzl": { "version": "2.8.0", From 3c8aaf1a6ab41fac0b6386ee0818c78bf8067d25 Mon Sep 17 00:00:00 2001 From: Greg Van Liew Date: Wed, 13 Sep 2017 14:36:55 -0700 Subject: [PATCH 068/145] Fix broken API link per vscode-docs PR #1142 --- src/vs/vscode.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 2de5b818653..ac6500b1860 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -4947,7 +4947,7 @@ declare module 'vscode' { /** * An event that is emitted when a [text document](#TextDocument) is changed. This usually happens * when the [contents](#TextDocument.getText) changes but also when other things like the - * [dirty](TextDocument#isDirty)-state changes. + * [dirty](#TextDocument.isDirty)-state changes. */ export const onDidChangeTextDocument: Event; From 2a4cf4f62207bd88b1b7e2bad30521db0def6449 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 13 Sep 2017 14:50:24 -0700 Subject: [PATCH 069/145] Speed up terminal parsing on Windows by minimizing timer restarts Fixes #34328 --- .../electron-browser/windowsShellHelper.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts index 1fbb6bb2cd8..b4a2d55c42a 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/windowsShellHelper.ts @@ -18,6 +18,7 @@ export class WindowsShellHelper { private _onCheckShell: Emitter>; private _isDisposed: boolean; private _currentRequest: TPromise; + private _newLineFeed: boolean; public constructor( private _rootProcessId: number, @@ -44,7 +45,19 @@ export class WindowsShellHelper { }, 50); }); - this._xterm.on('lineFeed', () => this._onCheckShell.fire()); + // We want to fire a new check for the shell on a lineFeed, but only + // when parsing has finished which is indicated by the cursormove event. + // If this is done on every lineFeed, parsing ends up taking + // significantly longer due to resetting timers. Note that this is + // private API. + this._xterm.on('lineFeed', () => this._newLineFeed = true); + this._xterm.on('cursormove', () => { + if (this._newLineFeed) { + this._onCheckShell.fire(); + } + }); + + // Fire a new check for the shell when any key is pressed. this._xterm.on('keypress', () => this._onCheckShell.fire()); } From e6b7eb0f6bc1e0eb3d64c0ab00278c31efcc6032 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 14:51:24 -0700 Subject: [PATCH 070/145] Fix test for undefined deref --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index e1c77e1f78a..b0e220c2bd5 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1686,7 +1686,7 @@ export class EditorOptionsValidator { matchBrackets: _boolean(opts.matchBrackets, defaults.matchBrackets), find: find, colorDecorators: _boolean(opts.colorDecorators, defaults.colorDecorators), - lightbulbEnabled: _boolean(opts.lightbulb.enabled, defaults.lightbulbEnabled) + lightbulbEnabled: _boolean(opts.lightbulb && opts.lightbulb.enabled, defaults.lightbulbEnabled) }; } } From 2859b125c168eb1f281288d95c967db1735c3e6d Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 13 Sep 2017 14:56:18 -0700 Subject: [PATCH 071/145] Fix #34204 - revert problematic brace matching change from language-php --- extensions/php/syntaxes/php.tmLanguage.json | 31 +++++++-------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/extensions/php/syntaxes/php.tmLanguage.json b/extensions/php/syntaxes/php.tmLanguage.json index 0a36eb0b2f5..3f4d3f537f6 100644 --- a/extensions/php/syntaxes/php.tmLanguage.json +++ b/extensions/php/syntaxes/php.tmLanguage.json @@ -1,10 +1,10 @@ { "information_for_contributors": [ - "This file has been converted from https://github.com/atom/language-php/blob/master/grammars/php.cson", + "This file has been converted from https://github.com/roblourens/language-php/blob/revertBraceMatching/grammars/php.cson", "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-php/commit/efab9c83b91c02f04b8cfd0236e0239e14c4af52", + "version": "https://github.com/roblourens/language-php/commit/91d50ab5f871ea2d11b4c511dc0b9a972e4ac5ce", "scopeName": "text.html.php", "name": "PHP", "fileTypes": [ @@ -1428,6 +1428,14 @@ { "include": "#comments" }, + { + "match": "{", + "name": "punctuation.section.scope.begin.php" + }, + { + "match": "}", + "name": "punctuation.section.scope.end.php" + }, { "begin": "(?i)^\\s*(interface)\\s+([a-z_\\x{7f}-\\x{ff}][a-z0-9_\\x{7f}-\\x{ff}]*)\\s*(extends)?\\s*", "beginCaptures": { @@ -2086,25 +2094,6 @@ { "include": "#string-backtick" }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.definition.begin.bracket.curly.php" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.definition.end.bracket.curly.php" - } - }, - "patterns": [ - { - "include": "#language" - } - ] - }, { "begin": "\\[", "beginCaptures": { From 4d26c8a5748b57f9f3fc2562153b4038e34d9928 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 13 Sep 2017 15:08:10 -0700 Subject: [PATCH 072/145] Correctly set terminal columns on layout Fixes #34332 --- .../parts/terminal/electron-browser/terminalConfigHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index d949eaec21d..90ae98f2274 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -74,7 +74,7 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { fontFamily, fontSize, lineHeight, - charWidth: Math.ceil(rect.width), + charWidth: rect.width, charHeight: Math.ceil(rect.height) }; return this._lastFontMeasurement; From 954ee607ba9648dd5e443cbe8067bfd326a14ae8 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Wed, 13 Sep 2017 15:11:52 -0700 Subject: [PATCH 073/145] Remove Azure Deploy experiment --- src/vs/platform/telemetry/common/experiments.ts | 4 +--- .../welcome/page/electron-browser/vs_code_welcome_page.ts | 1 - .../parts/welcome/page/electron-browser/welcomePage.ts | 6 ------ .../test/electron-browser/quickopen.perf.integrationTest.ts | 1 - 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/vs/platform/telemetry/common/experiments.ts b/src/vs/platform/telemetry/common/experiments.ts index 4a42a898e5e..6911c881760 100644 --- a/src/vs/platform/telemetry/common/experiments.ts +++ b/src/vs/platform/telemetry/common/experiments.ts @@ -10,7 +10,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' export interface IExperiments { ripgrepQuickSearch: boolean; - deployToAzureQuickLink: boolean; } export const IExperimentService = createDecorator('experimentService'); @@ -60,12 +59,11 @@ function applyOverrides(experiments: IExperiments, configurationService: IConfig function splitExperimentsRandomness(storageService: IStorageService): IExperiments { const random1 = getExperimentsRandomness(storageService); const [random2, ripgrepQuickSearch] = splitRandom(random1); - const [/* random3 */, deployToAzureQuickLink] = splitRandom(random2); + const [/* random3 */, /* deployToAzureQuickLink */] = splitRandom(random2); // const [random4, /* mergeQuickLinks */] = splitRandom(random3); // const [random5, /* enableWelcomePage */] = splitRandom(random4); return { ripgrepQuickSearch, - deployToAzureQuickLink }; } diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts index 1f09a886909..7672c53a798 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts @@ -70,7 +70,6 @@ export default () => `
  • -
diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index 452f9863d31..1e735249d6f 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -317,12 +317,6 @@ class WelcomePage { }; })); - if (this.experimentService.getExperiments().deployToAzureQuickLink) { - container.querySelector('.showInterfaceOverview').remove(); - } else { - container.querySelector('.deployToAzure').remove(); - } - if (product.quality !== 'stable') { container.querySelector('.stable-only').remove(); } else { diff --git a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts index d967748494d..fbe1e28e3b1 100644 --- a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts @@ -188,7 +188,6 @@ class TestExperimentService implements IExperimentService { getExperiments(): IExperiments { return { ripgrepQuickSearch: true, - deployToAzureQuickLink: false }; } } From 3cfc1b6e55d5e7558716fe90b5213bf1e5353c75 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 17:16:15 -0700 Subject: [PATCH 074/145] Make sure we use old pre-wrap settings for non markdown docs --- .../editor/contrib/parameterHints/browser/parameterHints.css | 5 +++++ .../contrib/parameterHints/browser/parameterHintsWidget.ts | 2 ++ src/vs/editor/contrib/suggest/browser/media/suggest.css | 5 +++++ src/vs/editor/contrib/suggest/browser/suggestWidget.ts | 2 ++ 4 files changed, 14 insertions(+) diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHints.css b/src/vs/editor/contrib/parameterHints/browser/parameterHints.css index db3ff8001ae..812bff41e87 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHints.css +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHints.css @@ -45,6 +45,11 @@ .monaco-editor .parameter-hints-widget .docs { padding: 0 10px 0 5px; + white-space: pre-wrap; +} + +.monaco-editor .parameter-hints-widget .docs.markdown-docs { + white-space: initial; } .monaco-editor .parameter-hints-widget .docs .code { diff --git a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts index bacb7f633f8..547ca4d3757 100644 --- a/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.ts @@ -336,8 +336,10 @@ export class ParameterHintsWidget implements IContentWidget, IDisposable { if (activeParameter && activeParameter.documentation) { const documentation = $('span.documentation'); if (typeof activeParameter.documentation === 'string') { + dom.removeClass(this.docs, 'markdown-docs'); documentation.textContent = activeParameter.documentation; } else { + dom.addClass(this.docs, 'markdown-docs'); documentation.appendChild(this.markdownRenderer.render(activeParameter.documentation)); } dom.append(this.docs, $('p', null, documentation)); diff --git a/src/vs/editor/contrib/suggest/browser/media/suggest.css b/src/vs/editor/contrib/suggest/browser/media/suggest.css index 3eee4201f43..1890d7da019 100644 --- a/src/vs/editor/contrib/suggest/browser/media/suggest.css +++ b/src/vs/editor/contrib/suggest/browser/media/suggest.css @@ -228,6 +228,11 @@ .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs { margin: 0; padding: 4px 5px; + white-space: pre-wrap; +} + +.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs.marked-docs { + white-space: initial; } .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs .code { diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index 63a2a0e9e3a..c81691c39b6 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -249,8 +249,10 @@ class SuggestionDetails { } removeClass(this.el, 'no-docs'); if (typeof item.suggestion.documentation === 'string') { + removeClass(this.docs, 'marked-docs'); this.docs.textContent = item.suggestion.documentation; } else { + addClass(this.docs, 'marked-docs'); this.docs.innerHTML = this.markdownRenderer.render(item.suggestion.documentation).innerHTML; } From 68040fa300a61f047f472ad435ed30a1ac55a7cf Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Wed, 13 Sep 2017 17:18:13 -0700 Subject: [PATCH 075/145] Use 1.1.8 version of vscode emmet helper Fixes #34216 Fixes #33898 --- extensions/emmet/npm-shrinkwrap.json | 6 +++--- extensions/emmet/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/emmet/npm-shrinkwrap.json b/extensions/emmet/npm-shrinkwrap.json index 28091803b29..e91e4e9c33b 100644 --- a/extensions/emmet/npm-shrinkwrap.json +++ b/extensions/emmet/npm-shrinkwrap.json @@ -38,9 +38,9 @@ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz" }, "vscode-emmet-helper": { - "version": "1.1.7", - "from": "vscode-emmet-helper@>=1.0.17 <2.0.0", - "resolved": "https://registry.npmjs.org/vscode-emmet-helper/-/vscode-emmet-helper-1.1.7.tgz" + "version": "1.1.8", + "from": "vscode-emmet-helper@>=1.0.8 <2.0.0", + "resolved": "https://registry.npmjs.org/vscode-emmet-helper/-/vscode-emmet-helper-1.1.8.tgz" }, "vscode-languageserver-types": { "version": "3.3.0", diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 31de43eb8bf..7e6d7155d31 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -265,7 +265,7 @@ "@emmetio/html-matcher": "^0.3.1", "@emmetio/css-parser": "ramya-rao-a/css-parser#vscode", "@emmetio/math-expression": "^0.1.1", - "vscode-emmet-helper": "^1.1.7", + "vscode-emmet-helper": "^1.1.8", "vscode-languageserver-types": "^3.0.3", "image-size": "^0.5.2", "vscode-nls": "2.0.2" From 2dc19b668f81a63b2302215ad84c163336dd0c03 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 22:55:07 -0700 Subject: [PATCH 076/145] Use consistent name for marking markdown docs --- src/vs/editor/contrib/suggest/browser/media/suggest.css | 2 +- src/vs/editor/contrib/suggest/browser/suggestWidget.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/editor/contrib/suggest/browser/media/suggest.css b/src/vs/editor/contrib/suggest/browser/media/suggest.css index 1890d7da019..2cd4a1b4896 100644 --- a/src/vs/editor/contrib/suggest/browser/media/suggest.css +++ b/src/vs/editor/contrib/suggest/browser/media/suggest.css @@ -231,7 +231,7 @@ white-space: pre-wrap; } -.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs.marked-docs { +.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs.markdown-docs { white-space: initial; } diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index c81691c39b6..472fce09a86 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -249,10 +249,10 @@ class SuggestionDetails { } removeClass(this.el, 'no-docs'); if (typeof item.suggestion.documentation === 'string') { - removeClass(this.docs, 'marked-docs'); + removeClass(this.docs, 'markdown-docs'); this.docs.textContent = item.suggestion.documentation; } else { - addClass(this.docs, 'marked-docs'); + addClass(this.docs, 'markdown-docs'); this.docs.innerHTML = this.markdownRenderer.render(item.suggestion.documentation).innerHTML; } From 0347eda9312bae709e8008d858a86900e82c5ffa Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Sep 2017 23:00:51 -0700 Subject: [PATCH 077/145] Update TS/JS grammars --- .../syntaxes/JavaScript.tmLanguage.json | 71 +++++++--- .../colorize-results/issue-28354_php.json | 4 +- .../php/test/colorize-results/test_php.json | 28 ++-- .../syntaxes/TypeScript.tmLanguage.json | 73 +++++++--- .../syntaxes/TypeScriptReact.tmLanguage.json | 71 +++++++--- .../colorize-results/test-issue5431_ts.json | 12 +- .../colorize-results/test-strings_ts.json | 130 +++++++++--------- 7 files changed, 244 insertions(+), 145 deletions(-) diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json index 6a9a32ac03c..de12bfe729c 100644 --- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json +++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/648a036db2bad78ee93463269ec49ed91ee5aa91", + "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/30d95ebb561fc57e784b43d08f0a6f46ad0c3e5d", "name": "JavaScript (with React support)", "scopeName": "source.js", "fileTypes": [ @@ -94,6 +94,29 @@ { "include": "#comment" }, + { + "begin": "(,)\\s*(?!\\S)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.comma.js" + } + }, + "end": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "beginCaptures": { "1": { "name": "meta.definition.variable.js entity.name.function.js" @@ -727,7 +750,7 @@ }, "import-declaration": { "name": "meta.import.js", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" }, { "name": "meta.definition.property.js variable.object.property.js", @@ -1572,7 +1595,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "captures": { "1": { "name": "storage.modifier.js" @@ -2410,7 +2433,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.js" @@ -2485,13 +2508,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.js", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2552,7 +2575,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.js" @@ -2697,7 +2720,7 @@ }, { "name": "meta.object.member.js", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.js" @@ -2714,8 +2737,7 @@ "0": { "name": "meta.object-literal.key.js" } - }, - "end": "(?=,|\\})" + } }, { "name": "meta.object.member.js", @@ -2741,6 +2763,16 @@ } } }, + { + "name": "meta.object.member.js", + "begin": "(?=[_$[:alpha:]][_$[:alnum:]]*\\s*=)", + "end": "(?=,|\\}|$)", + "patterns": [ + { + "include": "#expression" + } + ] + }, { "include": "#object-member-body" }, @@ -2815,7 +2847,7 @@ "name": "keyword.control.as.js" } }, - "end": "(?=$|^|[;,:})\\]])", + "end": "(?=$|^|[;,:})\\]]|((? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.js" @@ -3053,7 +3085,7 @@ "patterns": [ { "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.js" @@ -3076,7 +3108,7 @@ }, { "name": "string.regexp.js", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "beginCaptures": { "1": { "name": "meta.definition.variable.ts entity.name.function.ts" @@ -721,7 +744,7 @@ }, "import-declaration": { "name": "meta.import.ts", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" }, { "name": "meta.definition.property.ts variable.object.property.ts", @@ -1566,7 +1589,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "captures": { "1": { "name": "storage.modifier.ts" @@ -2404,7 +2427,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -2479,13 +2502,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.ts", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2546,7 +2569,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.ts" @@ -2625,7 +2648,7 @@ "patterns": [ { "name": "cast.expr.ts", - "begin": "(?:(?<=return|throw|yield|await|default|[=(,:>*?]))\\s*(<)(?!+*?]))\\s*(<)(?!)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.ts" @@ -2745,8 +2768,7 @@ "0": { "name": "meta.object-literal.key.ts" } - }, - "end": "(?=,|\\})" + } }, { "name": "meta.object.member.ts", @@ -2772,6 +2794,16 @@ } } }, + { + "name": "meta.object.member.ts", + "begin": "(?=[_$[:alpha:]][_$[:alnum:]]*\\s*=)", + "end": "(?=,|\\}|$)", + "patterns": [ + { + "include": "#expression" + } + ] + }, { "include": "#object-member-body" }, @@ -2846,7 +2878,7 @@ "name": "keyword.control.as.ts" } }, - "end": "(?=$|^|[;,:})\\]])", + "end": "(?=$|^|[;,:})\\]]|((? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.ts" @@ -3084,7 +3116,7 @@ "patterns": [ { "name": "string.regexp.ts", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.ts" @@ -3107,7 +3139,7 @@ }, { "name": "string.regexp.ts", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "begin": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "beginCaptures": { "1": { "name": "meta.definition.variable.tsx entity.name.function.tsx" @@ -724,7 +747,7 @@ }, "import-declaration": { "name": "meta.import.tsx", - "begin": "(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" + "match": "(?x)([_$[:alpha:]][_$[:alnum:]]*)(?=(\\?\\s*)?\\s*\n (=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)" }, { "name": "meta.definition.property.tsx variable.object.property.tsx", @@ -1569,7 +1592,7 @@ } }, { - "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", + "match": "(?x)(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n )) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n ))\n ))\n)", "captures": { "1": { "name": "storage.modifier.tsx" @@ -2407,7 +2430,7 @@ } }, { - "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "match": "(?x) (\\.) \\s* (?:\n (ATTRIBUTE_NODE|CDATA_SECTION_NODE|COMMENT_NODE|DOCUMENT_FRAGMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE\n |DOMSTRING_SIZE_ERR|ELEMENT_NODE|ENTITY_NODE|ENTITY_REFERENCE_NODE|HIERARCHY_REQUEST_ERR|INDEX_SIZE_ERR\n |INUSE_ATTRIBUTE_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR\n |NOT_SUPPORTED_ERR|NOTATION_NODE|PROCESSING_INSTRUCTION_NODE|TEXT_NODE|WRONG_DOCUMENT_ERR)\n |\n (_content|[xyz]|abbr|above|accept|acceptCharset|accessKey|action|align|[av]Link(?:color)?|all|alt|anchors|appCodeName\n |appCore|applets|appMinorVersion|appName|appVersion|archive|areas|arguments|attributes|availHeight|availLeft|availTop\n |availWidth|axis|background|backgroundColor|backgroundImage|below|bgColor|body|border|borderBottomWidth|borderColor\n |borderLeftWidth|borderRightWidth|borderStyle|borderTopWidth|borderWidth|bottom|bufferDepth|callee|caller|caption\n |cellPadding|cells|cellSpacing|ch|characterSet|charset|checked|childNodes|chOff|cite|classes|className|clear\n |clientInformation|clip|clipBoardData|closed|code|codeBase|codeType|color|colorDepth|cols|colSpan|compact|complete\n |components|content|controllers|cookie|cookieEnabled|cords|cpuClass|crypto|current|data|dateTime|declare|defaultCharset\n |defaultChecked|defaultSelected|defaultStatus|defaultValue|defaultView|defer|description|dialogArguments|dialogHeight\n |dialogLeft|dialogTop|dialogWidth|dir|directories|disabled|display|docmain|doctype|documentElement|elements|embeds\n |enabledPlugin|encoding|enctype|entities|event|expando|external|face|fgColor|filename|firstChild|fontFamily|fontSize\n |fontWeight|form|formName|forms|frame|frameBorder|frameElement|frames|hasFocus|hash|headers|height|history|host\n |hostname|href|hreflang|hspace|htmlFor|httpEquiv|id|ids|ignoreCase|images|implementation|index|innerHeight|innerWidth\n |input|isMap|label|lang|language|lastChild|lastIndex|lastMatch|lastModified|lastParen|layer[sXY]|left|leftContext\n |lineHeight|link|linkColor|links|listStyleType|localName|location|locationbar|longDesc|lowsrc|lowSrc|marginBottom\n |marginHeight|marginLeft|marginRight|marginTop|marginWidth|maxLength|media|menubar|method|mimeTypes|multiline|multiple\n |name|nameProp|namespaces|namespaceURI|next|nextSibling|nodeName|nodeType|nodeValue|noHref|noResize|noShade|notationName\n |notations|noWrap|object|offscreenBuffering|onLine|onreadystatechange|opener|opsProfile|options|oscpu|outerHeight\n |outerWidth|ownerDocument|paddingBottom|paddingLeft|paddingRight|paddingTop|page[XY]|page[XY]Offset|parent|parentLayer\n |parentNode|parentWindow|pathname|personalbar|pixelDepth|pkcs11|platform|plugins|port|prefix|previous|previousDibling\n |product|productSub|profile|profileend|prompt|prompter|protocol|publicId|readOnly|readyState|referrer|rel|responseText\n |responseXML|rev|right|rightContext|rowIndex|rows|rowSpan|rules|scheme|scope|screen[XY]|screenLeft|screenTop|scripts\n |scrollbars|scrolling|sectionRowIndex|security|securityPolicy|selected|selectedIndex|selection|self|shape|siblingAbove\n |siblingBelow|size|source|specified|standby|start|status|statusbar|statusText|style|styleSheets|suffixes|summary\n |systemId|systemLanguage|tagName|tags|target|tBodies|text|textAlign|textDecoration|textIndent|textTransform|tFoot|tHead\n |title|toolbar|top|type|undefined|uniqueID|updateInterval|URL|URLUnencoded|useMap|userAgent|userLanguage|userProfile\n |vAlign|value|valueType|vendor|vendorSub|version|visibility|vspace|whiteSpace|width|X[MS]LDocument|zIndex))\\b(?!\\$|\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -2482,13 +2505,13 @@ ] }, "function-call": { - "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "name": "meta.function-call.tsx", "begin": "(?=(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*))", - "end": "(?=\\s*(<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\()", + "end": "(?=\\s*(<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\()", "patterns": [ { "include": "#literal" @@ -2549,7 +2572,7 @@ "include": "#object-identifiers" }, { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", + "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n))", "captures": { "1": { "name": "punctuation.accessor.tsx" @@ -2694,7 +2717,7 @@ }, { "name": "meta.object.member.tsx", - "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", + "match": "(?x)(?:([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=:\\s*(\n ((async\\s+)?(\n (function\\s*[(<*]) |\n (function\\s+) |\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)\n )) |\n ((async\\s*)?(\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)\n ))\n)))", "captures": { "0": { "name": "meta.object-literal.key.tsx" @@ -2711,8 +2734,7 @@ "0": { "name": "meta.object-literal.key.tsx" } - }, - "end": "(?=,|\\})" + } }, { "name": "meta.object.member.tsx", @@ -2738,6 +2760,16 @@ } } }, + { + "name": "meta.object.member.tsx", + "begin": "(?=[_$[:alpha:]][_$[:alnum:]]*\\s*=)", + "end": "(?=,|\\}|$)", + "patterns": [ + { + "include": "#expression" + } + ] + }, { "include": "#object-member-body" }, @@ -2812,7 +2844,7 @@ "name": "keyword.control.as.tsx" } }, - "end": "(?=$|^|[;,:})\\]])", + "end": "(?=$|^|[;,:})\\]]|((? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>=]|=[^<]|\\<([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", + "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ((\\.\\.\\.\\s*)?[_$[:alpha:]][_$[:alnum:]]*\\s*:) # [(]param: | [(]...param:\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<\\s*[_$[:alpha:]\\{\\(]([^<>=]|=[^<]|\\<\\s*[_$[:alpha:]\\{\\(]([^=<>]|=[^<])+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", "beginCaptures": { "1": { "name": "storage.modifier.async.tsx" @@ -3050,7 +3082,7 @@ "patterns": [ { "name": "string.regexp.tsx", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", + "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/(?![\\/*])[gimuy]*(?!\\s*[a-zA-Z0-9_$]))", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.tsx" @@ -3073,7 +3105,7 @@ }, { "name": "string.regexp.tsx", - "begin": "(? Date: Wed, 13 Sep 2017 23:39:30 -0700 Subject: [PATCH 078/145] Fix compile error --- extensions/emmet/src/defaultCompletionProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index 5c78aea06a0..f01fb6db568 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -55,7 +55,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi return; } - let result: vscode.CompletionList = doComplete(document, position, syntax, getEmmetConfiguration(syntax)); + let result = doComplete(document, position, syntax, getEmmetConfiguration(syntax)); let newItems: vscode.CompletionItem[] = []; if (result && result.items) { result.items.forEach(item => { From bc056cb92c19ca1c7ec413ea60f638a79ce42c5d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 09:59:52 +0200 Subject: [PATCH 079/145] fix some URI.file (#34296) --- .../workbench/parts/files/browser/fileActions.ts | 14 ++++++-------- .../files/common/editors/fileEditorTracker.ts | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 9a2ab3ea142..e859b6521af 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -296,22 +296,20 @@ class RenameFileAction extends BaseRenameAction { } public runAction(newName: string): TPromise { - const dirty = this.textFileService.getDirty().filter(d => paths.isEqualOrParent(d.fsPath, this.element.resource.fsPath, !isLinux /* ignorecase */)); const dirtyRenamed: URI[] = []; return TPromise.join(dirty.map(d => { - const targetPath = paths.join(this.element.parent.resource.fsPath, newName); let renamed: URI; // If the dirty file itself got moved, just reparent it to the target folder if (paths.isEqual(this.element.resource.fsPath, d.fsPath)) { - renamed = URI.file(targetPath); + renamed = this.element.parent.resource.with({ path: targetPath }); } // Otherwise, a parent of the dirty resource got moved, so we have to reparent more complicated. Example: else { - renamed = URI.file(paths.join(targetPath, d.fsPath.substr(this.element.resource.fsPath.length + 1))); + renamed = this.element.parent.resource.with({ path: paths.join(targetPath, d.fsPath.substr(this.element.resource.fsPath.length + 1)) }); } dirtyRenamed.push(renamed); @@ -589,7 +587,7 @@ export class CreateFileAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFile(URI.file(paths.join(this.element.parent.resource.fsPath, fileName))).then(stat => { + return this.fileService.createFile(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.fsPath, fileName) })).then(stat => { return this.editorService.openEditor({ resource: stat.resource, options: { pinned: true } }); }, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); @@ -615,7 +613,7 @@ export class CreateFolderAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFolder(URI.file(paths.join(this.element.parent.resource.fsPath, fileName))).then(null, (error) => { + return this.fileService.createFolder(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.fsPath, fileName) })).then(null, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); }); } @@ -1046,14 +1044,14 @@ export class DuplicateFileAction extends BaseFileAction { private findTarget(): URI { let name = this.element.name; - let candidate = URI.file(paths.join(this.target.resource.fsPath, name)); + let candidate = this.target.resource.with({ path: paths.join(this.target.resource.fsPath, name) }); while (true) { if (!this.element.root.find(candidate)) { break; } name = this.toCopyName(name, this.element.isDirectory); - candidate = URI.file(paths.join(this.target.resource.fsPath, name)); + candidate = this.target.resource.with({ path: paths.join(this.target.resource.fsPath, name) }); } return candidate; diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts index 52124b9fb7e..5de8984ee4f 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts @@ -206,7 +206,7 @@ export class FileEditorTracker implements IWorkbenchContribution { reopenFileResource = newResource; // file got moved } else { const index = indexOf(resource.fsPath, oldResource.fsPath, !isLinux /* ignorecase */); - reopenFileResource = URI.file(paths.join(newResource.fsPath, resource.fsPath.substr(index + oldResource.fsPath.length + 1))); // parent folder got moved + reopenFileResource = newResource.with({ path: paths.join(newResource.fsPath, resource.fsPath.substr(index + oldResource.fsPath.length + 1)) }); // parent folder got moved } // Reopen From aea2c05183181fc67569b066bc7b7981bf5267e0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 14 Sep 2017 01:09:22 -0700 Subject: [PATCH 080/145] Uplevel xterm.js Fixes #34119 --- npm-shrinkwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 295d0b2cd71..57ac074e05f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -574,7 +574,7 @@ "xterm": { "version": "3.0.0", "from": "Tyriar/xterm.js#vscode-release/1.17", - "resolved": "git+https://github.com/Tyriar/xterm.js.git#28fb0977e904861237ad5d7c0abd8ced9583db7b" + "resolved": "git+https://github.com/Tyriar/xterm.js.git#35088059e61ba654ac78df453633c7a9272ed8bd" }, "yauzl": { "version": "2.8.0", From 65fe09e41ae15543b1a3ba7762ea675637450bab Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 10:09:51 +0200 Subject: [PATCH 081/145] do not use fsPath when using URI.with() --- .../workbench/parts/files/browser/fileActions.ts | 14 +++++++------- .../files/common/editors/fileEditorTracker.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index e859b6521af..10caeeb640b 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -299,17 +299,17 @@ class RenameFileAction extends BaseRenameAction { const dirty = this.textFileService.getDirty().filter(d => paths.isEqualOrParent(d.fsPath, this.element.resource.fsPath, !isLinux /* ignorecase */)); const dirtyRenamed: URI[] = []; return TPromise.join(dirty.map(d => { - const targetPath = paths.join(this.element.parent.resource.fsPath, newName); let renamed: URI; // If the dirty file itself got moved, just reparent it to the target folder + const targetPath = paths.join(this.element.parent.resource.path, newName); if (paths.isEqual(this.element.resource.fsPath, d.fsPath)) { renamed = this.element.parent.resource.with({ path: targetPath }); } // Otherwise, a parent of the dirty resource got moved, so we have to reparent more complicated. Example: else { - renamed = this.element.parent.resource.with({ path: paths.join(targetPath, d.fsPath.substr(this.element.resource.fsPath.length + 1)) }); + renamed = this.element.parent.resource.with({ path: paths.join(targetPath, d.path.substr(this.element.resource.path.length + 1)) }); } dirtyRenamed.push(renamed); @@ -587,7 +587,7 @@ export class CreateFileAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFile(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.fsPath, fileName) })).then(stat => { + return this.fileService.createFile(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.path, fileName) })).then(stat => { return this.editorService.openEditor({ resource: stat.resource, options: { pinned: true } }); }, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); @@ -613,7 +613,7 @@ export class CreateFolderAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFolder(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.fsPath, fileName) })).then(null, (error) => { + return this.fileService.createFolder(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.path, fileName) })).then(null, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); }); } @@ -845,7 +845,7 @@ export class ImportFileAction extends BaseFileAction { resources.forEach(resource => { importPromisesFactory.push(() => { const sourceFile = resource; - const targetFile = targetElement.resource.with({ path: paths.join(targetElement.resource.fsPath, paths.basename(sourceFile.fsPath)) }); + const targetFile = targetElement.resource.with({ path: paths.join(targetElement.resource.path, paths.basename(sourceFile.path)) }); // if the target exists and is dirty, make sure to revert it. otherwise the dirty contents // of the target file would replace the contents of the imported file. since we already @@ -1044,14 +1044,14 @@ export class DuplicateFileAction extends BaseFileAction { private findTarget(): URI { let name = this.element.name; - let candidate = this.target.resource.with({ path: paths.join(this.target.resource.fsPath, name) }); + let candidate = this.target.resource.with({ path: paths.join(this.target.resource.path, name) }); while (true) { if (!this.element.root.find(candidate)) { break; } name = this.toCopyName(name, this.element.isDirectory); - candidate = this.target.resource.with({ path: paths.join(this.target.resource.fsPath, name) }); + candidate = this.target.resource.with({ path: paths.join(this.target.resource.path, name) }); } return candidate; diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts index 5de8984ee4f..1795f7b9bf0 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts @@ -205,8 +205,8 @@ export class FileEditorTracker implements IWorkbenchContribution { if (oldResource.toString() === resource.toString()) { reopenFileResource = newResource; // file got moved } else { - const index = indexOf(resource.fsPath, oldResource.fsPath, !isLinux /* ignorecase */); - reopenFileResource = newResource.with({ path: paths.join(newResource.fsPath, resource.fsPath.substr(index + oldResource.fsPath.length + 1)) }); // parent folder got moved + const index = indexOf(resource.path, oldResource.path, !isLinux /* ignorecase */); + reopenFileResource = newResource.with({ path: paths.join(newResource.path, resource.path.substr(index + oldResource.path.length + 1)) }); // parent folder got moved } // Reopen From 1e7d23665b74ff41042f995f2875fe61d81b18dc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 10:21:28 +0200 Subject: [PATCH 082/145] revert URI changes for now on master and continue on branch --- .../parts/files/browser/fileActions.ts | 33 ++++++++++--------- .../files/browser/views/explorerViewer.ts | 5 +-- .../files/common/editors/fileEditorTracker.ts | 4 +-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/parts/files/browser/fileActions.ts b/src/vs/workbench/parts/files/browser/fileActions.ts index 10caeeb640b..3c609e62030 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.ts @@ -296,20 +296,22 @@ class RenameFileAction extends BaseRenameAction { } public runAction(newName: string): TPromise { + const dirty = this.textFileService.getDirty().filter(d => paths.isEqualOrParent(d.fsPath, this.element.resource.fsPath, !isLinux /* ignorecase */)); const dirtyRenamed: URI[] = []; return TPromise.join(dirty.map(d => { + + const targetPath = paths.join(this.element.parent.resource.fsPath, newName); let renamed: URI; // If the dirty file itself got moved, just reparent it to the target folder - const targetPath = paths.join(this.element.parent.resource.path, newName); if (paths.isEqual(this.element.resource.fsPath, d.fsPath)) { - renamed = this.element.parent.resource.with({ path: targetPath }); + renamed = URI.file(targetPath); } // Otherwise, a parent of the dirty resource got moved, so we have to reparent more complicated. Example: else { - renamed = this.element.parent.resource.with({ path: paths.join(targetPath, d.path.substr(this.element.resource.path.length + 1)) }); + renamed = URI.file(paths.join(targetPath, d.fsPath.substr(this.element.resource.fsPath.length + 1))); } dirtyRenamed.push(renamed); @@ -587,7 +589,7 @@ export class CreateFileAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFile(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.path, fileName) })).then(stat => { + return this.fileService.createFile(URI.file(paths.join(this.element.parent.resource.fsPath, fileName))).then(stat => { return this.editorService.openEditor({ resource: stat.resource, options: { pinned: true } }); }, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); @@ -613,7 +615,7 @@ export class CreateFolderAction extends BaseCreateAction { } public runAction(fileName: string): TPromise { - return this.fileService.createFolder(this.element.parent.resource.with({ path: paths.join(this.element.parent.resource.path, fileName) })).then(null, (error) => { + return this.fileService.createFolder(URI.file(paths.join(this.element.parent.resource.fsPath, fileName))).then(null, (error) => { this.onErrorWithRetry(error, () => this.runAction(fileName)); }); } @@ -796,9 +798,10 @@ export class ImportFileAction extends BaseFileAction { return this.tree; } - public run(resources: URI[]): TPromise { + public run(context?: any): TPromise { const importPromise = TPromise.as(null).then(() => { - if (resources && resources.length > 0) { + const input = context.input as { paths: string[] }; + if (input.paths && input.paths.length > 0) { // Find parent for import let targetElement: FileStat; @@ -823,8 +826,8 @@ export class ImportFileAction extends BaseFileAction { }); let overwrite = true; - if (resources.some(resource => { - return !!targetNames[isLinux ? paths.basename(resource.fsPath) : paths.basename(resource.fsPath).toLowerCase()]; + if (input.paths.some(path => { + return !!targetNames[isLinux ? paths.basename(path) : paths.basename(path).toLowerCase()]; })) { const confirm: IConfirmation = { message: nls.localize('confirmOverwrite', "A file or folder with the same name already exists in the destination folder. Do you want to replace it?"), @@ -842,10 +845,10 @@ export class ImportFileAction extends BaseFileAction { // Run import in sequence const importPromisesFactory: ITask>[] = []; - resources.forEach(resource => { + input.paths.forEach(path => { importPromisesFactory.push(() => { - const sourceFile = resource; - const targetFile = targetElement.resource.with({ path: paths.join(targetElement.resource.path, paths.basename(sourceFile.path)) }); + const sourceFile = URI.file(path); + const targetFile = URI.file(paths.join(targetElement.resource.fsPath, paths.basename(path))); // if the target exists and is dirty, make sure to revert it. otherwise the dirty contents // of the target file would replace the contents of the imported file. since we already @@ -859,7 +862,7 @@ export class ImportFileAction extends BaseFileAction { return this.fileService.importFile(sourceFile, targetElement.resource).then(res => { // if we only import one file, just open it directly - if (resources.length === 1) { + if (input.paths.length === 1) { this.editorService.openEditor({ resource: res.stat.resource, options: { pinned: true } }).done(null, errors.onUnexpectedError); } }, error => this.onError(error)); @@ -1044,14 +1047,14 @@ export class DuplicateFileAction extends BaseFileAction { private findTarget(): URI { let name = this.element.name; - let candidate = this.target.resource.with({ path: paths.join(this.target.resource.path, name) }); + let candidate = URI.file(paths.join(this.target.resource.fsPath, name)); while (true) { if (!this.element.root.find(candidate)) { break; } name = this.toCopyName(name, this.element.isDirectory); - candidate = this.target.resource.with({ path: paths.join(this.target.resource.path, name) }); + candidate = URI.file(paths.join(this.target.resource.fsPath, name)); } return candidate; diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index b1b520c78a4..3622e0e1ba4 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -910,8 +910,9 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { // Handle dropped files (only support FileStat as target) else if (target instanceof FileStat) { const importAction = this.instantiationService.createInstance(ImportFileAction, tree, target, null); - - return importAction.run(droppedResources.map(res => res.resource)); + return importAction.run({ + input: { paths: droppedResources.map(res => res.resource.fsPath) } + }); } return void 0; diff --git a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts index 1795f7b9bf0..52124b9fb7e 100644 --- a/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts +++ b/src/vs/workbench/parts/files/common/editors/fileEditorTracker.ts @@ -205,8 +205,8 @@ export class FileEditorTracker implements IWorkbenchContribution { if (oldResource.toString() === resource.toString()) { reopenFileResource = newResource; // file got moved } else { - const index = indexOf(resource.path, oldResource.path, !isLinux /* ignorecase */); - reopenFileResource = newResource.with({ path: paths.join(newResource.path, resource.path.substr(index + oldResource.path.length + 1)) }); // parent folder got moved + const index = indexOf(resource.fsPath, oldResource.fsPath, !isLinux /* ignorecase */); + reopenFileResource = URI.file(paths.join(newResource.fsPath, resource.fsPath.substr(index + oldResource.fsPath.length + 1))); // parent folder got moved } // Reopen From 2153617a7c78292e640dd10a22af25c43758d2d3 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 14 Sep 2017 10:26:39 +0200 Subject: [PATCH 083/145] Rename roots to folders --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 6 +-- src/vs/base/common/labels.ts | 12 ++--- .../standalone/browser/simpleServices.ts | 8 ++-- .../configuration/common/configuration.ts | 6 +-- src/vs/platform/workspace/common/workspace.ts | 48 +++++++++---------- .../workspace/test/common/workspace.test.ts | 2 +- .../electron-browser/mainThreadWorkspace.ts | 6 +-- src/vs/workbench/api/node/extHost.protocol.ts | 2 +- src/vs/workbench/api/node/extHostWorkspace.ts | 20 ++++---- .../browser/actions/workspaceActions.ts | 16 +++---- src/vs/workbench/browser/labels.ts | 8 ++-- .../browser/parts/statusbar/statusbarPart.ts | 2 +- .../browser/parts/titlebar/titlebarPart.ts | 8 ++-- src/vs/workbench/common/resources.ts | 18 +++---- src/vs/workbench/electron-browser/main.ts | 2 +- src/vs/workbench/electron-browser/window.ts | 4 +- src/vs/workbench/node/extensionHostMain.ts | 6 +-- .../debugConfigurationManager.ts | 4 +- .../statusbarColorProvider.ts | 2 +- .../extensions/browser/extensionsActions.ts | 2 +- .../electron-browser/feedbackStatusbarItem.ts | 2 +- .../files/browser/fileActions.contribution.ts | 2 +- .../parts/files/browser/views/explorerView.ts | 18 +++---- .../files/browser/views/explorerViewer.ts | 18 +++---- .../parts/files/common/explorerModel.ts | 10 ++-- .../parts/output/common/outputLinkProvider.ts | 6 +-- .../preferences/browser/preferencesActions.ts | 6 +-- .../preferences/browser/preferencesEditor.ts | 12 ++--- .../preferences/browser/preferencesService.ts | 6 +-- .../preferences/browser/preferencesWidgets.ts | 8 ++-- .../parts/preferences/common/preferences.ts | 4 +- .../relauncher.contribution.ts | 26 +++++----- .../parts/search/browser/openFileHandler.ts | 4 +- .../parts/search/browser/searchViewlet.ts | 16 +++---- .../parts/search/common/queryBuilder.ts | 4 +- .../search/test/common/queryBuilder.test.ts | 6 +-- .../electron-browser/task.contribution.ts | 4 +- .../electron-browser/terminalTaskSystem.ts | 2 +- .../parts/tasks/node/processRunnerDetector.ts | 8 ++-- .../parts/tasks/node/processTaskSystem.ts | 2 +- .../configuration/node/configuration.ts | 46 +++++++++--------- .../node/configurationEditingService.ts | 12 ++--- .../files/electron-browser/fileService.ts | 8 ++-- .../services/files/node/fileService.ts | 20 ++++---- .../files/node/watcher/nsfw/watcherService.ts | 16 +++---- .../files/node/watcher/unix/watcherService.ts | 2 +- .../node/watcher/win32/watcherService.ts | 2 +- .../services/history/browser/history.ts | 4 +- .../telemetry/common/workspaceStats.ts | 6 +-- .../textfile/common/textFileEditorModel.ts | 4 +- .../workspace/common/workspaceEditing.ts | 8 ++-- .../workspace/node/workspaceEditingService.ts | 40 ++++++++-------- .../api/extHostConfiguration.test.ts | 4 +- .../api/extHostWorkspace.test.ts | 34 ++++++------- .../workbench/test/workbenchTestServices.ts | 18 +++---- 55 files changed, 285 insertions(+), 285 deletions(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index d13e1c2682c..fb83ca1d3b1 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -11,7 +11,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte import { IMatch } from 'vs/base/common/filters'; import uri from 'vs/base/common/uri'; import paths = require('vs/base/common/paths'); -import { IRootProvider, getPathLabel, IUserHomeProvider } from 'vs/base/common/labels'; +import { IWorkspaceFolderProvider, getPathLabel, IUserHomeProvider } from 'vs/base/common/labels'; import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; export interface IIconLabelCreationOptions { @@ -152,13 +152,13 @@ export class IconLabel { export class FileLabel extends IconLabel { - constructor(container: HTMLElement, file: uri, provider: IRootProvider, userHome?: IUserHomeProvider) { + constructor(container: HTMLElement, file: uri, provider: IWorkspaceFolderProvider, userHome?: IUserHomeProvider) { super(container); this.setFile(file, provider, userHome); } - public setFile(file: uri, provider: IRootProvider, userHome: IUserHomeProvider): void { + public setFile(file: uri, provider: IWorkspaceFolderProvider, userHome: IUserHomeProvider): void { const parent = paths.dirname(file.fsPath); this.setValue(paths.basename(file.fsPath), parent && parent !== '.' ? getPathLabel(parent, provider, userHome) : '', { title: file.fsPath }); diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index d86e3f668e2..6192b7dcd01 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -17,10 +17,10 @@ export interface ILabelProvider { getLabel(element: any): string; } -export interface IRootProvider { - getRoot(resource: URI): URI; +export interface IWorkspaceFolderProvider { + getWorkspaceFolder(resource: URI): URI; getWorkspace(): { - roots: URI[]; + folders: URI[]; }; } @@ -28,7 +28,7 @@ export interface IUserHomeProvider { userHome: string; } -export function getPathLabel(resource: URI | string, rootProvider?: IRootProvider, userHomeProvider?: IUserHomeProvider): string { +export function getPathLabel(resource: URI | string, rootProvider?: IWorkspaceFolderProvider, userHomeProvider?: IUserHomeProvider): string { if (!resource) { return null; } @@ -38,9 +38,9 @@ export function getPathLabel(resource: URI | string, rootProvider?: IRootProvide } // return early if we can resolve a relative path label from the root - const baseResource = rootProvider ? rootProvider.getRoot(resource) : null; + const baseResource = rootProvider ? rootProvider.getWorkspaceFolder(resource) : null; if (baseResource) { - const hasMultipleRoots = rootProvider.getWorkspace().roots.length > 1; + const hasMultipleRoots = rootProvider.getWorkspace().folders.length > 1; let pathLabel: string; if (isEqual(baseResource.fsPath, resource.fsPath, !platform.isLinux /* ignorecase */)) { diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 228879e82dc..3dadc377cef 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -526,13 +526,13 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { public readonly onDidChangeWorkspaceName: Event = this._onDidChangeWorkspaceName.event; private readonly _onDidChangeWorkspaceRoots: Emitter = new Emitter(); - public readonly onDidChangeWorkspaceRoots: Event = this._onDidChangeWorkspaceRoots.event; + public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceRoots.event; private readonly workspace: IWorkspace; constructor() { const resource = URI.from({ scheme: SimpleWorkspaceContextService.SCHEME, authority: 'model', path: '/' }); - this.workspace = { id: '4064f6ec-cb38-4ad0-af64-ee6467e63c82', roots: [resource], name: resource.fsPath }; + this.workspace = { id: '4064f6ec-cb38-4ad0-af64-ee6467e63c82', folders: [resource], name: resource.fsPath }; } public getWorkspace(): IWorkspace { @@ -549,8 +549,8 @@ export class SimpleWorkspaceContextService implements IWorkspaceContextService { return WorkbenchState.EMPTY; } - public getRoot(resource: URI): URI { - return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME ? this.workspace.roots[0] : void 0; + public getWorkspaceFolder(resource: URI): URI { + return resource && resource.scheme === SimpleWorkspaceContextService.SCHEME ? this.workspace.folders[0] : void 0; } public isInsideWorkspace(resource: URI): boolean { diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index 85e3e00ff4c..7b9ecd5e500 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -257,7 +257,7 @@ export class Configuration { lookupLegacy(key: string): IConfigurationValue { if (!this._legacyWorkspaceConsolidatedConfiguration) { - this._legacyWorkspaceConsolidatedConfiguration = this._workspace ? new ConfigurationModel().merge(this._workspaceConfiguration).merge(this.folders.get(this._workspace.roots[0])) : null; + this._legacyWorkspaceConsolidatedConfiguration = this._workspace ? new ConfigurationModel().merge(this._workspaceConfiguration).merge(this.folders.get(this._workspace.folders[0])) : null; } const consolidateConfigurationModel = this.getConsolidateConfigurationModel({}); return { @@ -325,7 +325,7 @@ export class Configuration { return this._workspaceConsolidatedConfiguration; } - const root = this._workspace.getRoot(resource); + const root = this._workspace.getFolder(resource); if (!root) { return this._workspaceConsolidatedConfiguration; } @@ -338,7 +338,7 @@ export class Configuration { return null; } - const root = this._workspace.getRoot(resource); + const root = this._workspace.getFolder(resource); return root ? this.folders.get(root) : null; } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index bd4239f560a..38f755fc658 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -44,15 +44,15 @@ export interface IWorkspaceContextService { onDidChangeWorkspaceName: Event; /** - * An event which fires on workspace roots change. + * An event which fires on workspace folders change. */ - onDidChangeWorkspaceRoots: Event; + onDidChangeWorkspaceFolders: Event; /** - * Returns the root for the given resource from the workspace. + * Returns the folder for the given resource from the workspace. * Can be null if there is no workspace or the resource is not inside the workspace. */ - getRoot(resource: URI): URI; + getWorkspaceFolder(resource: URI): URI; /** * Return `true` if the current workspace has the given identifier otherwise `false`. @@ -83,9 +83,9 @@ export interface IWorkspace { readonly name: string; /** - * Roots in the workspace. + * Folders in the workspace. */ - readonly roots: URI[]; + readonly folders: URI[]; /** * the location of the workspace configuration @@ -95,30 +95,30 @@ export interface IWorkspace { export class Workspace implements IWorkspace { - private _rootsMap: TrieMap = new TrieMap(); - private _roots: URI[]; + private _foldersMap: TrieMap = new TrieMap(); + private _folders: URI[]; constructor( public readonly id: string, private _name: string, - roots: URI[], + folders: URI[], private _configuration: URI = null, public readonly ctime?: number ) { - this.roots = roots; + this.folders = folders; } - private ensureUnique(roots: URI[]): URI[] { - return distinct(roots, root => isLinux ? root.fsPath : root.fsPath.toLowerCase()); + private ensureUnique(folders: URI[]): URI[] { + return distinct(folders, folder => isLinux ? folder.fsPath : folder.fsPath.toLowerCase()); } - public get roots(): URI[] { - return this._roots; + public get folders(): URI[] { + return this._folders; } - public set roots(roots: URI[]) { - this._roots = this.ensureUnique(roots); - this.updateRootsMap(); + public set folders(folders: URI[]) { + this._folders = this.ensureUnique(folders); + this.updateFoldersMap(); } public get name(): string { @@ -137,22 +137,22 @@ export class Workspace implements IWorkspace { this._configuration = configuration; } - public getRoot(resource: URI): URI { + public getFolder(resource: URI): URI { if (!resource) { return null; } - return this._rootsMap.findSubstr(resource.fsPath); + return this._foldersMap.findSubstr(resource.fsPath); } - private updateRootsMap(): void { - this._rootsMap = new TrieMap(); - for (const root of this.roots) { - this._rootsMap.insert(root.fsPath, root); + private updateFoldersMap(): void { + this._foldersMap = new TrieMap(); + for (const folder of this.folders) { + this._foldersMap.insert(folder.fsPath, folder); } } public toJSON(): IWorkspace { - return { id: this.id, roots: this.roots, name: this.name }; + return { id: this.id, folders: this.folders, name: this.name }; } } diff --git a/src/vs/platform/workspace/test/common/workspace.test.ts b/src/vs/platform/workspace/test/common/workspace.test.ts index 1f296428317..dcfdff48e38 100644 --- a/src/vs/platform/workspace/test/common/workspace.test.ts +++ b/src/vs/platform/workspace/test/common/workspace.test.ts @@ -17,6 +17,6 @@ suite('Workspace', () => { let roots = [URI.file('/some/path'), URI.file('/some/path')]; let ws = new Workspace('id', 'name', roots, URI.file('/config')); - assert.equal(ws.roots.length, 1); + assert.equal(ws.folders.length, 1); }); }); \ No newline at end of file diff --git a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts index d58ce7c1744..32c8d9484d8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts @@ -38,7 +38,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { @IFileService private readonly _fileService: IFileService ) { this._proxy = extHostContext.get(ExtHostContext.ExtHostWorkspace); - this._contextService.onDidChangeWorkspaceRoots(this._onDidChangeWorkspace, this, this._toDispose); + this._contextService.onDidChangeWorkspaceFolders(this._onDidChangeWorkspace, this, this._toDispose); } dispose(): void { @@ -60,11 +60,11 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape { $startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable { const workspace = this._contextService.getWorkspace(); - if (!workspace.roots.length) { + if (!workspace.folders.length) { return undefined; } const query: ISearchQuery = { - folderQueries: workspace.roots.map(root => ({ folder: root })), + folderQueries: workspace.folders.map(root => ({ folder: root })), type: QueryType.File, maxResults, includePattern: { [include]: true }, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 0f5f2955d88..1f461211f6d 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -64,7 +64,7 @@ export interface IEnvironment { export interface IWorkspaceData { id: string; name: string; - roots: URI[]; + folders: URI[]; } export interface IInitData { diff --git a/src/vs/workbench/api/node/extHostWorkspace.ts b/src/vs/workbench/api/node/extHostWorkspace.ts index ba50508d0ef..219bfac0312 100644 --- a/src/vs/workbench/api/node/extHostWorkspace.ts +++ b/src/vs/workbench/api/node/extHostWorkspace.ts @@ -32,10 +32,10 @@ class Workspace2 extends Workspace { private readonly _structure = new TrieMap(s => s.split('/')); private constructor(data: IWorkspaceData) { - super(data.id, data.name, data.roots); + super(data.id, data.name, data.folders); // setup the workspace folder data structure - this.roots.forEach((uri, index) => { + this.folders.forEach((uri, index) => { const folder = { name: basename(uri.fsPath), uri, @@ -46,7 +46,7 @@ class Workspace2 extends Workspace { }); } - get folders(): vscode.WorkspaceFolder[] { + get workspaceFolders(): vscode.WorkspaceFolder[] { return this._folder.slice(0); } @@ -92,7 +92,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { if (!this._workspace) { return undefined; } else { - return this._workspace.folders.slice(0); + return this._workspace.workspaceFolders.slice(0); } } @@ -110,11 +110,11 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { if (!this._workspace) { return undefined; } - const { roots } = this._workspace; - if (roots.length === 0) { + const { folders } = this._workspace; + if (folders.length === 0) { return undefined; } - return roots[0].fsPath; + return folders[0].fsPath; } getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string { @@ -140,7 +140,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { } if (typeof includeWorkspace === 'undefined') { - includeWorkspace = this.workspace.roots.length > 1; + includeWorkspace = this.workspace.folders.length > 1; } let result = relative(folder.uri.fsPath, path); @@ -155,10 +155,10 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape { // keep old workspace folder, build new workspace, and // capture new workspace folders. Compute delta between // them send that as event - const oldRoots = this._workspace ? this._workspace.folders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; + const oldRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; this._workspace = Workspace2.fromData(data); - const newRoots = this._workspace ? this._workspace.folders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; + const newRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : []; const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareWorkspaceFolder); this._onDidChangeWorkspace.fire(Object.freeze({ diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index ee384bf7d00..525931079e0 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -76,8 +76,8 @@ export abstract class BaseWorkspacesAction extends Action { protected pickFolders(buttonLabel: string, title: string): string[] { let defaultPath: string; const workspace = this.contextService.getWorkspace(); - if (workspace.roots.length > 0) { - defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default + if (workspace.folders.length > 0) { + defaultPath = dirname(workspace.folders[0].fsPath); // pick the parent of the first root by default } return this.windowService.showOpenDialog({ @@ -113,11 +113,11 @@ export class AddRootFolderAction extends BaseWorkspacesAction { if (!folders || !folders.length) { return TPromise.as(null); } - return this.workspaceEditingService.addRoots(folders.map(folder => URI.file(folder))).then(() => { + return this.workspaceEditingService.addFolders(folders.map(folder => URI.file(folder))).then(() => { return this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true); }); } - return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().roots).run(); + return this.instantiationService.createInstance(NewWorkspaceAction, NewWorkspaceAction.ID, NewWorkspaceAction.LABEL, this.contextService.getWorkspace().folders).run(); } } @@ -170,7 +170,7 @@ export class RemoveRootFolderAction extends Action { } public run(): TPromise { - return this.workspaceEditingService.removeRoots([this.rootUri]); + return this.workspaceEditingService.removeFolders([this.rootUri]); } } @@ -204,7 +204,7 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { switch (workspaceState) { case WorkbenchState.FOLDER: - const workspaceFolders = this.contextService.getWorkspace().roots.map(root => root.fsPath); + const workspaceFolders = this.contextService.getWorkspace().folders.map(root => root.fsPath); return this.windowService.createAndOpenWorkspace(workspaceFolders, configPath); case WorkbenchState.WORKSPACE: @@ -220,8 +220,8 @@ export class SaveWorkspaceAsAction extends BaseWorkspacesAction { let defaultPath: string; if (workspace.configuration && !this.isUntitledWorkspace(workspace.configuration.fsPath)) { defaultPath = workspace.configuration.fsPath; - } else if (workspace.roots.length > 0) { - defaultPath = dirname(workspace.roots[0].fsPath); // pick the parent of the first root by default + } else if (workspace.folders.length > 0) { + defaultPath = dirname(workspace.folders[0].fsPath); // pick the parent of the first root by default } return this.windowService.showSaveDialog({ diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 655bec21217..66922084d46 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -12,7 +12,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IEditorInput } from 'vs/platform/editor/common/editor'; import { toResource } from 'vs/workbench/common/editor'; -import { getPathLabel, IRootProvider } from 'vs/base/common/labels'; +import { getPathLabel, IWorkspaceFolderProvider } from 'vs/base/common/labels'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -211,9 +211,9 @@ export class FileLabel extends ResourceLabel { public setFile(resource: uri, options?: IFileLabelOptions): void { const hidePath = (options && options.hidePath) || (resource.scheme === Schemas.untitled && !this.untitledEditorService.hasAssociatedFilePath(resource)); - const rootProvider: IRootProvider = (options && options.root) ? { - getRoot(): uri { return options.root; }, - getWorkspace(): { roots: uri[]; } { return { roots: [options.root] }; }, + const rootProvider: IWorkspaceFolderProvider = (options && options.root) ? { + getWorkspaceFolder(): uri { return options.root; }, + getWorkspace(): { folders: uri[]; } { return { folders: [options.root] }; }, } : this.contextService; this.setLabel({ diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index ea688b70089..a83c9847408 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -55,7 +55,7 @@ export class StatusbarPart extends Part implements IStatusbarService { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); } public addEntry(entry: IStatusbarEntry, alignment: StatusbarAlignment, priority: number = 0): IDisposable { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index ab03feddd0b..683183e95a3 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -101,7 +101,7 @@ export class TitlebarPart extends Part implements ITitleService { this.toUnbind.push(DOM.addDisposableListener(window, DOM.EventType.FOCUS, () => this.onFocus())); this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged(true))); this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); this.toUnbind.push(this.contextService.onDidChangeWorkspaceName(() => this.onDidChangeWorkspaceName())); } @@ -115,7 +115,7 @@ export class TitlebarPart extends Part implements ITitleService { this.updateStyles(); } - private onDidChangeWorkspaceRoots(): void { + private onDidChangeWorkspaceFolders(): void { this.setTitle(this.getWindowTitle()); } @@ -195,14 +195,14 @@ export class TitlebarPart extends Part implements ITitleService { // Compute folder resource // Single Root Workspace: always the root single workspace in this case // Otherwise: root folder of the currently active file if any - let folder: URI = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.roots[0] : this.contextService.getRoot(toResource(input, { supportSideBySide: true, filter: 'file' })); + let folder: URI = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER ? workspace.folders[0] : this.contextService.getWorkspaceFolder(toResource(input, { supportSideBySide: true, filter: 'file' })); // Variables const activeEditorShort = input ? input.getTitle(Verbosity.SHORT) : ''; const activeEditorMedium = input ? input.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = input ? input.getTitle(Verbosity.LONG) : activeEditorMedium; const rootName = workspace.name; - const rootPath = labels.getPathLabel(workspace.configuration || workspace.roots[0], void 0, this.environmentService) || ''; + const rootPath = labels.getPathLabel(workspace.configuration || workspace.folders[0], void 0, this.environmentService) || ''; const folderName = folder ? (paths.basename(folder.fsPath) || folder.fsPath) : ''; const folderPath = folder ? labels.getPathLabel(folder, void 0, this.environmentService) : ''; const dirty = input && input.isDirty() ? TitlebarPart.TITLE_DIRTY : ''; diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts index 7ee3341fcac..d8ae21d82d3 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -91,14 +91,14 @@ export class ResourceGlobMatcher { private registerListeners(): void { this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.onConfigurationChanged())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); } private onConfigurationChanged(): void { this.updateExcludes(true); } - private onDidChangeWorkspaceRoots(): void { + private onDidChangeWorkspaceFolders(): void { this.updateExcludes(true); } @@ -106,13 +106,13 @@ export class ResourceGlobMatcher { let changed = false; // Add excludes per workspaces that got added - this.contextService.getWorkspace().roots.forEach(root => { - const rootExcludes = this.globFn(root); - if (!this.mapRootToExpressionConfig.has(root.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(root.toString()), rootExcludes)) { + this.contextService.getWorkspace().folders.forEach(folder => { + const rootExcludes = this.globFn(folder); + if (!this.mapRootToExpressionConfig.has(folder.toString()) || !objects.equals(this.mapRootToExpressionConfig.get(folder.toString()), rootExcludes)) { changed = true; - this.mapRootToParsedExpression.set(root.toString(), this.parseFn(rootExcludes)); - this.mapRootToExpressionConfig.set(root.toString(), objects.clone(rootExcludes)); + this.mapRootToParsedExpression.set(folder.toString(), this.parseFn(rootExcludes)); + this.mapRootToExpressionConfig.set(folder.toString(), objects.clone(rootExcludes)); } }); @@ -122,7 +122,7 @@ export class ResourceGlobMatcher { return; // always keep this one } - if (!this.contextService.getRoot(URI.parse(root))) { + if (!this.contextService.getWorkspaceFolder(URI.parse(root))) { this.mapRootToParsedExpression.delete(root); this.mapRootToExpressionConfig.delete(root); @@ -145,7 +145,7 @@ export class ResourceGlobMatcher { } public matches(resource: URI): boolean { - const root = this.contextService.getRoot(resource); + const root = this.contextService.getWorkspaceFolder(resource); let expressionForRoot: ParsedExpression; if (root && this.mapRootToParsedExpression.has(root.toString())) { diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index 7d00adf6ec4..70cbf4e7b09 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -162,7 +162,7 @@ function createStorageService(workspaceService: IWorkspaceContextService, enviro // the ctime is used as secondary workspace id to clean up stale UI state if necessary case WorkbenchState.FOLDER: const workspace: Workspace = workspaceService.getWorkspace(); - workspaceId = workspace.roots[0].toString(); + workspaceId = workspace.folders[0].toString(); secondaryWorkspaceId = workspace.ctime; break; diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 9940e015191..e3307c35999 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -289,12 +289,12 @@ export class ElectronWindow extends Themable { // Workspace: just add to workspace config if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - this.workspaceEditingService.addRoots(foldersToAdd).done(null, errors.onUnexpectedError); + this.workspaceEditingService.addFolders(foldersToAdd).done(null, errors.onUnexpectedError); } // Single folder or no workspace: create workspace and open else { - const workspaceFolders: URI[] = [...this.contextService.getWorkspace().roots]; + const workspaceFolders: URI[] = [...this.contextService.getWorkspace().folders]; // Fill in remaining ones from request workspaceFolders.push(...request.foldersToAdd.map(folderToAdd => URI.file(folderToAdd.filePath))); diff --git a/src/vs/workbench/node/extensionHostMain.ts b/src/vs/workbench/node/extensionHostMain.ts index b798a89d457..9bd3d58ff3d 100644 --- a/src/vs/workbench/node/extensionHostMain.ts +++ b/src/vs/workbench/node/extensionHostMain.ts @@ -145,7 +145,7 @@ export class ExtensionHostMain { } private handleWorkspaceContainsEagerExtensions(): TPromise { - if (!this._workspace || this._workspace.roots.length === 0) { + if (!this._workspace || this._workspace.folders.length === 0) { return TPromise.as(null); } @@ -177,7 +177,7 @@ export class ExtensionHostMain { } const query: ISearchQuery = { - folderQueries: this._workspace.roots.map(root => ({ folder: root })), + folderQueries: this._workspace.folders.map(root => ({ folder: root })), type: QueryType.File, maxResults: 1, includePattern: { [p]: true } @@ -187,7 +187,7 @@ export class ExtensionHostMain { } else { // find exact path return (async resolve => { - for (const { fsPath } of this._workspace.roots) { + for (const { fsPath } of this._workspace.folders) { if (await pfs.exists(join(fsPath, p))) { return p; } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts index 0fa50d596b8..5aa8b1e8f0a 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugConfigurationManager.ts @@ -341,7 +341,7 @@ export class ConfigurationManager implements IConfigurationManager { }); }); - this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => { + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => { this.initLaunches(); this.selectConfiguration(); })); @@ -353,7 +353,7 @@ export class ConfigurationManager implements IConfigurationManager { } private initLaunches(): void { - this.launches = this.contextService.getWorkspace().roots.map(root => this.instantiationService.createInstance(Launch, this, root)); + this.launches = this.contextService.getWorkspace().folders.map(folder => this.instantiationService.createInstance(Launch, this, folder)); if (this.launches.indexOf(this._selectedLaunch) === -1) { this._selectedLaunch = undefined; } diff --git a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts index c4a2925e667..b4ae967d067 100644 --- a/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts +++ b/src/vs/workbench/parts/debug/electron-browser/statusbarColorProvider.ts @@ -49,7 +49,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri private registerListeners(): void { this.toUnbind.push(this.debugService.onDidChangeState(state => this.updateStyles())); - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(state => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(state => this.updateStyles())); } protected updateStyles(): void { diff --git a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts index b035130333e..51d6dc2eb26 100644 --- a/src/vs/workbench/parts/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/browser/extensionsActions.ts @@ -1276,7 +1276,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { } private getOrCreateExtensionsFile(): TPromise<{ created: boolean, extensionsFileResource: URI }> { - const extensionsFileResource = URI.file(paths.join(this.contextService.getWorkspace().roots[0].fsPath, '.vscode', 'extensions.json')); // TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) + const extensionsFileResource = URI.file(paths.join(this.contextService.getWorkspace().folders[0].fsPath, '.vscode', 'extensions.json')); // TODO@Sandeep (https://github.com/Microsoft/vscode/issues/29242) return this.fileService.resolveContent(extensionsFileResource).then(content => { return { created: false, extensionsFileResource }; diff --git a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts index bbd3755b8be..873ab35c441 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem.ts @@ -63,7 +63,7 @@ export class FeedbackStatusbarItem extends Themable implements IStatusbarItem { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); } protected updateStyles(): void { diff --git a/src/vs/workbench/parts/files/browser/fileActions.contribution.ts b/src/vs/workbench/parts/files/browser/fileActions.contribution.ts index 11385383db6..b72884929b5 100644 --- a/src/vs/workbench/parts/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/parts/files/browser/fileActions.contribution.ts @@ -95,7 +95,7 @@ class FilesViewerActionContributor extends ActionBarContributor { let action: Action = this.instantiationService.createInstance(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL); action.order = 52; actions.push(action); - if (this.contextService.getWorkspace().roots.length > 1) { + if (this.contextService.getWorkspace().folders.length > 1) { action = this.instantiationService.createInstance(RemoveRootFolderAction, stat.resource, RemoveRootFolderAction.ID, RemoveRootFolderAction.LABEL); action.order = 53; actions.push(action); diff --git a/src/vs/workbench/parts/files/browser/views/explorerView.ts b/src/vs/workbench/parts/files/browser/views/explorerView.ts index 33672313a9d..85fe8e72a8a 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerView.ts @@ -133,7 +133,7 @@ export class ExplorerView extends CollapsibleView { const titleSpan = $('span').appendTo(titleDiv); const setHeader = () => { const workspace = this.contextService.getWorkspace(); - const title = workspace.roots.map(root => labels.getPathLabel(root.fsPath, void 0, this.environmentService)).join(); + const title = workspace.folders.map(folder => labels.getPathLabel(folder.fsPath, void 0, this.environmentService)).join(); titleSpan.text(this.name).title(title); }; this.toDispose.push(this.contextService.onDidChangeWorkspaceName(() => setHeader())); @@ -166,7 +166,7 @@ export class ExplorerView extends CollapsibleView { }; this.toDispose.push(this.themeService.onDidFileIconThemeChange(onFileIconThemeChange)); - this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => this.refreshFromEvent())); + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.refreshFromEvent())); onFileIconThemeChange(this.themeService.getFileIconTheme()); } @@ -735,17 +735,17 @@ export class ExplorerView extends CollapsibleView { if (!this.isCreated) { const activeFile = this.getActiveFile(); if (activeFile) { - const root = this.contextService.getRoot(activeFile); - if (root) { - const found = targetsToResolve.filter(t => t.root.resource.toString() === root.toString()).pop(); + const workspaceFolder = this.contextService.getWorkspaceFolder(activeFile); + if (workspaceFolder) { + const found = targetsToResolve.filter(t => t.root.resource.toString() === workspaceFolder.toString()).pop(); found.options.resolveTo.push(activeFile); } } targetsToExpand.forEach(toExpand => { - const root = this.contextService.getRoot(toExpand); - if (root) { - const found = targetsToResolve.filter(ttr => ttr.resource.toString() === root.toString()).pop(); + const workspaceFolder = this.contextService.getWorkspaceFolder(toExpand); + if (workspaceFolder) { + const found = targetsToResolve.filter(ttr => ttr.resource.toString() === workspaceFolder.toString()).pop(); found.options.resolveTo.push(toExpand); } }); @@ -855,7 +855,7 @@ export class ExplorerView extends CollapsibleView { // Stat needs to be resolved first and then revealed const options: IResolveFileOptions = { resolveTo: [resource] }; - const rootUri = this.contextService.getRoot(resource) || this.model.roots[0].resource; + const rootUri = this.contextService.getWorkspaceFolder(resource) || this.model.roots[0].resource; return this.fileService.resolveFile(rootUri, options).then(stat => { // Convert to model diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 5f07e5d0f04..dc45f78e194 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -655,16 +655,16 @@ export class FileFilter implements IFilter { @IConfigurationService private configurationService: IConfigurationService ) { this.hiddenExpressionPerRoot = new Map(); - this.contextService.onDidChangeWorkspaceRoots(() => this.updateConfiguration()); + this.contextService.onDidChangeWorkspaceFolders(() => this.updateConfiguration()); } public updateConfiguration(): boolean { let needsRefresh = false; - this.contextService.getWorkspace().roots.forEach(root => { - const configuration = this.configurationService.getConfiguration(undefined, { resource: root }); + this.contextService.getWorkspace().folders.forEach(folder => { + const configuration = this.configurationService.getConfiguration(undefined, { resource: folder }); const excludesConfig = (configuration && configuration.files && configuration.files.exclude) || Object.create(null); - needsRefresh = needsRefresh || !objects.equals(this.hiddenExpressionPerRoot.get(root.toString()), excludesConfig); - this.hiddenExpressionPerRoot.set(root.toString(), objects.clone(excludesConfig)); // do not keep the config, as it gets mutated under our hoods + needsRefresh = needsRefresh || !objects.equals(this.hiddenExpressionPerRoot.get(folder.toString()), excludesConfig); + this.hiddenExpressionPerRoot.set(folder.toString(), objects.clone(excludesConfig)); // do not keep the config, as it gets mutated under our hoods }); return needsRefresh; @@ -838,7 +838,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY(true) : DRAG_OVER_ACCEPT_BUBBLE_DOWN(true); } - if (this.contextService.getWorkspace().roots.every(r => r.toString() !== target.resource.toString())) { + if (this.contextService.getWorkspace().folders.every(r => r.toString() !== target.resource.toString())) { return fromDesktop || isCopy ? DRAG_OVER_ACCEPT_BUBBLE_UP_COPY : DRAG_OVER_ACCEPT_BUBBLE_UP; } } @@ -883,7 +883,7 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { } if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { - return this.workspaceEditingService.addRoots(folders); + return this.workspaceEditingService.addFolders(folders); } // If we are in single-folder context, ask for confirmation to create a workspace @@ -894,8 +894,8 @@ export class FileDragAndDrop extends SimpleFileResourceDragAndDrop { }); if (result) { - const currentRoots = this.contextService.getWorkspace().roots; - const newRoots = [...currentRoots, ...folders]; + const currentFolders = this.contextService.getWorkspace().folders; + const newRoots = [...currentFolders, ...folders]; return this.windowService.createAndOpenWorkspace(distinct(newRoots.map(root => root.fsPath))); } diff --git a/src/vs/workbench/parts/files/common/explorerModel.ts b/src/vs/workbench/parts/files/common/explorerModel.ts index e3d97b1d97b..cbcbad4b33d 100644 --- a/src/vs/workbench/parts/files/common/explorerModel.ts +++ b/src/vs/workbench/parts/files/common/explorerModel.ts @@ -25,8 +25,8 @@ export class Model { private _roots: FileStat[]; constructor( @IWorkspaceContextService private contextService: IWorkspaceContextService) { - const setRoots = () => this._roots = this.contextService.getWorkspace().roots.map(uri => new FileStat(uri, undefined)); - this.contextService.onDidChangeWorkspaceRoots(() => setRoots()); + const setRoots = () => this._roots = this.contextService.getWorkspace().folders.map(uri => new FileStat(uri, undefined)); + this.contextService.onDidChangeWorkspaceFolders(() => setRoots()); setRoots(); } @@ -49,9 +49,9 @@ export class Model { * Will return null in case the FileStat does not exist. */ public findClosest(resource: URI): FileStat { - const rootUri = this.contextService.getRoot(resource); - if (rootUri) { - const root = this.roots.filter(r => r.resource.toString() === rootUri.toString()).pop(); + const folder = this.contextService.getWorkspaceFolder(resource); + if (folder) { + const root = this.roots.filter(r => r.resource.toString() === folder.toString()).pop(); if (root) { return root.find(resource); } diff --git a/src/vs/workbench/parts/output/common/outputLinkProvider.ts b/src/vs/workbench/parts/output/common/outputLinkProvider.ts index 6279ac099c1..e457e1073c4 100644 --- a/src/vs/workbench/parts/output/common/outputLinkProvider.ts +++ b/src/vs/workbench/parts/output/common/outputLinkProvider.ts @@ -37,7 +37,7 @@ export class OutputLinkProvider { } private registerListeners(): void { - this.contextService.onDidChangeWorkspaceRoots(() => this.updateLinkProviderWorker()); + this.contextService.onDidChangeWorkspaceFolders(() => this.updateLinkProviderWorker()); } private updateLinkProviderWorker(): void { @@ -55,7 +55,7 @@ export class OutputLinkProvider { } // Update link provider worker if workspace roots changed - const newWorkspacesCount = this.contextService.getWorkspace().roots.length; + const newWorkspacesCount = this.contextService.getWorkspace().folders.length; if (this.workspacesCount !== newWorkspacesCount) { this.workspacesCount = newWorkspacesCount; @@ -80,7 +80,7 @@ export class OutputLinkProvider { if (!this.worker) { const createData: ICreateData = { - workspaceFolders: this.contextService.getWorkspace().roots.map(root => root.toString()) + workspaceFolders: this.contextService.getWorkspace().folders.map(folder => folder.toString()) }; this.worker = createWebWorker(this.modelService, { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts index 8e13d25f3b8..aeee25d30bf 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesActions.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesActions.ts @@ -105,9 +105,9 @@ export class OpenFolderSettingsAction extends Action { } public run(): TPromise { - const picks: IPickOpenEntry[] = this.workspaceContextService.getWorkspace().roots.map((root, index) => { + const picks: IPickOpenEntry[] = this.workspaceContextService.getWorkspace().folders.map((folder, index) => { return { - label: getSettingsTargetName(ConfigurationTarget.FOLDER, root, this.workspaceContextService), + label: getSettingsTargetName(ConfigurationTarget.FOLDER, folder, this.workspaceContextService), id: `${index}` }; }); @@ -115,7 +115,7 @@ export class OpenFolderSettingsAction extends Action { return this.quickOpenService.pick(picks, { placeHolder: nls.localize('pickFolder', "Select Folder") }) .then(pick => { if (pick) { - return this.preferencesService.openFolderSettings(this.workspaceContextService.getWorkspace().roots[parseInt(pick.id)]); + return this.preferencesService.openFolderSettings(this.workspaceContextService.getWorkspace().folders[parseInt(pick.id)]); } return undefined; }); diff --git a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts index d0872cca42f..624ab8f0ef9 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesEditor.ts @@ -152,7 +152,7 @@ export class PreferencesEditor extends BaseEditor { this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget)); this.preferencesRenderers = this._register(new PreferencesRenderers()); - this._register(this.workspaceContextService.onDidChangeWorkspaceRoots(() => this.onWorkspaceRootsChanged())); + this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.onWorkspaceFoldersChanged())); } public setInput(newInput: PreferencesEditorInput, options?: EditorOptions): TPromise { @@ -226,7 +226,7 @@ export class PreferencesEditor extends BaseEditor { if (this.preferencesService.workspaceSettingsResource.fsPath === resource.fsPath) { return ConfigurationTarget.WORKSPACE; } - if (this.workspaceContextService.getRoot(resource)) { + if (this.workspaceContextService.getWorkspaceFolder(resource)) { return ConfigurationTarget.FOLDER; } return null; @@ -240,10 +240,10 @@ export class PreferencesEditor extends BaseEditor { return resource; } - return this.workspaceContextService.getRoot(resource); + return this.workspaceContextService.getWorkspaceFolder(resource); } - private onWorkspaceRootsChanged(): void { + private onWorkspaceFoldersChanged(): void { if (this.input) { const settingsResource = toResource((this.input).master); const targetResource = this.getSettingsConfigurationTargetUri(settingsResource); @@ -886,8 +886,8 @@ class SettingsEditorContribution extends AbstractSettingsEditorContribution impl return true; } - for (const root of this.workspaceContextService.getWorkspace().roots) { - const folderSettingsResource = this.preferencesService.getFolderSettingsResource(root); + for (const folder of this.workspaceContextService.getWorkspace().folders) { + const folderSettingsResource = this.preferencesService.getFolderSettingsResource(folder); if (folderSettingsResource && folderSettingsResource.fsPath === model.uri.fsPath) { return true; } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 75dfb54e9d3..e820df5ea27 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -320,10 +320,10 @@ export class PreferencesService extends Disposable implements IPreferencesServic return null; } const workspace = this.contextService.getWorkspace(); - return workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.roots[0]); + return workspace.configuration || this.toResource(paths.join('.vscode', 'settings.json'), workspace.folders[0]); case ConfigurationTarget.FOLDER: - const root = this.contextService.getRoot(resource); - return root ? this.toResource(paths.join('.vscode', 'settings.json'), root) : null; + const folder = this.contextService.getWorkspaceFolder(resource); + return folder ? this.toResource(paths.join('.vscode', 'settings.json'), folder) : null; } return null; } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 6c02f39fd6c..cb4392d3c8c 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -350,13 +350,13 @@ export class SettingsTargetsWidget extends Widget { if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { actions.push(new Separator()); - actions.push(...this.workspaceContextService.getWorkspace().roots.map((root, index) => { + actions.push(...this.workspaceContextService.getWorkspace().folders.map((folder, index) => { return { id: 'folderSettingsTarget' + index, - label: getSettingsTargetName(ConfigurationTarget.FOLDER, root, this.workspaceContextService), - checked: this.uri.fsPath === root.fsPath, + label: getSettingsTargetName(ConfigurationTarget.FOLDER, folder, this.workspaceContextService), + checked: this.uri.fsPath === folder.fsPath, enabled: true, - run: () => this.onTargetClicked(root) + run: () => this.onTargetClicked(folder) }; })); } diff --git a/src/vs/workbench/parts/preferences/common/preferences.ts b/src/vs/workbench/parts/preferences/common/preferences.ts index 7037e86c7e7..ec69c7a8cb8 100644 --- a/src/vs/workbench/parts/preferences/common/preferences.ts +++ b/src/vs/workbench/parts/preferences/common/preferences.ts @@ -107,8 +107,8 @@ export function getSettingsTargetName(target: ConfigurationTarget, resource: URI case ConfigurationTarget.WORKSPACE: return localize('workspaceSettingsTarget', "Workspace Settings"); case ConfigurationTarget.FOLDER: - const root = workspaceContextService.getRoot(resource); - return root ? paths.basename(root.fsPath) : ''; + const folder = workspaceContextService.getWorkspaceFolder(resource); + return folder ? paths.basename(folder.fsPath) : ''; } } diff --git a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts index eaa5f82e0e7..f5dc4573e53 100644 --- a/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts +++ b/src/vs/workbench/parts/relauncher/electron-browser/relauncher.contribution.ts @@ -30,8 +30,8 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private nativeTabs: boolean; private updateChannel: string; private enableCrashReporter: boolean; - private rootCount: number; - private firstRootPath: string; + private foldersCount: number; + private firstFolderPath: string; constructor( @IWindowsService private windowsService: IWindowsService, @@ -44,8 +44,8 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { @IExtensionService private extensionService: IExtensionService ) { const workspace = this.contextService.getWorkspace(); - this.rootCount = workspace.roots.length; - this.firstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; + this.foldersCount = workspace.folders.length; + this.firstFolderPath = workspace.folders.length > 0 ? workspace.folders[0].fsPath : void 0; this.onConfigurationChange(configurationService.getConfiguration(), false); @@ -54,7 +54,7 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { private registerListeners(): void { this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration(), true))); - this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots())); + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); } private onConfigurationChange(config: IConfiguration, notify: boolean): void { @@ -95,27 +95,27 @@ export class SettingsChangeRelauncher implements IWorkbenchContribution { } } - private onDidChangeWorkspaceRoots(): void { + private onDidChangeWorkspaceFolders(): void { const workspace = this.contextService.getWorkspace(); - const newRootCount = workspace.roots.length; - const newFirstRootPath = workspace.roots.length > 0 ? workspace.roots[0].fsPath : void 0; + const newFoldersCount = workspace.folders.length; + const newFirstFolderPath = workspace.folders.length > 0 ? workspace.folders[0].fsPath : void 0; let reloadWindow = false; let reloadExtensionHost = false; - if (this.rootCount === 0 && newRootCount > 0) { + if (this.foldersCount === 0 && newFoldersCount > 0) { reloadWindow = true; // transition: from 0 folders to 1+ - } else if (this.rootCount > 0 && newRootCount === 0) { + } else if (this.foldersCount > 0 && newFoldersCount === 0) { reloadWindow = true; // transition: from 1+ folders to 0 } - if (this.firstRootPath !== newFirstRootPath) { + if (this.firstFolderPath !== newFirstFolderPath) { reloadExtensionHost = true; // first root folder changed (impact on deprecated workspace.rootPath API) } - this.rootCount = newRootCount; - this.firstRootPath = newFirstRootPath; + this.foldersCount = newFoldersCount; + this.firstFolderPath = newFirstFolderPath; // Reload window if this is needed if (reloadWindow) { diff --git a/src/vs/workbench/parts/search/browser/openFileHandler.ts b/src/vs/workbench/parts/search/browser/openFileHandler.ts index e25d03cd56d..7fbbcfdbe2c 100644 --- a/src/vs/workbench/parts/search/browser/openFileHandler.ts +++ b/src/vs/workbench/parts/search/browser/openFileHandler.ts @@ -164,7 +164,7 @@ export class OpenFileHandler extends QuickOpenHandler { iconClass = 'file'; // only use a generic file icon if we are forced to use an icon and have no icon theme set otherwise } - const folderResources = this.contextService.getWorkspace().roots; + const folderResources = this.contextService.getWorkspace().folders; return this.searchService.search(this.queryBuilder.file(folderResources, query)).then((complete) => { const results: QuickOpenEntry[] = []; for (let i = 0; i < complete.results.length; i++) { @@ -199,7 +199,7 @@ export class OpenFileHandler extends QuickOpenHandler { useRipgrep: this.experimentService.getExperiments().ripgrepQuickSearch }; - const folderResources = this.contextService.getWorkspace().roots; + const folderResources = this.contextService.getWorkspace().folders; const query = this.queryBuilder.file(folderResources, options); return query; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 27a1845e66c..e550acb92fb 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -874,19 +874,19 @@ export class SearchViewlet extends Viewlet { if (resource) { if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { // Show relative path from the root for single-root mode - folderPath = paths.relative(workspace.roots[0].fsPath, resource.fsPath); + folderPath = paths.relative(workspace.folders[0].fsPath, resource.fsPath); if (folderPath && folderPath !== '.') { folderPath = './' + folderPath; } } else { - const owningRoot = this.contextService.getRoot(resource); - if (owningRoot) { - const owningRootBasename = paths.basename(owningRoot.fsPath); + const owningFolder = this.contextService.getWorkspaceFolder(resource); + if (owningFolder) { + const owningRootBasename = paths.basename(owningFolder.fsPath); // If this root is the only one with its basename, use a relative ./ path. If there is another, use an absolute path - const isUniqueRoot = workspace.roots.filter(root => paths.basename(root.fsPath) === owningRootBasename).length === 1; - if (isUniqueRoot) { - folderPath = `./${owningRootBasename}/${paths.relative(owningRoot.fsPath, resource.fsPath)}`; + const isUniqueFolder = workspace.folders.filter(root => paths.basename(root.fsPath) === owningRootBasename).length === 1; + if (isUniqueFolder) { + folderPath = `./${owningRootBasename}/${paths.relative(owningFolder.fsPath, resource.fsPath)}`; } else { folderPath = resource.fsPath; } @@ -960,7 +960,7 @@ export class SearchViewlet extends Viewlet { excludePattern, includePattern }; - const folderResources = this.contextService.getWorkspace().roots; + const folderResources = this.contextService.getWorkspace().folders; const onQueryValidationError = (err: Error) => { this.searchWidget.searchInput.showMessage({ content: err.message, type: MessageType.ERROR }); diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index 9acbb706f52..49fa52d03d5 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -214,14 +214,14 @@ export class QueryBuilder { if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.FOLDER) { // TODO: @Sandy Try checking workspace folders length instead. return [paths.normalize( - paths.join(this.workspaceContextService.getWorkspace().roots[0].fsPath, searchPath))]; + paths.join(this.workspaceContextService.getWorkspace().folders[0].fsPath, searchPath))]; } else if (searchPath === './') { return []; // ./ or ./**/foo makes sense for single-folder but not multi-folder workspaces } else { const relativeSearchPathMatch = searchPath.match(/\.[\/\\]([^\/\\]+)([\/\\].+)?/); if (relativeSearchPathMatch) { const searchPathRoot = relativeSearchPathMatch[1]; - const matchingRoots = this.workspaceContextService.getWorkspace().roots.filter(root => paths.basename(root.fsPath) === searchPathRoot); + const matchingRoots = this.workspaceContextService.getWorkspace().folders.filter(folder => paths.basename(folder.fsPath) === searchPathRoot); if (matchingRoots.length) { return matchingRoots.map(root => { return relativeSearchPathMatch[2] ? diff --git a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts index 9a492fa3f65..8c79981d63f 100644 --- a/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts +++ b/src/vs/workbench/parts/search/test/common/queryBuilder.test.ts @@ -154,7 +154,7 @@ suite('QueryBuilder', () => { const ROOT_2_URI = getUri(ROOT_2); const ROOT_3 = fixPath('/project/root3'); const ROOT_3_URI = getUri(ROOT_3); - mockWorkspace.roots = [ROOT_1_URI, ROOT_2_URI, ROOT_3_URI]; + mockWorkspace.folders = [ROOT_1_URI, ROOT_2_URI, ROOT_3_URI]; mockWorkspace.configuration = uri.file(fixPath('/config')); mockConfigService.setUserConfiguration('search', { @@ -473,7 +473,7 @@ suite('QueryBuilder', () => { test('relative includes w/two root folders', () => { const ROOT_2 = '/project/root2'; - mockWorkspace.roots = [ROOT_1_URI, getUri(ROOT_2)]; + mockWorkspace.folders = [ROOT_1_URI, getUri(ROOT_2)]; mockWorkspace.configuration = uri.file(fixPath('config')); [ @@ -513,7 +513,7 @@ suite('QueryBuilder', () => { test('relative includes w/multiple ambiguous root folders', () => { const ROOT_2 = '/project/rootB'; const ROOT_3 = '/otherproject/rootB'; - mockWorkspace.roots = [ROOT_1_URI, getUri(ROOT_2), getUri(ROOT_3)]; + mockWorkspace.folders = [ROOT_1_URI, getUri(ROOT_2), getUri(ROOT_3)]; mockWorkspace.configuration = uri.file(fixPath('/config')); [ diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 001b0ed44c1..5d30f4a319b 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -301,7 +301,7 @@ class BuildStatusBarItem extends Themable implements IStatusbarItem { } private registerListeners(): void { - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.updateStyles())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateStyles())); } protected updateStyles(): void { @@ -1547,7 +1547,7 @@ class TaskService extends EventEmitter implements ITaskService { } private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().roots[0] }) : undefined; + let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().folders[0] }) : undefined; if (!result) { return { config: undefined, hasParseErrors: false }; } diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index b3f2037268f..cf38b3bcb18 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -647,7 +647,7 @@ export class TerminalTaskSystem extends EventEmitter implements ITaskSystem { private resolveVariable(value: string): string { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 - return this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], value); + return this.configurationResolverService.resolve(this.contextService.getWorkspace().folders[0], value); } private resolveOptions(options: CommandOptions): CommandOptions { diff --git a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts index 931567edb21..e0e81b063ff 100644 --- a/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts +++ b/src/vs/workbench/parts/tasks/node/processRunnerDetector.ts @@ -156,7 +156,7 @@ export class ProcessRunnerDetector { this.taskConfiguration = config; this._stderr = []; this._stdout = []; - this._cwd = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? Paths.normalize(this.contextService.getWorkspace().roots[0].fsPath, true) : ''; + this._cwd = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? Paths.normalize(this.contextService.getWorkspace().folders[0].fsPath, true) : ''; } public get stderr(): string[] { @@ -175,7 +175,7 @@ export class ProcessRunnerDetector { let isShellCommand = !!this.taskConfiguration.isShellCommand; // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 return this.runDetection( - new LineProcess(this.taskConfiguration.command, this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], args), isShellCommand, options), + new LineProcess(this.taskConfiguration.command, this.configurationResolverService.resolve(this.contextService.getWorkspace().folders[0], args), isShellCommand, options), this.taskConfiguration.command, isShellCommand, config.matcher, ProcessRunnerDetector.DefaultProblemMatchers, list); } else { if (detectSpecific) { @@ -219,10 +219,10 @@ export class ProcessRunnerDetector { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 let result = Objects.clone(options); if (result.cwd) { - result.cwd = this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], result.cwd); + result.cwd = this.configurationResolverService.resolve(this.contextService.getWorkspace().folders[0], result.cwd); } if (result.env) { - result.env = this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], result.env); + result.env = this.configurationResolverService.resolve(this.contextService.getWorkspace().folders[0], result.env); } return result; } diff --git a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts index c320299767d..e0006516a31 100644 --- a/src/vs/workbench/parts/tasks/node/processTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/node/processTaskSystem.ts @@ -382,7 +382,7 @@ export class ProcessTaskSystem extends EventEmitter implements ITaskSystem { private resolveVariable(value: string): string { // TODO@Dirk adopt new configuration resolver service https://github.com/Microsoft/vscode/issues/31365 - return this.configurationResolverService.resolve(this.contextService.getWorkspace().roots[0], value); + return this.configurationResolverService.resolve(this.contextService.getWorkspace().folders[0], value); } public log(value: string): void { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 7e811f487fc..e72503560fc 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -184,8 +184,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; - protected readonly _onDidChangeWorkspaceRoots: Emitter = this._register(new Emitter()); - public readonly onDidChangeWorkspaceRoots: Event = this._onDidChangeWorkspaceRoots.event; + protected readonly _onDidChangeWorkspaceFolders: Emitter = this._register(new Emitter()); + public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event; protected readonly _onDidChangeWorkspaceName: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkspaceName: Event = this._onDidChangeWorkspaceName.event; @@ -206,7 +206,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } // Folder has single root - if (this.workspace.roots.length === 1) { + if (this.workspace.folders.length === 1) { return WorkbenchState.FOLDER; } @@ -214,18 +214,18 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return WorkbenchState.EMPTY; } - public getRoot(resource: URI): URI { - return this.workspace.getRoot(resource); + public getWorkspaceFolder(resource: URI): URI { + return this.workspace.getFolder(resource); } public isInsideWorkspace(resource: URI): boolean { - return !!this.getRoot(resource); + return !!this.getWorkspaceFolder(resource); } public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { switch (this.getWorkbenchState()) { case WorkbenchState.FOLDER: - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.folders[0].fsPath, workspaceIdentifier); case WorkbenchState.WORKSPACE: return isWorkspaceIdentifier(workspaceIdentifier) && this.workspace.id === workspaceIdentifier.id; } @@ -233,8 +233,8 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } public toResource(workspaceRelativePath: string): URI { - if (this.workspace.roots.length) { - return URI.file(paths.join(this.workspace.roots[0].fsPath, workspaceRelativePath)); + if (this.workspace.folders.length) { + return URI.file(paths.join(this.workspace.folders[0].fsPath, workspaceRelativePath)); } return null; } @@ -373,7 +373,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } public getUnsupportedWorkspaceKeys(): string[] { - return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).workspaceSettingsConfig.unsupportedKeys : []; + return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.folders[0]).workspaceSettingsConfig.unsupportedKeys : []; } public initialize(trigger: boolean = true): TPromise { @@ -404,9 +404,9 @@ export class WorkspaceServiceImpl extends WorkspaceService { } public handleWorkspaceFileEvents(event: FileChangesEvent): void { - TPromise.join(this.workspace.roots.map(folder => this.cachedFolderConfigs.get(folder).handleWorkspaceFileEvents(event))) // handle file event for each folder + TPromise.join(this.workspace.folders.map(folder => this.cachedFolderConfigs.get(folder).handleWorkspaceFileEvents(event))) // handle file event for each folder .then(folderConfigurations => - folderConfigurations.map((configuration, index) => ({ configuration, folder: this.workspace.roots[index] })) + folderConfigurations.map((configuration, index) => ({ configuration, folder: this.workspace.folders[index] })) .filter(folderConfiguration => !!folderConfiguration.configuration) // Filter folders which are not impacted by events .map(folderConfiguration => this.updateFolderConfiguration(folderConfiguration.folder, folderConfiguration.configuration, true)) // Update the configuration of impacted folders .reduce((result, value) => result || value, false)) // Check if the effective configuration of folder is changed @@ -416,7 +416,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { protected resetCaches(): void { this.cachedFolderConfigs = new StrictResourceMap>(); this._configuration = new Configuration(this.baseConfigurationService.configuration(), new ConfigurationModel(), new StrictResourceMap>(), this.workspace); - this.initCachesForFolders(this.workspace.roots); + this.initCachesForFolders(this.workspace.folders); } private initializeWorkspace(): TPromise { @@ -541,7 +541,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } } - protected updateConfiguration(folders: URI[] = this.workspace.roots): TPromise { + protected updateConfiguration(folders: URI[] = this.workspace.folders): TPromise { return TPromise.join([...folders.map(folder => this.cachedFolderConfigs.get(folder).loadConfiguration() .then(configuration => this.updateFolderConfiguration(folder, configuration, true)))]) .then(changed => changed.reduce((result, value) => result || value, false)) @@ -550,7 +550,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { private onBaseConfigurationChanged({ source, sourceConfig }: IConfigurationServiceEvent): void { if (source === ConfigurationSource.Default) { - this.workspace.roots.forEach(folder => this._configuration.getFolderConfigurationModel(folder).update()); + this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder).update()); } if (this._configuration.updateBaseConfiguration(this.baseConfigurationService.configuration())) { this._onDidUpdateConfiguration.fire({ source, sourceConfig }); @@ -559,12 +559,12 @@ export class WorkspaceServiceImpl extends WorkspaceService { private onWorkspaceConfigurationChanged(): void { let configuredFolders = this.parseWorkspaceFolders(this.workspaceConfiguration.workspaceConfigurationModel.folders); - const foldersChanged = !equals(this.workspace.roots, configuredFolders, (r1, r2) => r1.fsPath === r2.fsPath); + const foldersChanged = !equals(this.workspace.folders, configuredFolders, (r1, r2) => r1.fsPath === r2.fsPath); if (foldersChanged) { // TODO@Sandeep be smarter here about detecting changes - this.workspace.roots = configuredFolders; + this.workspace.folders = configuredFolders; this.onFoldersChanged() .then(configurationChanged => { - this._onDidChangeWorkspaceRoots.fire(); + this._onDidChangeWorkspaceFolders.fire(); if (configurationChanged) { this.triggerConfigurationChange(); } @@ -582,7 +582,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { // Remove the configurations of deleted folders for (const key of this.cachedFolderConfigs.keys()) { - if (!this.workspace.roots.filter(folder => folder.toString() === key.toString())[0]) { + if (!this.workspace.folders.filter(folder => folder.toString() === key.toString())[0]) { this.cachedFolderConfigs.delete(key); if (this._configuration.deleteFolderConfiguration(key)) { configurationChangedOnRemoval = true; @@ -591,7 +591,7 @@ export class WorkspaceServiceImpl extends WorkspaceService { } // Initialize the newly added folders - const toInitialize = this.workspace.roots.filter(folder => !this.cachedFolderConfigs.has(folder)); + const toInitialize = this.workspace.folders.filter(folder => !this.cachedFolderConfigs.has(folder)); if (toInitialize.length) { this.initCachesForFolders(toInitialize); return this.updateConfiguration(toInitialize) @@ -613,12 +613,12 @@ export class WorkspaceServiceImpl extends WorkspaceService { } private updateWorkspaceConfiguration(compare: boolean): boolean { - const workspaceConfiguration = this.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.roots[0]); + const workspaceConfiguration = this.getWorkbenchState() === WorkbenchState.WORKSPACE ? this.workspaceConfiguration.workspaceConfigurationModel.workspaceConfiguration : this._configuration.getFolderConfigurationModel(this.workspace.folders[0]); return this._configuration.updateWorkspaceConfiguration(workspaceConfiguration, compare); } protected triggerConfigurationChange(): void { - this._onDidUpdateConfiguration.fire({ source: ConfigurationSource.Workspace, sourceConfig: this._configuration.getFolderConfigurationModel(this.workspace.roots[0]).contents }); + this._onDidUpdateConfiguration.fire({ source: ConfigurationSource.Workspace, sourceConfig: this._configuration.getFolderConfigurationModel(this.workspace.folders[0]).contents }); } } @@ -894,7 +894,7 @@ export class Configuration extends BaseConfiguration { } deleteFolderConfiguration(folder: URI): boolean { - if (this._workspace && this._workspace.roots.length > 0 && this._workspace.roots[0].fsPath === folder.fsPath) { + if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].fsPath === folder.fsPath) { // Do not remove workspace configuration return false; } diff --git a/src/vs/workbench/services/configuration/node/configurationEditingService.ts b/src/vs/workbench/services/configuration/node/configurationEditingService.ts index c08df2e04c3..113aeeacda5 100644 --- a/src/vs/workbench/services/configuration/node/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/node/configurationEditingService.ts @@ -333,14 +333,14 @@ export class ConfigurationEditingService implements IConfigurationEditingService const workspace = this.contextService.getWorkspace(); if (target === ConfigurationTarget.WORKSPACE) { - return workspace.configuration || this.toResource(relativePath, workspace.roots[0]); + return workspace.configuration || this.toResource(relativePath, workspace.folders[0]); } if (target === ConfigurationTarget.FOLDER && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { if (resource) { - const root = this.contextService.getRoot(resource); - if (root) { - return this.toResource(relativePath, root); + const folder = this.contextService.getWorkspaceFolder(resource); + if (folder) { + return this.toResource(relativePath, folder); } } } @@ -348,7 +348,7 @@ export class ConfigurationEditingService implements IConfigurationEditingService return null; } - private toResource(relativePath: string, root: URI): URI { - return URI.file(paths.join(root.fsPath, relativePath)); + private toResource(relativePath: string, folder: URI): URI { + return URI.file(paths.join(folder.fsPath, relativePath)); } } diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index c6b81d34478..980b301890a 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -133,21 +133,21 @@ export class FileService implements IFileService { this.toUnbind.push(this.editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); // Root changes - this.toUnbind.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots())); + this.toUnbind.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); // Lifecycle this.lifecycleService.onShutdown(this.dispose, this); } - private onDidChangeWorkspaceRoots(): void { + private onDidChangeWorkspaceFolders(): void { this.updateOptions({ encodingOverride: this.getEncodingOverrides() }); } private getEncodingOverrides(): IEncodingOverride[] { const encodingOverride: IEncodingOverride[] = []; encodingOverride.push({ resource: uri.file(this.environmentService.appSettingsHome), encoding: encoding.UTF8 }); - this.contextService.getWorkspace().roots.forEach(root => { - encodingOverride.push({ resource: uri.file(paths.join(root.fsPath, '.vscode')), encoding: encoding.UTF8 }); + this.contextService.getWorkspace().folders.forEach(folder => { + encodingOverride.push({ resource: uri.file(paths.join(folder.fsPath, '.vscode')), encoding: encoding.UTF8 }); }); return encodingOverride; diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index 59010bd922b..02be0c0be68 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -90,7 +90,7 @@ export class FileService implements IFileService { private undeliveredRawFileChangesEvents: IRawFileChange[]; private activeWorkspaceChangeWatcher: IDisposable; - private currentWorkspaceRootsCount: number; + private currentWorkspaceFoldersCount: number; constructor( private contextService: IWorkspaceContextService, @@ -101,7 +101,7 @@ export class FileService implements IFileService { this.toDispose = []; this.options = options || Object.create(null); this.tmpPath = this.options.tmpDir || os.tmpdir(); - this.currentWorkspaceRootsCount = contextService.getWorkspace().roots.length; + this.currentWorkspaceFoldersCount = contextService.getWorkspace().folders.length; this._onFileChanges = new Emitter(); this.toDispose.push(this._onFileChanges); @@ -113,7 +113,7 @@ export class FileService implements IFileService { this.options.errorLogger = console.error; } - if (this.currentWorkspaceRootsCount > 0 && !this.options.disableWatcher) { + if (this.currentWorkspaceFoldersCount > 0 && !this.options.disableWatcher) { this.setupWorkspaceWatching(); } @@ -125,16 +125,16 @@ export class FileService implements IFileService { } private registerListeners(): void { - this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => this.onDidChangeWorkspaceRoots())); + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders())); } - private onDidChangeWorkspaceRoots(): void { - const newRootCount = this.contextService.getWorkspace().roots.length; + private onDidChangeWorkspaceFolders(): void { + const newFoldersCount = this.contextService.getWorkspace().folders.length; let restartWorkspaceWatcher = false; - if (this.currentWorkspaceRootsCount <= 1 && newRootCount > 1) { + if (this.currentWorkspaceFoldersCount <= 1 && newFoldersCount > 1) { restartWorkspaceWatcher = true; // transition: from 1 or 0 folders to 2+ - } else if (this.currentWorkspaceRootsCount > 1 && newRootCount <= 1) { + } else if (this.currentWorkspaceFoldersCount > 1 && newFoldersCount <= 1) { restartWorkspaceWatcher = true; // transition: from 2+ folders to 1 or 0 } @@ -142,7 +142,7 @@ export class FileService implements IFileService { this.setupWorkspaceWatching(); } - this.currentWorkspaceRootsCount = newRootCount; + this.currentWorkspaceFoldersCount = newFoldersCount; } public get onFileChanges(): Event { @@ -167,7 +167,7 @@ export class FileService implements IFileService { } // new watcher: use it if setting tells us so or we run in multi-root environment - if (this.options.useExperimentalFileWatcher || this.contextService.getWorkspace().roots.length > 1) { + if (this.options.useExperimentalFileWatcher || this.contextService.getWorkspace().folders.length > 1) { this.activeWorkspaceChangeWatcher = toDisposable(this.setupNsfwWorkspaceWatching().startWatching()); } diff --git a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts index b3f8c608892..6a52fff3712 100644 --- a/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/nsfw/watcherService.ts @@ -81,30 +81,30 @@ export class FileWatcher { }); // Start watching - this.updateRoots(); - this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => this.updateRoots())); - this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.updateRoots())); + this.updateFolders(); + this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateFolders())); + this.toDispose.push(this.configurationService.onDidUpdateConfiguration(() => this.updateFolders())); return () => this.dispose(); } - private updateRoots() { + private updateFolders() { if (this.isDisposed) { return; } - const roots = this.contextService.getWorkspace().roots; - this.service.setRoots(roots.map(root => { + const folders = this.contextService.getWorkspace().folders; + this.service.setRoots(folders.map(folder => { // Fetch the root's watcherExclude setting and return it const configuration = this.configurationService.getConfiguration(undefined, { - resource: root + resource: folder }); let ignored: string[] = []; if (configuration.files && configuration.files.watcherExclude) { ignored = Object.keys(configuration.files.watcherExclude).filter(k => !!configuration.files.watcherExclude[k]); } return { - basePath: root.fsPath, + basePath: folder.fsPath, ignored }; })); diff --git a/src/vs/workbench/services/files/node/watcher/unix/watcherService.ts b/src/vs/workbench/services/files/node/watcher/unix/watcherService.ts index 0f96d2c3b9c..a330c432f4f 100644 --- a/src/vs/workbench/services/files/node/watcher/unix/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/unix/watcherService.ts @@ -52,7 +52,7 @@ export class FileWatcher { const service = new WatcherChannelClient(channel); // Start watching - const basePath: string = normalize(this.contextService.getWorkspace().roots[0].fsPath); + const basePath: string = normalize(this.contextService.getWorkspace().folders[0].fsPath); service.watch({ basePath: basePath, ignored: this.ignored, verboseLogging: this.verboseLogging }).then(null, err => { if (!this.isDisposed && !(err instanceof Error && err.name === 'Canceled' && err.message === 'Canceled')) { return TPromise.wrapError(err); // the service lib uses the promise cancel error to indicate the process died, we do not want to bubble this up diff --git a/src/vs/workbench/services/files/node/watcher/win32/watcherService.ts b/src/vs/workbench/services/files/node/watcher/win32/watcherService.ts index 54ba8d297fd..e0b3b87fbee 100644 --- a/src/vs/workbench/services/files/node/watcher/win32/watcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/win32/watcherService.ts @@ -26,7 +26,7 @@ export class FileWatcher { } public startWatching(): () => void { - let basePath: string = normalize(this.contextService.getWorkspace().roots[0].fsPath); + let basePath: string = normalize(this.contextService.getWorkspace().folders[0].fsPath); if (basePath && basePath.indexOf('\\\\') === 0 && endsWith(basePath, sep)) { // for some weird reason, node adds a trailing slash to UNC paths diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 9cb7d80137c..726f54f8002 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -781,13 +781,13 @@ export class HistoryService extends BaseHistoryService implements IHistoryServic } const resourceInput = input as IResourceInput; - const resourceWorkspace = this.contextService.getRoot(resourceInput.resource); + const resourceWorkspace = this.contextService.getWorkspaceFolder(resourceInput.resource); if (resourceWorkspace) { return resourceWorkspace; } } // fallback to first workspace - return this.contextService.getWorkspace().roots[0]; + return this.contextService.getWorkspace().folders[0]; } } diff --git a/src/vs/workbench/services/telemetry/common/workspaceStats.ts b/src/vs/workbench/services/telemetry/common/workspaceStats.ts index 6246daee2b6..9975ddf8c80 100644 --- a/src/vs/workbench/services/telemetry/common/workspaceStats.ts +++ b/src/vs/workbench/services/telemetry/common/workspaceStats.ts @@ -154,10 +154,10 @@ export class WorkspaceStats { const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; const workspace = this.contextService.getWorkspace(); - tags['workspace.roots'] = isEmpty ? 0 : workspace.roots.length; + tags['workspace.roots'] = isEmpty ? 0 : workspace.folders.length; tags['workspace.empty'] = isEmpty; - const folders = !isEmpty ? workspace.roots : this.environmentService.appQuality !== 'stable' && this.findFolders(configuration); + const folders = !isEmpty ? workspace.folders : this.environmentService.appQuality !== 'stable' && this.findFolders(configuration); if (folders && folders.length && this.fileService) { return this.fileService.resolveFiles(folders.map(resource => ({ resource }))).then(results => { const names = ([]).concat(...results.map(result => result.success ? (result.stat.children || []) : [])).map(c => c.name); @@ -324,7 +324,7 @@ export class WorkspaceStats { } public reportCloudStats(): void { - const uris = this.contextService.getWorkspace().roots; + const uris = this.contextService.getWorkspace().folders; if (uris && uris.length && this.fileService) { this.reportRemoteDomains(uris); this.reportRemotes(uris); diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 364f9b8c6dd..d112fa773c7 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -745,8 +745,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } // Check for workspace settings file - return this.contextService.getWorkspace().roots.some(root => { - return paths.isEqualOrParent(this.resource.fsPath, path.join(root.fsPath, '.vscode')); + return this.contextService.getWorkspace().folders.some(folder => { + return paths.isEqualOrParent(this.resource.fsPath, path.join(folder.fsPath, '.vscode')); }); } diff --git a/src/vs/workbench/services/workspace/common/workspaceEditing.ts b/src/vs/workbench/services/workspace/common/workspaceEditing.ts index f3ed40ee523..6be9313390f 100644 --- a/src/vs/workbench/services/workspace/common/workspaceEditing.ts +++ b/src/vs/workbench/services/workspace/common/workspaceEditing.ts @@ -16,14 +16,14 @@ export interface IWorkspaceEditingService { _serviceBrand: ServiceIdentifier; /** - * add roots to the existing workspace + * add folders to the existing workspace */ - addRoots(roots: URI[]): TPromise; + addFolders(folders: URI[]): TPromise; /** - * remove roots from the existing workspace + * remove folders from the existing workspace */ - removeRoots(roots: URI[]): TPromise; + removeFolders(folders: URI[]): TPromise; } export const IWorkspaceMigrationService = createDecorator('workspaceMigrationService'); diff --git a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts index d851cd92cce..ffd1ff7c3b4 100644 --- a/src/vs/workbench/services/workspace/node/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/node/workspaceEditingService.ts @@ -31,25 +31,25 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { ) { } - public addRoots(rootsToAdd: URI[]): TPromise { + public addFolders(foldersToAdd: URI[]): TPromise { if (!this.isSupported()) { return TPromise.as(void 0); // we need a workspace to begin with } - const roots = this.contextService.getWorkspace().roots; + const folders = this.contextService.getWorkspace().folders; - return this.doSetRoots([...roots, ...rootsToAdd]); + return this.doSetFolders([...folders, ...foldersToAdd]); } - public removeRoots(rootsToRemove: URI[]): TPromise { + public removeFolders(foldersToRemove: URI[]): TPromise { if (!this.isSupported()) { return TPromise.as(void 0); // we need a workspace to begin with } - const roots = this.contextService.getWorkspace().roots; - const rootsToRemoveRaw = rootsToRemove.map(root => root.toString()); + const folders = this.contextService.getWorkspace().folders; + const foldersToRemoveRaw = foldersToRemove.map(folder => folder.toString()); - return this.doSetRoots(roots.filter(root => rootsToRemoveRaw.indexOf(root.toString()) === -1)); + return this.doSetFolders(folders.filter(folder => foldersToRemoveRaw.indexOf(folder.toString()) === -1)); } private isSupported(): boolean { @@ -59,41 +59,41 @@ export class WorkspaceEditingService implements IWorkspaceEditingService { ); } - private doSetRoots(newRoots: URI[]): TPromise { + private doSetFolders(newFolders: URI[]): TPromise { const workspace = this.contextService.getWorkspace(); - const currentWorkspaceRoots = this.contextService.getWorkspace().roots.map(root => root.fsPath); - const newWorkspaceRoots = this.validateRoots(newRoots); + const currentWorkspaceFolders = this.contextService.getWorkspace().folders.map(folder => folder.fsPath); + const newWorkspaceFolders = this.validateFolders(newFolders); // See if there are any changes - if (equals(currentWorkspaceRoots, newWorkspaceRoots)) { + if (equals(currentWorkspaceFolders, newWorkspaceFolders)) { return TPromise.as(void 0); } // Apply to config - if (newWorkspaceRoots.length) { + if (newWorkspaceFolders.length) { const workspaceConfigFolder = dirname(workspace.configuration.fsPath); - const value: IStoredWorkspaceFolder[] = newWorkspaceRoots.map(newWorkspaceRoot => { - if (isEqualOrParent(newWorkspaceRoot, workspaceConfigFolder, !isLinux)) { - newWorkspaceRoot = relative(workspaceConfigFolder, newWorkspaceRoot) || '.'; // absolute paths get converted to relative ones to workspace location if possible + const value: IStoredWorkspaceFolder[] = newWorkspaceFolders.map(newWorkspaceFolder => { + if (isEqualOrParent(newWorkspaceFolder, workspaceConfigFolder, !isLinux)) { + newWorkspaceFolder = relative(workspaceConfigFolder, newWorkspaceFolder) || '.'; // absolute paths get converted to relative ones to workspace location if possible } - return { path: newWorkspaceRoot }; + return { path: newWorkspaceFolder }; }); return this.jsonEditingService.write(workspace.configuration, { key: 'folders', value }, true); } else { - // TODO: Sandeep - Removing all roots? + // TODO: Sandeep - Removing all folders? } return TPromise.as(null); } - private validateRoots(roots: URI[]): string[] { - if (!roots) { + private validateFolders(folders: URI[]): string[] { + if (!folders) { return []; } // Prevent duplicates - return distinct(roots.map(root => root.fsPath), root => isLinux ? root : root.toLowerCase()); + return distinct(folders.map(folder => folder.fsPath), folder => isLinux ? folder : folder.toLowerCase()); } } diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index 8f7c6e4163f..d854c4ec6f1 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -131,7 +131,7 @@ suite('ExtHostConfiguration', function () { new class extends mock() { }, new ExtHostWorkspace(new TestThreadService(), { 'id': 'foo', - 'roots': [URI.file('foo')], + 'folders': [URI.file('foo')], 'name': 'foo' }), { @@ -203,7 +203,7 @@ suite('ExtHostConfiguration', function () { new class extends mock() { }, new ExtHostWorkspace(new TestThreadService(), { 'id': 'foo', - 'roots': [firstRoot, secondRoot], + 'folders': [firstRoot, secondRoot], 'name': 'foo' }), { diff --git a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts index ee65bea102b..dcde31bf2a6 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostWorkspace.test.ts @@ -24,7 +24,7 @@ suite('ExtHostWorkspace', function () { test('asRelativePath', function () { - const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file('/Coding/Applications/NewsWoWBot')], name: 'Test' }); + const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file('/Coding/Applications/NewsWoWBot')], name: 'Test' }); assertAsRelativePath(ws, '/Coding/Applications/NewsWoWBot/bernd/das/brot', 'bernd/das/brot'); assertAsRelativePath(ws, '/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart', @@ -38,7 +38,7 @@ suite('ExtHostWorkspace', function () { test('asRelativePath, same paths, #11402', function () { const root = '/home/aeschli/workspaces/samples/docker'; const input = '/home/aeschli/workspaces/samples/docker'; - const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file(root)], name: 'Test' }); + const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file(root)], name: 'Test' }); assertAsRelativePath(ws, (input), input); @@ -53,14 +53,14 @@ suite('ExtHostWorkspace', function () { }); test('asRelativePath, multiple folders', function () { - const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); + const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); assertAsRelativePath(ws, '/Coding/One/file.txt', 'One/file.txt'); assertAsRelativePath(ws, '/Coding/Two/files/out.txt', 'Two/files/out.txt'); assertAsRelativePath(ws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt'); }); test('slightly inconsistent behaviour of asRelativePath and getWorkspaceFolder, #31553', function () { - const mrws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); + const mrws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt'); assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt', true); @@ -72,7 +72,7 @@ suite('ExtHostWorkspace', function () { assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', true); assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', false); - const srws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file('/Coding/One')], name: 'Test' }); + const srws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file('/Coding/One')], name: 'Test' }); assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt'); assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt', false); assertAsRelativePath(srws, '/Coding/One/file.txt', 'One/file.txt', true); @@ -82,7 +82,7 @@ suite('ExtHostWorkspace', function () { }); test('getPath, legacy', function () { - let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [] }); + let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [] }); assert.equal(ws.getPath(), undefined); ws = new ExtHostWorkspace(new TestThreadService(), null); @@ -91,15 +91,15 @@ suite('ExtHostWorkspace', function () { ws = new ExtHostWorkspace(new TestThreadService(), undefined); assert.equal(ws.getPath(), undefined); - ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [URI.file('Folder'), URI.file('Another/Folder')] }); + ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [URI.file('Folder'), URI.file('Another/Folder')] }); assert.equal(ws.getPath().replace(/\\/g, '/'), '/Folder'); - ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [URI.file('/Folder')] }); + ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [URI.file('/Folder')] }); assert.equal(ws.getPath().replace(/\\/g, '/'), '/Folder'); }); test('WorkspaceFolder has name and index', function () { - const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', roots: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); + const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', folders: [URI.file('/Coding/One'), URI.file('/Coding/Two')], name: 'Test' }); const [one, two] = ws.getWorkspaceFolders(); @@ -110,7 +110,7 @@ suite('ExtHostWorkspace', function () { }); test('getContainingWorkspaceFolder', function () { - const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [URI.file('/Coding/One'), URI.file('/Coding/Two'), URI.file('/Coding/Two/Nested')] }); + const ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [URI.file('/Coding/One'), URI.file('/Coding/Two'), URI.file('/Coding/Two/Nested')] }); let folder = ws.getWorkspaceFolder(URI.file('/foo/bar')); assert.equal(folder, undefined); @@ -141,13 +141,13 @@ suite('ExtHostWorkspace', function () { }); test('Multiroot change event should have a delta, #29641', function () { - let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [] }); + let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [] }); let sub = ws.onDidChangeWorkspace(e => { assert.deepEqual(e.added, []); assert.deepEqual(e.removed, []); }); - ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', roots: [] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { @@ -155,7 +155,7 @@ suite('ExtHostWorkspace', function () { assert.equal(e.added.length, 1); assert.equal(e.added[0].uri.toString(), 'foo:bar'); }); - ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', roots: [URI.parse('foo:bar')] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [URI.parse('foo:bar')] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { @@ -163,7 +163,7 @@ suite('ExtHostWorkspace', function () { assert.equal(e.added.length, 1); assert.equal(e.added[0].uri.toString(), 'foo:bar2'); }); - ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', roots: [URI.parse('foo:bar'), URI.parse('foo:bar2')] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [URI.parse('foo:bar'), URI.parse('foo:bar2')] }); sub.dispose(); sub = ws.onDidChangeWorkspace(e => { @@ -174,13 +174,13 @@ suite('ExtHostWorkspace', function () { assert.equal(e.added.length, 1); assert.equal(e.added[0].uri.toString(), 'foo:bar3'); }); - ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', roots: [URI.parse('foo:bar3')] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [URI.parse('foo:bar3')] }); sub.dispose(); }); test('Multiroot change event is immutable', function () { - let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', roots: [] }); + let ws = new ExtHostWorkspace(new TestThreadService(), { id: 'foo', name: 'Test', folders: [] }); let sub = ws.onDidChangeWorkspace(e => { assert.throws(() => { (e).added = []; @@ -189,7 +189,7 @@ suite('ExtHostWorkspace', function () { (e.added)[0] = null; }); }); - ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', roots: [] }); + ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] }); sub.dispose(); }); }); diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 18c26611255..d9ef1d58aff 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -73,25 +73,25 @@ export class TestContextService implements IWorkspaceContextService { private options: any; private _onDidChangeWorkspaceName: Emitter; - private _onDidChangeWorkspaceRoots: Emitter; + private _onDidChangeWorkspaceFolders: Emitter; constructor(workspace: any = TestWorkspace, options: any = null) { this.workspace = workspace; this.id = generateUuid(); this.options = options || Object.create(null); - this._onDidChangeWorkspaceRoots = new Emitter(); + this._onDidChangeWorkspaceFolders = new Emitter(); } public get onDidChangeWorkspaceName(): Event { return this._onDidChangeWorkspaceName.event; } - public get onDidChangeWorkspaceRoots(): Event { - return this._onDidChangeWorkspaceRoots.event; + public get onDidChangeWorkspaceFolders(): Event { + return this._onDidChangeWorkspaceFolders.event; } public getFolders(): URI[] { - return this.workspace ? this.workspace.roots : []; + return this.workspace ? this.workspace.folders : []; } public getWorkbenchState(): WorkbenchState { @@ -108,8 +108,8 @@ export class TestContextService implements IWorkspaceContextService { return this.workspace; } - public getRoot(resource: URI): URI { - return this.isInsideWorkspace(resource) ? this.workspace.roots[0] : null; + public getWorkspaceFolder(resource: URI): URI { + return this.isInsideWorkspace(resource) ? this.workspace.folders[0] : null; } public setWorkspace(workspace: any): void { @@ -126,7 +126,7 @@ export class TestContextService implements IWorkspaceContextService { public isInsideWorkspace(resource: URI): boolean { if (resource && this.workspace) { - return paths.isEqualOrParent(resource.fsPath, this.workspace.roots[0].fsPath, !isLinux /* ignorecase */); + return paths.isEqualOrParent(resource.fsPath, this.workspace.folders[0].fsPath, !isLinux /* ignorecase */); } return false; @@ -137,7 +137,7 @@ export class TestContextService implements IWorkspaceContextService { } public isCurrentWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): boolean { - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.roots[0].fsPath, workspaceIdentifier); + return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && this.pathEquals(this.workspace.folders[0].fsPath, workspaceIdentifier); } private pathEquals(path1: string, path2: string): boolean { From a4e5195bde667188b498e5797cca576f753bebdf Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 14 Sep 2017 11:05:59 +0200 Subject: [PATCH 084/145] fix panel --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index b0e220c2bd5..c619e76e5e9 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1686,7 +1686,7 @@ export class EditorOptionsValidator { matchBrackets: _boolean(opts.matchBrackets, defaults.matchBrackets), find: find, colorDecorators: _boolean(opts.colorDecorators, defaults.colorDecorators), - lightbulbEnabled: _boolean(opts.lightbulb && opts.lightbulb.enabled, defaults.lightbulbEnabled) + lightbulbEnabled: _boolean(opts.lightbulb ? opts.lightbulb.enabled : false, defaults.lightbulbEnabled) }; } } From d225fc9ab2832d83626a098c25f6bf751e190485 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 14 Sep 2017 11:12:11 +0200 Subject: [PATCH 085/145] debug smoke: use fs to get launch.json content --- test/smoke/src/areas/debug/debug.test.ts | 12 +++--------- test/smoke/src/areas/debug/debug.ts | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index b5486fbe9b9..a9c9a506b90 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -9,7 +9,7 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR } from '../../spectron/application'; +import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR, WORKSPACE_PATH } from '../../spectron/application'; describe('Debug', () => { let app: SpectronApplication = new SpectronApplication(); @@ -46,14 +46,8 @@ describe('Debug', () => { await app.workbench.openFile('app.js'); await app.workbench.debug.configure(); await app.screenCapturer.capture('launch.json file'); - let json; - await app.client.waitFor(async () => { - const content = await app.workbench.editor.getEditorVisibleText(); - try { - json = JSON.parse(stripJsonComments(content)); - return true; - } catch (e) { return false; } - }, result => result); + const content = fs.readFileSync(path.join(WORKSPACE_PATH, '.vscode', 'launch.json'), 'utf8'); + const json = JSON.parse(stripJsonComments(content)); assert.equal(json.configurations[0].request, 'launch'); assert.equal(json.configurations[0].type, 'node'); diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index a119b6b4921..f7755b89c7b 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -64,7 +64,7 @@ export class Debug extends Viewlet { await this.spectron.client.waitFor(async () => { const output = await this.getConsoleOutput(); return output.join(''); - }, text => text.indexOf('Debugger listening on') >= 0); + }, text => !!text && text.indexOf('Debugger listening on') >= 0); } async stepOver(): Promise { From 2ef1c762dd6dedc953a0f06eba84271585f65b93 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 14 Sep 2017 12:08:16 +0200 Subject: [PATCH 086/145] fix compilation --- src/vs/workbench/parts/files/browser/views/explorerViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 3043425d3db..5061faf54cf 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -573,7 +573,7 @@ export class FileSorter implements ISorter { if (statA.isRoot) { if (statB.isRoot) { const ws = this.contextService.getWorkspace(); - return ws.roots.indexOf(statA.resource) - ws.roots.indexOf(statB.resource); + return ws.folders.indexOf(statA.resource) - ws.folders.indexOf(statB.resource); } return -1; } From a6dd83a983e2d77395d4b472080889ba096a0810 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 14 Sep 2017 12:09:26 +0200 Subject: [PATCH 087/145] debug smoke: remove timeouts --- test/smoke/src/areas/debug/debug.test.ts | 14 ++++---------- test/smoke/src/areas/debug/debug.ts | 9 +++++++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index a9c9a506b90..163b92f1487 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -13,6 +13,7 @@ import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR, WORKSPACE_PATH } fro describe('Debug', () => { let app: SpectronApplication = new SpectronApplication(); + let port: number; if (app.build === VSCODE_BUILD.DEV) { const extensionsPath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions'); @@ -64,15 +65,8 @@ describe('Debug', () => { }); it('start debugging', async function () { - await app.workbench.debug.startDebugging(); - - await new Promise(c => { - setTimeout(() => { - http.get(`http://localhost:3000`) - .on('error', e => void 0); - c(); - }, 400); - }); + port = await app.workbench.debug.startDebugging(); + http.get(`http://localhost:${port}`).on('error', e => void 0); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); }); @@ -99,7 +93,7 @@ describe('Debug', () => { it('continue', async function () { await app.workbench.debug.continue(); - http.get(`http://localhost:3000`).on('error', e => void 0); + http.get(`http://localhost:${port}`).on('error', e => void 0); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); }); diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index f7755b89c7b..ddca2631983 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -57,14 +57,19 @@ export class Debug extends Viewlet { await this.spectron.client.waitForElement(BREAKPOINT_GLYPH); } - async startDebugging(): Promise { + async startDebugging(): Promise { await this.spectron.client.waitAndClick(START); await this.spectron.client.waitForElement(PAUSE); await this.spectron.client.waitForElement(DEBUG_STATUS_BAR); + const portPrefix = 'Port: '; await this.spectron.client.waitFor(async () => { const output = await this.getConsoleOutput(); return output.join(''); - }, text => !!text && text.indexOf('Debugger listening on') >= 0); + }, text => !!text && text.indexOf(portPrefix) >= 0); + const output = await this.getConsoleOutput(); + const lastOutput = output.pop(); + + return lastOutput ? parseInt(lastOutput.substr(portPrefix.length)) : 3000; } async stepOver(): Promise { From 0e7d3cbef8a745913efbe8f6886accccad4feec8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 12:11:07 +0200 Subject: [PATCH 088/145] fix hanging --wait processes --- src/vs/base/node/pfs.ts | 15 +++++++++++++++ src/vs/code/electron-main/launch.ts | 9 +++++++-- src/vs/code/node/cli.ts | 10 ++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 16f8d7509be..ce1f52d799c 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -189,3 +189,18 @@ const tmpDir = os.tmpdir(); export function del(path: string, tmp = tmpDir): TPromise { return nfcall(extfs.del, path, tmp); } + +export function whenDeleted(path: string): TPromise { + + // Complete when wait marker file is deleted + return new TPromise(c => { + const interval = setInterval(() => { + fs.exists(path, exists => { + if (!exists) { + clearInterval(interval); + c(null); + } + }); + }, 1000); + }); +} \ No newline at end of file diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index 1df7365dc64..189224ef9c6 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -14,6 +14,7 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { OpenContext } from 'vs/platform/windows/common/windows'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { whenDeleted } from 'vs/base/node/pfs'; export const ID = 'launchService'; export const ILaunchService = createDecorator(ID); @@ -113,9 +114,13 @@ export class LaunchService implements ILaunchService { } // If the other instance is waiting to be killed, we hook up a window listener if one window - // is being used and only then resolve the startup promise which will kill this second instance + // is being used and only then resolve the startup promise which will kill this second instance. + // In addition, we poll for the wait marker file to be deleted to return. if (args.wait && usedWindows.length === 1 && usedWindows[0]) { - return this.windowsService.waitForWindowCloseOrLoad(usedWindows[0].id); + return TPromise.any([ + this.windowsService.waitForWindowCloseOrLoad(usedWindows[0].id), + whenDeleted(args.waitMarkerFilePath) + ]).then(() => void 0, () => void 0); } return TPromise.as(null); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index d0f0416e6ff..7476115fcee 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -14,6 +14,7 @@ import pkg from 'vs/platform/node/package'; import * as fs from 'fs'; import * as paths from 'path'; import * as os from 'os'; +import { whenDeleted } from 'vs/base/node/pfs'; function shouldSpawnCliProcess(argv: ParsedArgs): boolean { return argv['list-extensions'] || !!argv['install-extension'] || !!argv['uninstall-extension']; @@ -105,14 +106,7 @@ export function main(argv: string[]): TPromise { child.once('exit', () => c(null)); // Complete when wait marker file is deleted - const interval = setInterval(() => { - fs.exists(waitMarkerFilePath, exists => { - if (!exists) { - clearInterval(interval); - c(null); - } - }); - }, 1000); + whenDeleted(waitMarkerFilePath).done(c, c); }); } } From a0b3c401c380106d915183d3f446aeb3013fcad2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 14:37:07 +0200 Subject: [PATCH 089/145] less verbose tests --- .../test/electron-browser/terminalLinkHandler.test.ts | 2 +- .../test/browser/parts/editor/baseEditor.test.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts index ba9f623fb9f..77d9fed7145 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -152,7 +152,7 @@ suite('Workbench - TerminalLinkHandler', () => { linkUrls.forEach(linkUrl => { supportedLinkFormats.forEach(linkFormatInfo => { - console.log('linkFormatInfo: ', linkFormatInfo); + // console.log('linkFormatInfo: ', linkFormatInfo); testLink( strings.format(linkFormatInfo.urlFormat, linkUrl, linkFormatInfo.line, linkFormatInfo.column), linkUrl, diff --git a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts index 66589da8664..7a889e4f0df 100644 --- a/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/baseEditor.test.ts @@ -14,10 +14,10 @@ import * as Platform from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; +import URI from 'vs/base/common/uri'; const NullThemeService = new TestThemeService(); @@ -165,10 +165,10 @@ suite('Workbench BaseEditor', () => { let inst = new TestInstantiationService(); - inst.createInstance(EditorRegistry.getEditor(inst.createInstance(MyResourceInput, 'fake', '', '', PLAINTEXT_MODE_ID, false)), 'id').then(editor => { + inst.createInstance(EditorRegistry.getEditor(inst.createInstance(MyResourceInput, 'fake', '', URI.file('/fake'))), 'id').then(editor => { assert.strictEqual(editor.getId(), 'myEditor'); - return inst.createInstance(EditorRegistry.getEditor(inst.createInstance(ResourceEditorInput, 'fake', '', '', PLAINTEXT_MODE_ID, false)), 'id').then(editor => { + return inst.createInstance(EditorRegistry.getEditor(inst.createInstance(ResourceEditorInput, 'fake', '', URI.file('/fake'))), 'id').then(editor => { assert.strictEqual(editor.getId(), 'myOtherEditor'); (EditorRegistry).setEditors(oldEditors); @@ -186,7 +186,7 @@ suite('Workbench BaseEditor', () => { let inst = new TestInstantiationService(); - inst.createInstance(EditorRegistry.getEditor(inst.createInstance(MyResourceInput, 'fake', '', '', PLAINTEXT_MODE_ID, false)), 'id').then(editor => { + inst.createInstance(EditorRegistry.getEditor(inst.createInstance(MyResourceInput, 'fake', '', URI.file('/fake'))), 'id').then(editor => { assert.strictEqual('myOtherEditor', editor.getId()); (EditorRegistry).setEditors(oldEditors); From 3854794379645ec9357ae232af3b064ea90cf5ff Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 14 Sep 2017 15:05:57 +0200 Subject: [PATCH 090/145] [file icons] annotate schema with 'color' format --- src/vs/workbench/services/themes/common/fileIconThemeSchema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts b/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts index 8233a577d9e..263f48a9b35 100644 --- a/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts +++ b/src/vs/workbench/services/themes/common/fileIconThemeSchema.ts @@ -167,6 +167,7 @@ const schema: IJSONSchema = { }, fontColor: { type: 'string', + format: 'color', description: nls.localize('schema.fontColor', 'When using a glyph font: The color to use.') }, fontSize: { From c75b1558e8cbebd8737aebf478db4ff6b5f56d61 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 14 Sep 2017 15:08:36 +0200 Subject: [PATCH 091/145] debug: remove stale focus code for no folder workspace --- src/vs/workbench/parts/debug/browser/debugViewlet.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugViewlet.ts b/src/vs/workbench/parts/debug/browser/debugViewlet.ts index a97e3d17f85..d0ff9fd24e1 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewlet.ts @@ -56,10 +56,6 @@ export class DebugViewlet extends PersistentViewsViewlet { public focus(): void { super.focus(); - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { - this.views[0].focusBody(); - } - if (this.startDebugActionItem) { this.startDebugActionItem.focus(); } From 74bd9fe9a6ba2196f7d9d60c1d321032dd141b2c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 14 Sep 2017 15:26:37 +0200 Subject: [PATCH 092/145] smoke: - introduce data-uri attribute in editor to know if the editor is ready - fix editor focus class name issue --- src/vs/editor/browser/view/viewImpl.ts | 5 +++-- src/vs/editor/browser/widget/codeEditorWidget.ts | 1 + test/smoke/package.json | 3 ++- test/smoke/src/areas/debug/debug.test.ts | 4 ++-- test/smoke/src/areas/editor/editor.ts | 7 +++++++ test/smoke/src/areas/explorer/explorer.ts | 10 ++-------- test/smoke/src/areas/workbench/workbench.ts | 7 ++++++- 7 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index b8c5900a2d2..79cf5f2c105 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -308,7 +308,8 @@ export class View extends ViewEventHandler { } private getEditorClassName() { - return this._context.configuration.editor.editorClassName + ' ' + getThemeTypeSelector(this._context.theme.type); + let focused = this._textAreaHandler.isFocused() ? ' focused' : ''; + return this._context.configuration.editor.editorClassName + ' ' + getThemeTypeSelector(this._context.theme.type) + focused; } // --- begin event handlers @@ -323,7 +324,7 @@ export class View extends ViewEventHandler { return false; } public onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean { - this.domNode.toggleClassName('focused', e.isFocused); + this.domNode.setClassName(this.getEditorClassName()); if (e.isFocused) { this.outgoingEvents.emitViewFocusGained(); } else { diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index fe646ba39e4..22efae7b65e 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -400,6 +400,7 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito this._view.render(false, true); this.hasView = true; + this._view.domNode.domNode.setAttribute('data-uri', model.uri.toString()); } } diff --git a/test/smoke/package.json b/test/smoke/package.json index 6237dc93093..1ab31447938 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -23,6 +23,7 @@ "spectron": "~3.6.4", "strip-json-comments": "^2.0.1", "tmp": "0.0.33", - "typescript": "^2.2.2" + "typescript": "^2.2.2", + "vscode-uri": "^1.0.1" } } diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 163b92f1487..e3f2a52b980 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -9,7 +9,7 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR, WORKSPACE_PATH } from '../../spectron/application'; +import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR } from '../../spectron/application'; describe('Debug', () => { let app: SpectronApplication = new SpectronApplication(); @@ -47,7 +47,7 @@ describe('Debug', () => { await app.workbench.openFile('app.js'); await app.workbench.debug.configure(); await app.screenCapturer.capture('launch.json file'); - const content = fs.readFileSync(path.join(WORKSPACE_PATH, '.vscode', 'launch.json'), 'utf8'); + const content = await app.workbench.editor.getEditorVisibleText(); const json = JSON.parse(stripJsonComments(content)); assert.equal(json.configurations[0].request, 'launch'); diff --git a/test/smoke/src/areas/editor/editor.ts b/test/smoke/src/areas/editor/editor.ts index 36b326b2f56..e37d916cedf 100644 --- a/test/smoke/src/areas/editor/editor.ts +++ b/test/smoke/src/areas/editor/editor.ts @@ -102,6 +102,13 @@ export class Editor { await this.spectron.client.waitAndClick(selector); } + public async getFocusedEditorUri(): Promise { + return this.spectron.webclient.selectorExecute(`.editor-container .monaco-editor.focused`, (elements: HTMLElement[]) => { + elements = Array.isArray(elements) ? elements : [elements]; + return elements[0].getAttribute('data-uri'); + }); + } + private async getClassSelectors(term: string, viewline: number): Promise { const result: { text: string, className: string }[] = await this.spectron.webclient.selectorExecute(`${Editor.VIEW_LINES}>:nth-child(${viewline}) span span`, elements => (Array.isArray(elements) ? elements : [elements]) diff --git a/test/smoke/src/areas/explorer/explorer.ts b/test/smoke/src/areas/explorer/explorer.ts index d59f02244d2..904afdbc170 100644 --- a/test/smoke/src/areas/explorer/explorer.ts +++ b/test/smoke/src/areas/explorer/explorer.ts @@ -25,14 +25,8 @@ export class Explorer extends Viewlet { } public async openFile(fileName: string): Promise { - let selector = `div[class="monaco-icon-label file-icon ${fileName}-name-file-icon ${this.getExtensionSelector(fileName)} explorer-item"]`; - try { - await this.spectron.client.doubleClickAndWait(selector); - await this.spectron.client.waitForElement(`.tabs-container div[aria-label="${fileName}, tab"]`); - await this.spectron.client.waitForElement(`.monaco-editor.focused`); - } catch (e) { - return Promise.reject(`Cannot fine ${fileName} in a viewlet.`); - } + await this.spectron.client.doubleClickAndWait(`div[class="monaco-icon-label file-icon ${fileName}-name-file-icon ${this.getExtensionSelector(fileName)} explorer-item"]`); + await this.spectron.workbench.waitForEditorFocus(fileName); } public getExtensionSelector(fileName: string): string { diff --git a/test/smoke/src/areas/workbench/workbench.ts b/test/smoke/src/areas/workbench/workbench.ts index bf8743e6d8f..1d04da84db5 100644 --- a/test/smoke/src/areas/workbench/workbench.ts +++ b/test/smoke/src/areas/workbench/workbench.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as path from 'path'; +import URI from 'vscode-uri'; import { SpectronApplication } from '../../spectron/application'; import { Explorer } from '../explorer/explorer'; import { ActivityBar } from '../activitybar/activityBar'; @@ -68,7 +70,10 @@ export class Workbench { public async waitForEditorFocus(fileName: string, untitled: boolean = false): Promise { await this.waitForActiveTab(fileName); - await this.spectron.client.waitForElement(`.editor-container[aria-label="${fileName}. ${untitled ? 'Untitled file text editor.' : 'Text file editor.'}, Group 1."] .monaco-editor textarea:focus`); + await this.spectron.client.waitFor(async () => { + const uri = await this.editor.getFocusedEditorUri(); + return uri && path.basename(URI.parse(uri).path) === fileName; + }, void 0, `Wait for editor with ${fileName} is focussed`); } public async waitForActiveTab(fileName: string, isDirty: boolean = false): Promise { From 09050b6aef914a52d382b72c163c4031fe2b45d9 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 14 Sep 2017 15:43:46 +0200 Subject: [PATCH 093/145] splitview: initial tests --- .../base/browser/ui/splitview/splitview2.ts | 325 ++++++++++++++++++ .../browser/ui/splitview/splitview.test.ts | 118 +++++++ 2 files changed, 443 insertions(+) create mode 100644 src/vs/base/browser/ui/splitview/splitview2.ts create mode 100644 src/vs/base/test/browser/ui/splitview/splitview.test.ts diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts new file mode 100644 index 00000000000..a65ad774a40 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -0,0 +1,325 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/css!./splitview'; +import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; +import Event, { fromEventEmitter, mapEvent } from 'vs/base/common/event'; +import types = require('vs/base/common/types'); +import dom = require('vs/base/browser/dom'); +import { Sash, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; +export { Orientation } from 'vs/base/browser/ui/sash/sash'; + +interface ISashEvent { + sash: Sash; + start: number; + current: number; +} + +export interface IOptions { + orientation?: Orientation; // default Orientation.VERTICAL + canChangeOrderByDragAndDrop?: boolean; +} + +export interface IView { + readonly minimumSize: number; + readonly maximumSize: number; + readonly onDidChange: Event; + render(container: HTMLElement, orientation: Orientation): void; + layout(size: number, orientation: Orientation): void; + focus(): void; +} + +class ViewItem { + + public explicitSize: number; + + constructor( + readonly view: IView, + readonly container: HTMLElement, + public size: number, + private orientation: Orientation, + private disposables: IDisposable[] + ) { + + } + + layout(): void { + if (this.orientation === Orientation.VERTICAL) { + this.container.style.height = `${this.size}px`; + } else { + this.container.style.width = `${this.size}px`; + } + + this.view.layout(this.size, this.orientation); + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + +interface ISashItem { + sash: Sash; + disposable: IDisposable; +} + +export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider { + + private orientation: Orientation; + + private el: HTMLElement; + // private size: number; + // private viewElements: HTMLElement[]; + private viewItems: ViewItem[] = []; + private sashItems: ISashItem[] = []; + // private viewChangeListeners: IDisposable[]; + // private viewFocusPreviousListeners: IDisposable[]; + // private viewFocusNextListeners: IDisposable[]; + // private viewFocusListeners: IDisposable[]; + // private viewDnDListeners: IDisposable[][]; + // private sashOrientation: Orientation; + // private sashes: Sash[]; + // private sashesListeners: IDisposable[]; + // private eventWrapper: (event: ISashEvent) => ISashEvent; + // private animationTimeout: number; + // private state: IState; + + // private _onFocus: Emitter = this._register(new Emitter()); + // readonly onFocus: Event = this._onFocus.event; + + // private _onDidOrderChange: Emitter = this._register(new Emitter()); + // readonly onDidOrderChange: Event = this._onDidOrderChange.event; + + get length(): number { + return this.viewItems.length; + } + + constructor(private container: HTMLElement, options?: IOptions) { + options = options || {}; + this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation; + + this.el = document.createElement('div'); + dom.addClass(this.el, 'monaco-split-view'); + dom.addClass(this.el, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal'); + container.appendChild(this.el); + + // this.size = null; + // this.viewElements = []; + // this.views = []; + // this.viewChangeListeners = []; + // this.viewFocusPreviousListeners = []; + // this.viewFocusNextListeners = []; + // this.viewFocusListeners = []; + // this.viewDnDListeners = []; + // this.sashes = []; + // this.sashesListeners = []; + // this.animationTimeout = null; + + // this.sashOrientation = this.orientation === Orientation.VERTICAL + // ? Orientation.HORIZONTAL + // : Orientation.VERTICAL; + + // if (this.orientation === Orientation.VERTICAL) { + // this.eventWrapper = e => { return { start: e.startY, current: e.currentY }; }; + // } else { + // this.eventWrapper = e => { return { start: e.startX, current: e.currentX }; }; + // } + + // The void space exists to handle the case where all other views are fixed size + // this.addView(new VoidView(), 0); + } + + private getContainerSize(): number { + return this.orientation === Orientation.VERTICAL + ? dom.getContentHeight(this.container) + : dom.getContentWidth(this.container); + } + + addView(view: IView, size: number, index = this.viewItems.length - 1): void { + // Create view container + const container = document.createElement('div'); + dom.addClass(container, 'split-view-view'); + const containerDisposable = toDisposable(() => this.el.removeChild(container)); + + // List to change events + const onChangeDisposable = mapEvent(view.onDidChange, () => item)(this.onViewChange, this); + + // Create item + const item = new ViewItem(view, container, size, this.orientation, [onChangeDisposable, containerDisposable]); + this.viewItems.splice(index, 0, item); + + // Render view + view.render(container, this.orientation); + + // Attach view + if (this.viewItems.length === 1) { + this.el.appendChild(container); + } else { + this.el.insertBefore(container, this.el.children.item(index)); + } + + // Add sash + if (this.viewItems.length <= 1) { + return; + } + + const orientation = this.orientation === Orientation.VERTICAL + ? Orientation.HORIZONTAL + : Orientation.VERTICAL; + + const sash = new Sash(this.el, this, { orientation }); + const sashEventMapper = this.orientation === Orientation.VERTICAL + ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) + : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); + + const onStart = mapEvent(fromEventEmitter(sash, 'start'), sashEventMapper); + const onStartDisposable = onStart(this.onSashStart, this); + + const onChange = mapEvent(fromEventEmitter(sash, 'change'), sashEventMapper); + const onSashChangeDisposable = onChange(this.onSashChange, this); + + const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, sash]); + + const sashItem: ISashItem = { + sash, + disposable + }; + + this.sashItems.splice(index - 1, 0, sashItem); + } + + removeView(index: number): void { + if (index < 0 || index >= this.viewItems.length) { + return; + } + + // Remove view + const viewItem = this.viewItems.splice(index, 1)[0]; + viewItem.dispose(); + + if (this.viewItems.length < 1) { + return; + } + + // Remove sash + const sashIndex = Math.max(index - 1, 0); + const sashItem = this.sashItems.splice(sashIndex, 1)[0]; + sashItem.disposable.dispose(); + } + + layout(size?: number): void { + size = size || this.getContainerSize(); + } + + private onSashStart({ sash, start, current }: ISashEvent): void { + + } + + private onSashChange({ sash, start, current }: ISashEvent): void { + + } + + // Main algorithm + // private expandCollapse(collapse: number, collapses: number[], expands: number[], collapseIndexes: number[], expandIndexes: number[]): void { + // let totalCollapse = collapse; + // let totalExpand = totalCollapse; + + // collapseIndexes.forEach(i => { + // let collapse = Math.min(collapses[i], totalCollapse); + // totalCollapse -= collapse; + // this.views[i].size -= collapse; + // }); + + // expandIndexes.forEach(i => { + // let expand = Math.min(expands[i], totalExpand); + // totalExpand -= expand; + // this.views[i].size += expand; + // }); + // } + + private getLastFlexibleViewIndex(exceptIndex: number = null): number { + // for (let i = this.views.length - 1; i >= 0; i--) { + // if (exceptIndex === i) { + // continue; + // } + // if (this.views[i].sizing === ViewSizing.Flexible) { + // return i; + // } + // } + + return -1; + } + + private layoutViews(): void { + this.viewItems.forEach(item => item.layout()); + this.sashItems.forEach(item => item.sash.layout()); + + // Update sashes enablement + // let previous = false; + // let collapsesDown = this.views.map(v => previous = (v.size - v.minimumSize > 0) || previous); + + // previous = false; + // let expandsDown = this.views.map(v => previous = (v.maximumSize - v.size > 0) || previous); + + // let reverseViews = this.views.slice().reverse(); + // previous = false; + // let collapsesUp = reverseViews.map(v => previous = (v.size - v.minimumSize > 0) || previous).reverse(); + + // previous = false; + // let expandsUp = reverseViews.map(v => previous = (v.maximumSize - v.size > 0) || previous).reverse(); + + // this.sashes.forEach((s, i) => { + // if ((collapsesDown[i] && expandsUp[i + 1]) || (expandsDown[i] && collapsesUp[i + 1])) { + // s.enable(); + // } else { + // s.disable(); + // } + // }); + } + + private onViewChange(view: ViewItem): void { + } + + // private setupAnimation(): void { + // if (types.isNumber(this.animationTimeout)) { + // window.clearTimeout(this.animationTimeout); + // } + + // dom.addClass(this.el, 'animated'); + // this.animationTimeout = window.setTimeout(() => this.clearAnimation(), 200); + // } + + // private clearAnimation(): void { + // this.animationTimeout = null; + // dom.removeClass(this.el, 'animated'); + // } + + getVerticalSashLeft(sash: Sash): number { + return this.getSashPosition(sash); + } + + getHorizontalSashTop(sash: Sash): number { + return this.getSashPosition(sash); + } + + private getSashPosition(sash: Sash): number { + let position = 0; + + for (let i = 0; i < this.sashItems.length; i++) { + position += this.viewItems[i].size; + + if (this.sashItems[i].sash === sash) { + return position; + } + } + + throw new Error('Sash not found'); + } + + dispose(): void { + } +} diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts new file mode 100644 index 00000000000..94dbb16fe87 --- /dev/null +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -0,0 +1,118 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { Emitter } from 'vs/base/common/event'; +import { SplitView, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview2'; + +class TestView implements IView { + + private _onDidChange = new Emitter(); + readonly onDidChange = this._onDidChange.event; + + get minimumSize(): number { return this._minimumSize; } + set minimumSize(size: number) { this._minimumSize = size; this._onDidChange.fire(); } + + get maximumSize(): number { return this._maximumSize; } + set maximumSize(size: number) { this._maximumSize = size; this._onDidChange.fire(); } + + private _onDidRender = new Emitter<{ container: HTMLElement; orientation: Orientation }>(); + readonly onDidRender = this._onDidRender.event; + + private _onDidLayout = new Emitter<{ size: number; orientation: Orientation }>(); + readonly onDidLayout = this._onDidLayout.event; + + private _onDidFocus = new Emitter(); + readonly onDidFocus = this._onDidFocus.event; + + constructor( + private _minimumSize: number, + private _maximumSize: number + ) { + assert(_minimumSize <= _maximumSize, 'splitview view minimum size must be <= maximum size'); + } + + render(container: HTMLElement, orientation: Orientation): void { + this._onDidRender.fire({ container, orientation }); + } + + layout(size: number, orientation: Orientation): void { + this._onDidLayout.fire({ size, orientation }); + } + + focus(): void { + this._onDidFocus.fire(); + } + + dispose(): void { + this._onDidChange.dispose(); + this._onDidRender.dispose(); + this._onDidLayout.dispose(); + this._onDidFocus.dispose(); + } +} + +suite('Splitview', () => { + let container: HTMLElement; + + setup(() => { + container = document.createElement('div'); + container.style.position = 'absolute'; + container.style.width = '200px'; + container.style.height = '200px'; + }); + + teardown(() => { + container = null; + }); + + test('empty splitview has empty DOM', () => { + const splitview = new SplitView(container); + assert.equal(container.firstElementChild.childElementCount, 0, 'split view should be empty'); + splitview.dispose(); + }); + + test('splitview has views as sashes as children', () => { + const view = new TestView(20, 20); + const splitview = new SplitView(container); + + splitview.addView(view, 20); + splitview.addView(view, 20); + splitview.addView(view, 20); + + let viewQuery = container.querySelectorAll('.monaco-split-view > .split-view-view'); + assert.equal(viewQuery.length, 3, 'split view should have 3 views'); + + let sashQuery = container.querySelectorAll('.monaco-split-view > .monaco-sash'); + assert.equal(sashQuery.length, 2, 'split view should have 2 sashes'); + + splitview.removeView(2); + + viewQuery = container.querySelectorAll('.monaco-split-view > .split-view-view'); + assert.equal(viewQuery.length, 2, 'split view should have 2 views'); + + sashQuery = container.querySelectorAll('.monaco-split-view > .monaco-sash'); + assert.equal(sashQuery.length, 1, 'split view should have 1 sash'); + + splitview.removeView(0); + + viewQuery = container.querySelectorAll('.monaco-split-view > .split-view-view'); + assert.equal(viewQuery.length, 1, 'split view should have 1 view'); + + sashQuery = container.querySelectorAll('.monaco-split-view > .monaco-sash'); + assert.equal(sashQuery.length, 0, 'split view should have no sashes'); + + splitview.removeView(0); + + viewQuery = container.querySelectorAll('.monaco-split-view > .split-view-view'); + assert.equal(viewQuery.length, 0, 'split view should have no views'); + + sashQuery = container.querySelectorAll('.monaco-split-view > .monaco-sash'); + assert.equal(sashQuery.length, 0, 'split view should have no sashes'); + + splitview.dispose(); + view.dispose(); + }); +}); \ No newline at end of file From 8770c22393aa30a794009639f92635c6869a4b96 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 14 Sep 2017 16:39:31 +0200 Subject: [PATCH 094/145] smoke: more screenshots --- test/smoke/src/spectron/application.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 72bce7b5e2f..ea6fb20ed16 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -76,6 +76,7 @@ export class SpectronApplication { await this.startApplication(testSuiteName, codeArgs); await this.checkWindowReady(); await this.waitForWelcome(); + await this.screenCapturer.capture('Application started'); } public async reload(): Promise { @@ -87,6 +88,7 @@ export class SpectronApplication { public async stop(): Promise { if (this.spectron && this.spectron.isRunning()) { + await this.screenCapturer.capture('Stopping application'); return await this.spectron.stop(); } } From 9afefc8b00b63c20d6375b62a8044bc8f427ad31 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 14 Sep 2017 17:13:53 +0200 Subject: [PATCH 095/145] arrays.range, arrays.weave --- src/vs/base/browser/ui/list/listWidget.ts | 2 +- src/vs/base/common/arrays.ts | 38 +++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 9eb101a4f35..cbba77216b3 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -398,7 +398,7 @@ class MouseController implements IDisposable { if (isSelectionRangeChangeEvent(e) && reference !== undefined) { const min = Math.min(reference, focus); const max = Math.max(reference, focus); - const rangeSelection = range(max + 1, min); + const rangeSelection = range(min, max + 1); const selection = this.list.getSelection(); const contiguousRange = getContiguousRangeContaining(disjunction(selection, [reference]), reference); diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 4be8d60f396..a64b84276eb 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -325,11 +325,43 @@ export function flatten(arr: T[][]): T[] { return arr.reduce((r, v) => r.concat(v), []); } -export function range(to: number, from = 0): number[] { +export function range(to: number): number[]; +export function range(from: number, to: number): number[]; +export function range(arg: number, to?: number): number[] { + let from = typeof to === 'number' ? arg : 0; + + if (typeof to === 'number') { + from = arg; + } else { + from = 0; + to = arg; + } + const result: number[] = []; - for (let i = from; i < to; i++) { - result.push(i); + if (from <= to) { + for (let i = from; i < to; i++) { + result.push(i); + } + } else { + for (let i = from; i > to; i--) { + result.push(i); + } + } + + return result; +} + +export function weave(a: T[], b: T[]): T[] { + const result: T[] = []; + let ai = 0, bi = 0; + + for (let i = 0, length = a.length + b.length; i < length; i++) { + if ((i % 2 === 0 && ai < a.length) || bi >= b.length) { + result.push(a[ai++]); + } else { + result.push(b[bi++]); + } } return result; From 3a50909c69b4b561533ed6a11ebe748980d7aa49 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 17:53:55 +0200 Subject: [PATCH 096/145] prevent overwriting a workspace that is opened inside another window --- src/vs/code/electron-main/windows.ts | 369 ++++++++++++++++----------- 1 file changed, 216 insertions(+), 153 deletions(-) diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index e04278782bf..6151b7b28ef 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -5,7 +5,7 @@ 'use strict'; -import * as path from 'path'; +import { basename, normalize, join, dirname } from 'path'; import * as fs from 'original-fs'; import { localize } from 'vs/nls'; import * as arrays from 'vs/base/common/arrays'; @@ -114,6 +114,7 @@ export class WindowsManager implements IWindowsMainService { private lastClosedWindowState: IWindowState; private fileDialog: FileDialog; + private workspacesManager: WorkspacesManager; private _onWindowReady = new Emitter(); onWindowReady: CommonEvent = this._onWindowReady.event; @@ -146,7 +147,9 @@ export class WindowsManager implements IWindowsMainService { @IInstantiationService private instantiationService: IInstantiationService ) { this.windowsState = this.storageService.getItem(WindowsManager.windowsStateStorageKey) || { openedWindows: [] }; + this.fileDialog = new FileDialog(environmentService, telemetryService, storageService, this); + this.workspacesManager = new WorkspacesManager(workspacesService, lifecycleService, backupService, environmentService, this); this.migrateLegacyWindowState(); } @@ -403,7 +406,7 @@ export class WindowsManager implements IWindowsMainService { workspacesToRestore.push(...this.workspacesService.getUntitledWorkspacesSync()); // collect from previous window session emptyToRestore = this.backupService.getEmptyWindowBackupPaths(); - emptyToRestore.push(...pathsToOpen.filter(w => !w.workspace && !w.folderPath && w.backupPath).map(w => path.basename(w.backupPath))); // add empty windows with backupPath + emptyToRestore.push(...pathsToOpen.filter(w => !w.workspace && !w.folderPath && w.backupPath).map(w => basename(w.backupPath))); // add empty windows with backupPath emptyToRestore = arrays.distinct(emptyToRestore); // prevent duplicates } @@ -932,7 +935,7 @@ export class WindowsManager implements IWindowsMainService { anyPath = parsedPath.path; } - const candidate = path.normalize(anyPath); + const candidate = normalize(anyPath); try { const candidateStat = fs.statSync(candidate); if (candidateStat) { @@ -1051,7 +1054,7 @@ export class WindowsManager implements IWindowsMainService { // For all other cases we first call into registerEmptyWindowBackupSync() to set it before // loading the window. if (options.emptyWindowBackupFolder) { - configuration.backupPath = path.join(this.environmentService.backupHome, options.emptyWindowBackupFolder); + configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupFolder); } let window: CodeWindow; @@ -1291,93 +1294,19 @@ export class WindowsManager implements IWindowsMainService { }); } - public saveAndOpenWorkspace(window: CodeWindow, path: string): TPromise { - if (!window || !window.win || window.readyState !== ReadyState.READY || !window.openedWorkspace || !path) { - return TPromise.as(null); // return early if the window is not ready or disposed or does not have a workspace - } - - return this.doSaveAndOpenWorkspace(window, window.openedWorkspace, path); + public saveAndOpenWorkspace(win: CodeWindow, path: string): TPromise { + return this.workspacesManager.saveAndOpenWorkspace(win, path); } - public createAndOpenWorkspace(window: CodeWindow, folders?: string[], path?: string): TPromise { - if (!window || !window.win || window.readyState !== ReadyState.READY) { - return TPromise.as(null); // return early if the window is not ready or disposed - } - - return this.workspacesService.createWorkspace(folders).then(workspace => { - return this.doSaveAndOpenWorkspace(window, workspace, path); - }); + public createAndOpenWorkspace(win: CodeWindow, folders?: string[], path?: string): TPromise { + return this.workspacesManager.createAndOpenWorkspace(win, folders, path); } - private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise { - let savePromise: TPromise; - if (path) { - savePromise = this.workspacesService.saveWorkspace(workspace, path); - } else { - savePromise = TPromise.as(workspace); - } - - return savePromise.then(workspace => { - window.focus(); - - // Only open workspace when the window has not vetoed this - return this.lifecycleService.unload(window, UnloadReason.RELOAD, workspace).done(veto => { - if (!veto) { - - // Register window for backups and migrate current backups over - let backupPath: string; - if (window.config && !window.config.extensionDevelopmentPath) { - backupPath = this.backupService.registerWorkspaceBackupSync(workspace, window.config.backupPath); - } - - // Craft a new window configuration to use for the transition - const configuration: IWindowConfiguration = mixin({}, window.config); - configuration.folderPath = void 0; - configuration.workspace = workspace; - configuration.backupPath = backupPath; - - // Reload - window.reload(configuration); - } - }); - }); + public openWorkspace(win?: CodeWindow): void { + this.workspacesManager.openWorkspace(win); } - public openWorkspace(window: CodeWindow = this.getLastActiveWindow()): void { - let defaultPath: string; - if (window && window.openedWorkspace && !this.workspacesService.isUntitledWorkspace(window.openedWorkspace)) { - defaultPath = path.dirname(window.openedWorkspace.configPath); - } else { - defaultPath = this.getWorkspaceDialogDefaultPath(window ? (window.openedWorkspace || window.openedFolderPath) : void 0); - } - this.pickFileAndOpen({ - windowId: window ? window.id : void 0, - dialogOptions: { - buttonLabel: mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open")), - title: localize('openWorkspaceTitle', "Open Workspace"), - filters: WORKSPACE_FILTER, - properties: ['openFile'], - defaultPath - } - }); - } - - private getWorkspaceDialogDefaultPath(workspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier): string { - let defaultPath: string; - if (workspace) { - if (isSingleFolderWorkspaceIdentifier(workspace)) { - defaultPath = path.dirname(workspace); - } else { - const resolvedWorkspace = this.workspacesService.resolveWorkspaceSync(workspace.configPath); - if (resolvedWorkspace && resolvedWorkspace.folders.length > 0) { - defaultPath = path.dirname(resolvedWorkspace.folders[0].path); - } - } - } - - return defaultPath; - } private onBeforeWindowUnload(e: IWindowUnloadEvent): void { const windowClosing = (e.reason === UnloadReason.CLOSE); @@ -1399,74 +1328,8 @@ export class WindowsManager implements IWindowsMainService { return; // Windows/Linux: quits when last window is closed, so do not ask then } - this.promptToSaveUntitledWorkspace(e, workspace); - } - - private promptToSaveUntitledWorkspace(e: IWindowUnloadEvent, workspace: IWorkspaceIdentifier): void { - enum ConfirmResult { - SAVE, - DONT_SAVE, - CANCEL - } - - const save = { label: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), result: ConfirmResult.SAVE }; - const dontSave = { label: mnemonicButtonLabel(localize({ key: 'doNotSave', comment: ['&& denotes a mnemonic'] }, "Do&&n't Save")), result: ConfirmResult.DONT_SAVE }; - const cancel = { label: localize('cancel', "Cancel"), result: ConfirmResult.CANCEL }; - - const buttons: { label: string; result: ConfirmResult; }[] = []; - if (isWindows) { - buttons.push(save, dontSave, cancel); - } else if (isLinux) { - buttons.push(dontSave, cancel, save); - } else { - buttons.push(save, cancel, dontSave); - } - - const options: Electron.MessageBoxOptions = { - title: this.environmentService.appNameLong, - message: localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"), - detail: localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."), - noLink: true, - type: 'warning', - buttons: buttons.map(button => button.label), - cancelId: buttons.indexOf(cancel) - }; - - if (isLinux) { - options.defaultId = 2; - } - - const res = dialog.showMessageBox(e.window.win, options); - - switch (buttons[res].result) { - - // Cancel: veto unload - case ConfirmResult.CANCEL: - e.veto(true); - break; - - // Don't Save: delete workspace - case ConfirmResult.DONT_SAVE: - this.workspacesService.deleteUntitledWorkspaceSync(workspace); - e.veto(false); - break; - - // Save: save workspace, but do not veto unload - case ConfirmResult.SAVE: { - const target = dialog.showSaveDialog(e.window.win, { - buttonLabel: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), - title: localize('saveWorkspace', "Save Workspace"), - filters: WORKSPACE_FILTER, - defaultPath: this.getWorkspaceDialogDefaultPath(workspace) - }); - - if (target) { - e.veto(this.workspacesService.saveWorkspace(workspace, target).then(() => false, () => false)); - } else { - e.veto(true); // keep veto if no target was provided - } - } - } + // Handle untitled workspaces with prompt as needed + this.workspacesManager.promptToSaveUntitledWorkspace(e, workspace); } public focusLastActive(cli: ParsedArgs, context: OpenContext): CodeWindow { @@ -1754,7 +1617,7 @@ class FileDialog { if (paths && paths.length > 0) { // Remember path in storage for next time - this.storageService.setItem(FileDialog.workingDirPickerStorageKey, path.dirname(paths[0])); + this.storageService.setItem(FileDialog.workingDirPickerStorageKey, dirname(paths[0])); // Return return clb(paths); @@ -1763,4 +1626,204 @@ class FileDialog { return clb(void (0)); }); } +} + +class WorkspacesManager { + + constructor( + private workspacesService: IWorkspacesMainService, + private lifecycleService: ILifecycleService, + private backupService: IBackupMainService, + private environmentService: IEnvironmentService, + private windowsMainService: IWindowsMainService + ) { + } + + public saveAndOpenWorkspace(window: CodeWindow, path: string): TPromise { + if (!window || !window.win || window.readyState !== ReadyState.READY || !window.openedWorkspace || !path || !this.isValidTargetWorkspacePath(window, path)) { + return TPromise.as(null); // return early if the window is not ready or disposed or does not have a workspace + } + + return this.doSaveAndOpenWorkspace(window, window.openedWorkspace, path); + } + + public createAndOpenWorkspace(window: CodeWindow, folders?: string[], path?: string): TPromise { + if (!window || !window.win || window.readyState !== ReadyState.READY || !this.isValidTargetWorkspacePath(window, path)) { + return TPromise.as(null); // return early if the window is not ready or disposed + } + + return this.workspacesService.createWorkspace(folders).then(workspace => { + return this.doSaveAndOpenWorkspace(window, workspace, path); + }); + } + + private isValidTargetWorkspacePath(window: CodeWindow, path?: string): boolean { + if (!path) { + return true; + } + + if (window.openedWorkspace && window.openedWorkspace.configPath === path) { + return false; // window is already opened on a workspace with that path + } + + // Prevent overwriting a workspace that is currently opened in another window + if (findWindowOnWorkspace(this.windowsMainService.getWindows(), { id: this.workspacesService.getWorkspaceId(path), configPath: path })) { + const options: Electron.MessageBoxOptions = { + title: product.nameLong, + type: 'info', + buttons: [localize('ok', "OK")], + message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), + detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close the window first and then try again."), + noLink: true + }; + + const activeWindow = BrowserWindow.getFocusedWindow(); + if (activeWindow) { + dialog.showMessageBox(activeWindow, options); + } else { + dialog.showMessageBox(options); + } + + return false; + } + + return true; // OK + } + + private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise { + let savePromise: TPromise; + if (path) { + savePromise = this.workspacesService.saveWorkspace(workspace, path); + } else { + savePromise = TPromise.as(workspace); + } + + return savePromise.then(workspace => { + window.focus(); + + // Only open workspace when the window has not vetoed this + return this.lifecycleService.unload(window, UnloadReason.RELOAD, workspace).done(veto => { + if (!veto) { + + // Register window for backups and migrate current backups over + let backupPath: string; + if (window.config && !window.config.extensionDevelopmentPath) { + backupPath = this.backupService.registerWorkspaceBackupSync(workspace, window.config.backupPath); + } + + // Craft a new window configuration to use for the transition + const configuration: IWindowConfiguration = mixin({}, window.config); + configuration.folderPath = void 0; + configuration.workspace = workspace; + configuration.backupPath = backupPath; + + // Reload + window.reload(configuration); + } + }); + }); + } + + public openWorkspace(window = this.windowsMainService.getLastActiveWindow()): void { + let defaultPath: string; + if (window && window.openedWorkspace && !this.workspacesService.isUntitledWorkspace(window.openedWorkspace)) { + defaultPath = dirname(window.openedWorkspace.configPath); + } else { + defaultPath = this.getWorkspaceDialogDefaultPath(window ? (window.openedWorkspace || window.openedFolderPath) : void 0); + } + + this.windowsMainService.pickFileAndOpen({ + windowId: window ? window.id : void 0, + dialogOptions: { + buttonLabel: mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open")), + title: localize('openWorkspaceTitle', "Open Workspace"), + filters: WORKSPACE_FILTER, + properties: ['openFile'], + defaultPath + } + }); + } + + public promptToSaveUntitledWorkspace(e: IWindowUnloadEvent, workspace: IWorkspaceIdentifier): void { + enum ConfirmResult { + SAVE, + DONT_SAVE, + CANCEL + } + + const save = { label: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), result: ConfirmResult.SAVE }; + const dontSave = { label: mnemonicButtonLabel(localize({ key: 'doNotSave', comment: ['&& denotes a mnemonic'] }, "Do&&n't Save")), result: ConfirmResult.DONT_SAVE }; + const cancel = { label: localize('cancel', "Cancel"), result: ConfirmResult.CANCEL }; + + const buttons: { label: string; result: ConfirmResult; }[] = []; + if (isWindows) { + buttons.push(save, dontSave, cancel); + } else if (isLinux) { + buttons.push(dontSave, cancel, save); + } else { + buttons.push(save, cancel, dontSave); + } + + const options: Electron.MessageBoxOptions = { + title: this.environmentService.appNameLong, + message: localize('saveWorkspaceMessage', "Do you want to save your workspace configuration as a file?"), + detail: localize('saveWorkspaceDetail', "Save your workspace if you plan to open it again."), + noLink: true, + type: 'warning', + buttons: buttons.map(button => button.label), + cancelId: buttons.indexOf(cancel) + }; + + if (isLinux) { + options.defaultId = 2; + } + + const res = dialog.showMessageBox(e.window.win, options); + + switch (buttons[res].result) { + + // Cancel: veto unload + case ConfirmResult.CANCEL: + e.veto(true); + break; + + // Don't Save: delete workspace + case ConfirmResult.DONT_SAVE: + this.workspacesService.deleteUntitledWorkspaceSync(workspace); + e.veto(false); + break; + + // Save: save workspace, but do not veto unload + case ConfirmResult.SAVE: { + const target = dialog.showSaveDialog(e.window.win, { + buttonLabel: mnemonicButtonLabel(localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")), + title: localize('saveWorkspace', "Save Workspace"), + filters: WORKSPACE_FILTER, + defaultPath: this.getWorkspaceDialogDefaultPath(workspace) + }); + + if (target) { + e.veto(this.workspacesService.saveWorkspace(workspace, target).then(() => false, () => false)); + } else { + e.veto(true); // keep veto if no target was provided + } + } + } + } + + private getWorkspaceDialogDefaultPath(workspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier): string { + let defaultPath: string; + if (workspace) { + if (isSingleFolderWorkspaceIdentifier(workspace)) { + defaultPath = dirname(workspace); + } else { + const resolvedWorkspace = this.workspacesService.resolveWorkspaceSync(workspace.configPath); + if (resolvedWorkspace && resolvedWorkspace.folders.length > 0) { + defaultPath = dirname(resolvedWorkspace.folders[0].path); + } + } + } + + return defaultPath; + } } \ No newline at end of file From 01b014a9504e0ee84f1f54a8c7d9835aa2c1f36c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 14 Sep 2017 18:28:22 +0200 Subject: [PATCH 097/145] do not overwrite existing backups when migrating workspace --- src/vs/code/electron-main/windows.ts | 2 +- .../backup/electron-main/backupMainService.ts | 49 +++++++++++++------ .../electron-main/backupMainService.test.ts | 27 ++++++++++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 6151b7b28ef..5c6464d7db1 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -1673,7 +1673,7 @@ class WorkspacesManager { type: 'info', buttons: [localize('ok', "OK")], message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), - detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close the window first and then try again."), + detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."), noLink: true }; diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index 94210b0572f..9ea43c880e6 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -88,14 +88,19 @@ export class BackupMainService implements IBackupMainService { } private moveBackupFolderSync(backupPath: string, moveFromPath: string): void { - if (!fs.existsSync(moveFromPath)) { - return; + + // Target exists: make sure to convert existing backups to empty window backups + if (fs.existsSync(backupPath)) { + this.convertToEmptyWindowBackup(backupPath); } - try { - fs.renameSync(moveFromPath, backupPath); - } catch (ex) { - this.logService.error(`Backup: Could not move backup folder to new location: ${ex.toString()}`); + // When we have data to migrate from, move it over to the target location + if (fs.existsSync(moveFromPath)) { + try { + fs.renameSync(moveFromPath, backupPath); + } catch (ex) { + this.logService.error(`Backup: Could not move backup folder to new location: ${ex.toString()}`); + } } } @@ -231,16 +236,7 @@ export class BackupMainService implements IBackupMainService { staleBackupWorkspaces.push({ workspaceIdentifier: workspaceId, backupPath, target: workspaceOrFolder.target }); if (missingWorkspace) { - const identifier = this.getRandomEmptyWindowId(); - this.pushBackupPathsSync(identifier, this.backups.emptyWorkspaces); - const newEmptyWindowBackupPath = path.join(this.backupHome, identifier); - try { - fs.renameSync(backupPath, newEmptyWindowBackupPath); - } catch (ex) { - this.logService.error(`Backup: Could not rename backup folder for missing workspace: ${ex.toString()}`); - - this.removeBackupPathSync(identifier, this.backups.emptyWorkspaces); - } + this.convertToEmptyWindowBackup(backupPath); } } }); @@ -267,6 +263,27 @@ export class BackupMainService implements IBackupMainService { }); } + private convertToEmptyWindowBackup(backupPath: string): boolean { + + // New empty window backup + const identifier = this.getRandomEmptyWindowId(); + this.pushBackupPathsSync(identifier, this.backups.emptyWorkspaces); + + // Rename backupPath to new empty window backup path + const newEmptyWindowBackupPath = path.join(this.backupHome, identifier); + try { + fs.renameSync(backupPath, newEmptyWindowBackupPath); + } catch (ex) { + this.logService.error(`Backup: Could not rename backup folder: ${ex.toString()}`); + + this.removeBackupPathSync(identifier, this.backups.emptyWorkspaces); + + return false; + } + + return true; + } + private hasBackupsSync(backupPath: string): boolean { try { const backupSchemas = extfs.readdirSync(backupPath); diff --git a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts index 063ebe91c6a..7d5a37d4edb 100644 --- a/src/vs/platform/backup/test/electron-main/backupMainService.test.ts +++ b/src/vs/platform/backup/test/electron-main/backupMainService.test.ts @@ -208,6 +208,33 @@ suite('BackupMainService', () => { assert.ok(fs.existsSync(path.join(workspaceBackupPath, 'backup.txt'))); assert.ok(!fs.existsSync(backupPathToMigrate)); + const emptyBackups = service.getEmptyWindowBackupPaths(); + assert.equal(0, emptyBackups.length); + + done(); + }); + + test('service backup migration makes sure to preserve existing backups', done => { + const backupPathToMigrate = service.toBackupPath(fooFile.fsPath); + fs.mkdirSync(backupPathToMigrate); + fs.writeFileSync(path.join(backupPathToMigrate, 'backup.txt'), 'Some Data'); + service.registerFolderBackupSync(backupPathToMigrate); + + const backupPathToPreserve = service.toBackupPath(barFile.fsPath); + fs.mkdirSync(backupPathToPreserve); + fs.writeFileSync(path.join(backupPathToPreserve, 'backup.txt'), 'Some Data'); + service.registerFolderBackupSync(backupPathToPreserve); + + const workspaceBackupPath = service.registerWorkspaceBackupSync(toWorkspace(barFile.fsPath), backupPathToMigrate); + + assert.ok(fs.existsSync(workspaceBackupPath)); + assert.ok(fs.existsSync(path.join(workspaceBackupPath, 'backup.txt'))); + assert.ok(!fs.existsSync(backupPathToMigrate)); + + const emptyBackups = service.getEmptyWindowBackupPaths(); + assert.equal(1, emptyBackups.length); + assert.equal(1, fs.readdirSync(path.join(backupHome, emptyBackups[0])).length); + done(); }); From b3318dabda06972d51a353b7e57065b98b65cceb Mon Sep 17 00:00:00 2001 From: Riley Skains <24799022+rileyskains@users.noreply.github.com> Date: Thu, 14 Sep 2017 14:29:56 -0500 Subject: [PATCH 098/145] Everyday typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 670195c3c92..b0a86b728ae 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ a code editor with what developers need for their core edit-build-debug cycle. Code provides comprehensive editing and debugging support, an extensibility model, and lightweight integration with existing tools. -VS Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [VS Code's website](https://code.visualstudio.com/Download). To get the latest releases everyday, you can install the [Insiders version of VS Code](https://code.visualstudio.com/insiders). This builds from the master branch and is updated at least daily. +VS Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [VS Code's website](https://code.visualstudio.com/Download). To get the latest releases every day, you can install the [Insiders version of VS Code](https://code.visualstudio.com/insiders). This builds from the master branch and is updated at least daily.

VS Code in action From 65d00e6dc2495f9e6d13ca62e5528ad2e482ae87 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 14 Sep 2017 22:54:56 +0200 Subject: [PATCH 099/145] support for sourceRef query param in debug uri --- .../debug/browser/debugContentProvider.ts | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/parts/debug/browser/debugContentProvider.ts b/src/vs/workbench/parts/debug/browser/debugContentProvider.ts index ad96768d0d5..ccf2795916f 100644 --- a/src/vs/workbench/parts/debug/browser/debugContentProvider.ts +++ b/src/vs/workbench/parts/debug/browser/debugContentProvider.ts @@ -32,13 +32,21 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC public provideTextContent(resource: uri): TPromise { let process: IProcess; + let sourceRef: number; + if (resource.query) { const keyvalues = resource.query.split('&'); for (let keyvalue of keyvalues) { const pair = keyvalue.split('='); - if (pair.length === 2 && pair[0] === 'session') { - process = this.debugService.findProcessByUUID(decodeURIComponent(pair[1])); - break; + if (pair.length === 2) { + switch (pair[0]) { + case 'session': + process = this.debugService.findProcessByUUID(decodeURIComponent(pair[1])); + break; + case 'sourceRef': + sourceRef = parseInt(pair[1]); + break; + } } } } @@ -55,18 +63,26 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC let rawSource: DebugProtocol.Source; if (source) { rawSource = source.raw; + if (!sourceRef) { + sourceRef = source.reference; + } } else { - // Remove debug: scheme - rawSource = { path: resource.with({ scheme: '', query: '' }).toString(true) }; + // create a Source + rawSource = { + path: resource.with({ scheme: '', query: '' }).toString(true), // Remove debug: scheme + sourceReference: sourceRef + }; } - return process.session.source({ sourceReference: source ? source.reference : undefined, source: rawSource }).then(response => { + return process.session.source({ sourceReference: sourceRef, source: rawSource }).then(response => { + const mime = response.body.mimeType || guessMimeTypes(resource.toString())[0]; const modePromise = this.modeService.getOrCreateMode(mime); const model = this.modelService.createModel(response.body.content, modePromise, resource); return model; }, (err: DebugProtocol.ErrorResponse) => { + this.debugService.sourceIsNotAvailable(resource); const modePromise = this.modeService.getOrCreateMode(MIME_TEXT); const model = this.modelService.createModel(err.message, modePromise, resource); From b34aba9078fa1a19a1a106db2d9609e62494aa69 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 14 Sep 2017 23:20:52 +0200 Subject: [PATCH 100/145] more splitview tests --- .../base/browser/ui/splitview/splitview2.ts | 309 +++++++++++------- src/vs/base/common/numbers.ts | 5 + .../browser/ui/splitview/splitview.test.ts | 80 ++++- 3 files changed, 273 insertions(+), 121 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index a65ad774a40..3d357223596 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -6,10 +6,12 @@ 'use strict'; import 'vs/css!./splitview'; -import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, combinedDisposable, empty as EmptyDisposable, toDisposable } from 'vs/base/common/lifecycle'; import Event, { fromEventEmitter, mapEvent } from 'vs/base/common/event'; import types = require('vs/base/common/types'); import dom = require('vs/base/browser/dom'); +import { clamp } from 'vs/base/common/numbers'; +import { range, firstIndex, weave } from 'vs/base/common/arrays'; import { Sash, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash'; @@ -33,33 +35,22 @@ export interface IView { focus(): void; } -class ViewItem { - - public explicitSize: number; - - constructor( - readonly view: IView, - readonly container: HTMLElement, - public size: number, - private orientation: Orientation, - private disposables: IDisposable[] - ) { +interface IViewItem { + view: IView; + size: number; + explicitSize: number; + container: HTMLElement; + disposable: IDisposable; +} +function layoutViewItem(item: IViewItem, orientation: Orientation): void { + if (orientation === Orientation.VERTICAL) { + item.container.style.height = `${item.size}px`; + } else { + item.container.style.width = `${item.size}px`; } - layout(): void { - if (this.orientation === Orientation.VERTICAL) { - this.container.style.height = `${this.size}px`; - } else { - this.container.style.width = `${this.size}px`; - } - - this.view.layout(this.size, this.orientation); - } - - dispose(): void { - this.disposables = dispose(this.disposables); - } + item.view.layout(item.size, orientation); } interface ISashItem { @@ -67,14 +58,27 @@ interface ISashItem { disposable: IDisposable; } +interface ISashDragState { + start: number; + sizes: number[]; + up: number[]; + down: number[]; + maxUp: number; + maxDown: number; + collapses: number[]; + expands: number[]; +} + +const sum = (a: number[]) => a.reduce((a, b) => a + b, 0); + export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider { private orientation: Orientation; private el: HTMLElement; - // private size: number; + private size = 0; // private viewElements: HTMLElement[]; - private viewItems: ViewItem[] = []; + private viewItems: IViewItem[] = []; private sashItems: ISashItem[] = []; // private viewChangeListeners: IDisposable[]; // private viewFocusPreviousListeners: IDisposable[]; @@ -86,7 +90,7 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // private sashesListeners: IDisposable[]; // private eventWrapper: (event: ISashEvent) => ISashEvent; // private animationTimeout: number; - // private state: IState; + private sashDragState: ISashDragState; // private _onFocus: Emitter = this._register(new Emitter()); // readonly onFocus: Event = this._onFocus.event; @@ -133,24 +137,26 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // this.addView(new VoidView(), 0); } - private getContainerSize(): number { - return this.orientation === Orientation.VERTICAL - ? dom.getContentHeight(this.container) - : dom.getContentWidth(this.container); - } + // private getContainerSize(): number { + // return this.orientation === Orientation.VERTICAL + // ? dom.getContentHeight(this.container) + // : dom.getContentWidth(this.container); + // } - addView(view: IView, size: number, index = this.viewItems.length - 1): void { + addView(view: IView, size: number, index = this.viewItems.length): void { // Create view container const container = document.createElement('div'); dom.addClass(container, 'split-view-view'); const containerDisposable = toDisposable(() => this.el.removeChild(container)); - // List to change events + // Create item + const item: IViewItem = { view, container, explicitSize: size, size, disposable: EmptyDisposable }; + this.viewItems.splice(index, 0, item); + const onChangeDisposable = mapEvent(view.onDidChange, () => item)(this.onViewChange, this); - // Create item - const item = new ViewItem(view, container, size, this.orientation, [onChangeDisposable, containerDisposable]); - this.viewItems.splice(index, 0, item); + // Disposable + item.disposable = combinedDisposable([onChangeDisposable, containerDisposable]); // Render view view.render(container, this.orientation); @@ -163,33 +169,33 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } // Add sash - if (this.viewItems.length <= 1) { - return; + if (this.viewItems.length > 1) { + const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; + const sash = new Sash(this.el, this, { orientation }); + const sashEventMapper = this.orientation === Orientation.VERTICAL + ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) + : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); + + const onStart = mapEvent(fromEventEmitter(sash, 'start'), sashEventMapper); + const onStartDisposable = onStart(this.onSashStart, this); + const onChange = mapEvent(fromEventEmitter(sash, 'change'), sashEventMapper); + const onSashChangeDisposable = onChange(this.onSashChange, this); + const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, sash]); + const sashItem: ISashItem = { sash, disposable }; + + this.sashItems.splice(index - 1, 0, sashItem); } - const orientation = this.orientation === Orientation.VERTICAL - ? Orientation.HORIZONTAL - : Orientation.VERTICAL; + // TODO: layout + // go through all viewitems, set their size to preferred size + // sum all sizes up + // run expandcollapse - const sash = new Sash(this.el, this, { orientation }); - const sashEventMapper = this.orientation === Orientation.VERTICAL - ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) - : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); + this.viewItems.forEach(i => i.size = clamp(i.explicitSize, i.view.minimumSize, i.view.maximumSize)); - const onStart = mapEvent(fromEventEmitter(sash, 'start'), sashEventMapper); - const onStartDisposable = onStart(this.onSashStart, this); - - const onChange = mapEvent(fromEventEmitter(sash, 'change'), sashEventMapper); - const onSashChangeDisposable = onChange(this.onSashChange, this); - - const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, sash]); - - const sashItem: ISashItem = { - sash, - disposable - }; - - this.sashItems.splice(index - 1, 0, sashItem); + const previousSize = this.size; + this.size = this.viewItems.reduce((r, i) => r + i.size, 0); + this.layout(previousSize); } removeView(index: number): void { @@ -199,63 +205,153 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // Remove view const viewItem = this.viewItems.splice(index, 1)[0]; - viewItem.dispose(); + const collapse = viewItem.size; + viewItem.disposable.dispose(); - if (this.viewItems.length < 1) { + // Remove sash + if (this.viewItems.length >= 1) { + const sashIndex = Math.max(index - 1, 0); + const sashItem = this.sashItems.splice(sashIndex, 1)[0]; + sashItem.disposable.dispose(); + } + + // Layout views + const up = range(index - 1, -1); + const down = range(index, this.viewItems.length); + const indexes = weave(up, down); + const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + + this.expandCollapse(collapse, collapses, [], indexes, []); + } + + layout(size: number): void { + // size = size || this.getContainerSize(); + + // size = Math.max(size, this.viewItems.reduce((t, i) => t + i.view.minimumSize, 0)); + + + if (this.size === size) { return; } - // Remove sash - const sashIndex = Math.max(index - 1, 0); - const sashItem = this.sashItems.splice(sashIndex, 1)[0]; - sashItem.disposable.dispose(); + const indexes = range(this.viewItems.length - 1, -1); + const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); + const diff = Math.abs(this.size - size); + + if (size < this.size) { + this.expandCollapse(Math.min(diff, sum(collapses)), collapses, expands, indexes, []); + } else if (size > this.size) { + this.expandCollapse(Math.min(diff, sum(expands)), collapses, expands, [], indexes); + } + + this.size = size; } - layout(size?: number): void { - size = size || this.getContainerSize(); - } + private onSashStart({ sash, start }: ISashEvent): void { + const i = firstIndex(this.sashItems, item => item.sash === sash); + const sizes = this.viewItems.map(i => i.size); + const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - private onSashStart({ sash, start, current }: ISashEvent): void { + const up = range(i, -1); + const down = range(i + 1, this.viewItems.length); + + const collapsesUp = up.map(i => collapses[i]); + const collapsesDown = down.map(i => collapses[i]); + const expandsUp = up.map(i => expands[i]); + const expandsDown = down.map(i => expands[i]); + + const maxUp = Math.min(sum(collapsesUp), sum(expandsDown)); + const maxDown = Math.min(sum(expandsUp), sum(collapsesDown)); + + this.sashDragState = { start, sizes, up, down, maxUp, maxDown, collapses, expands }; } private onSashChange({ sash, start, current }: ISashEvent): void { + const diff = current - this.sashDragState.start; + if (diff < 0) { + this.expandCollapse(Math.min(-diff, this.sashDragState.maxUp), this.sashDragState.collapses, this.sashDragState.expands, this.sashDragState.up, this.sashDragState.down); + } else { + this.expandCollapse(Math.min(diff, this.sashDragState.maxDown), this.sashDragState.collapses, this.sashDragState.expands, this.sashDragState.down, this.sashDragState.up); + } + + this.viewItems.forEach(viewItem => viewItem.explicitSize = viewItem.size); } - // Main algorithm - // private expandCollapse(collapse: number, collapses: number[], expands: number[], collapseIndexes: number[], expandIndexes: number[]): void { - // let totalCollapse = collapse; - // let totalExpand = totalCollapse; + private onViewChange(item: IViewItem): void { + const size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); - // collapseIndexes.forEach(i => { - // let collapse = Math.min(collapses[i], totalCollapse); - // totalCollapse -= collapse; - // this.views[i].size -= collapse; - // }); + if (size === item.size) { + return; + } - // expandIndexes.forEach(i => { - // let expand = Math.min(expands[i], totalExpand); - // totalExpand -= expand; - // this.views[i].size += expand; - // }); + // this could maybe use the same code than the addView() does + + // this.setupAnimation(); + + const index = this.viewItems.indexOf(item); + const diff = Math.abs(size - item.size); + + const up = range(index - 1, -1); + const down = range(index + 1, this.viewItems.length); + const downUp = down.concat(up); + + const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); + + + let collapse: number, collapseIndexes: number[], expandIndexes: number[]; + + if (size < item.size) { + collapse = Math.min(downUp.reduce((t, i) => t + expands[i], 0), diff); + collapseIndexes = [index]; + expandIndexes = downUp; + + } else { + collapse = Math.min(downUp.reduce((t, i) => t + collapses[i], 0), diff); + collapseIndexes = downUp; + expandIndexes = [index]; + } + + this.expandCollapse(collapse, collapses, expands, collapseIndexes, expandIndexes); + // this.layoutViews(); + } + + // private setupAnimation(): void { + // if (types.isNumber(this.animationTimeout)) { + // window.clearTimeout(this.animationTimeout); + // } + + // dom.addClass(this.el, 'animated'); + // this.animationTimeout = window.setTimeout(() => this.clearAnimation(), 200); // } - private getLastFlexibleViewIndex(exceptIndex: number = null): number { - // for (let i = this.views.length - 1; i >= 0; i--) { - // if (exceptIndex === i) { - // continue; - // } - // if (this.views[i].sizing === ViewSizing.Flexible) { - // return i; - // } - // } + // private clearAnimation(): void { + // this.animationTimeout = null; + // dom.removeClass(this.el, 'animated'); + // } - return -1; - } + // Main algorithm + private expandCollapse(collapse: number, collapses: number[], expands: number[], collapseIndexes: number[], expandIndexes: number[]): void { + let totalCollapse = collapse; + let totalExpand = totalCollapse; - private layoutViews(): void { - this.viewItems.forEach(item => item.layout()); + collapseIndexes.forEach(i => { + let collapse = Math.min(collapses[i], totalCollapse); + totalCollapse -= collapse; + this.viewItems[i].size -= collapse; + }); + + expandIndexes.forEach(i => { + let expand = Math.min(expands[i], totalExpand); + totalExpand -= expand; + this.viewItems[i].size += expand; + }); + + this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); this.sashItems.forEach(item => item.sash.layout()); // Update sashes enablement @@ -281,23 +377,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // }); } - private onViewChange(view: ViewItem): void { - } - - // private setupAnimation(): void { - // if (types.isNumber(this.animationTimeout)) { - // window.clearTimeout(this.animationTimeout); - // } - - // dom.addClass(this.el, 'animated'); - // this.animationTimeout = window.setTimeout(() => this.clearAnimation(), 200); - // } - - // private clearAnimation(): void { - // this.animationTimeout = null; - // dom.removeClass(this.el, 'animated'); - // } - getVerticalSashLeft(sash: Sash): number { return this.getSashPosition(sash); } diff --git a/src/vs/base/common/numbers.ts b/src/vs/base/common/numbers.ts index 65bcbbd7922..9f804fe6dd9 100644 --- a/src/vs/base/common/numbers.ts +++ b/src/vs/base/common/numbers.ts @@ -46,3 +46,8 @@ export function countToArray(fromOrTo: number, to?: number): number[] { return result; } + + +export function clamp(value: number, min: number, max: number): number { + return Math.min(Math.max(value, min), max); +} \ No newline at end of file diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 94dbb16fe87..60d531b6c41 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -21,6 +21,8 @@ class TestView implements IView { private _onDidRender = new Emitter<{ container: HTMLElement; orientation: Orientation }>(); readonly onDidRender = this._onDidRender.event; + private _size = 0; + get size(): number { return this._size; } private _onDidLayout = new Emitter<{ size: number; orientation: Orientation }>(); readonly onDidLayout = this._onDidLayout.event; @@ -39,6 +41,7 @@ class TestView implements IView { } layout(size: number, orientation: Orientation): void { + this._size = size; this._onDidLayout.fire({ size, orientation }); } @@ -54,14 +57,16 @@ class TestView implements IView { } } +const TOTAL_SIZE = 200; + suite('Splitview', () => { let container: HTMLElement; setup(() => { container = document.createElement('div'); container.style.position = 'absolute'; - container.style.width = '200px'; - container.style.height = '200px'; + container.style.width = `${TOTAL_SIZE}px`; + container.style.height = `${TOTAL_SIZE}px`; }); teardown(() => { @@ -75,12 +80,14 @@ suite('Splitview', () => { }); test('splitview has views as sashes as children', () => { - const view = new TestView(20, 20); + const view1 = new TestView(20, 20); + const view2 = new TestView(20, 20); + const view3 = new TestView(20, 20); const splitview = new SplitView(container); - splitview.addView(view, 20); - splitview.addView(view, 20); - splitview.addView(view, 20); + splitview.addView(view1, 20); + splitview.addView(view2, 20); + splitview.addView(view3, 20); let viewQuery = container.querySelectorAll('.monaco-split-view > .split-view-view'); assert.equal(viewQuery.length, 3, 'split view should have 3 views'); @@ -113,6 +120,67 @@ suite('Splitview', () => { assert.equal(sashQuery.length, 0, 'split view should have no sashes'); splitview.dispose(); + view1.dispose(); + view2.dispose(); + view3.dispose(); + }); + + test('splitview calls view methods on addView and removeView', () => { + const view = new TestView(20, 20); + const splitview = new SplitView(container); + + let didLayout = false; + const layoutDisposable = view.onDidLayout(() => didLayout = true); + + let didRender = false; + const renderDisposable = view.onDidRender(() => didRender = true); + + splitview.addView(view, 20); + + assert.equal(view.size, 20, 'view has right size'); + assert(didLayout, 'layout was called'); + assert(didLayout, 'render was called'); + + splitview.dispose(); + layoutDisposable.dispose(); + renderDisposable.dispose(); view.dispose(); }); + + test('splitview stretches view to viewport', () => { + const view = new TestView(20, Number.POSITIVE_INFINITY); + const splitview = new SplitView(container); + splitview.layout(TOTAL_SIZE); + + splitview.addView(view, 20); + assert.equal(view.size, TOTAL_SIZE, 'view was stretched'); + + splitview.dispose(); + view.dispose(); + }); + + test('splitview respects preferred sizes', () => { + const view1 = new TestView(20, Number.POSITIVE_INFINITY); + const view2 = new TestView(20, Number.POSITIVE_INFINITY); + const view3 = new TestView(20, Number.POSITIVE_INFINITY); + const splitview = new SplitView(container); + splitview.layout(TOTAL_SIZE); + + splitview.addView(view1, 20); + assert.equal(view1.size, TOTAL_SIZE, 'view1 was stretched'); + + splitview.addView(view2, 20); + assert.equal(view1.size, 20, 'view1 size was restored'); + assert.equal(view2.size, TOTAL_SIZE - 20, 'view2 was stretched'); + + splitview.addView(view3, 20); + assert.equal(view1.size, 20, 'view1 size was restored'); + assert.equal(view2.size, 20, 'view2 size was restored'); + assert.equal(view3.size, TOTAL_SIZE - 20 * 2, 'view3 was stretched'); + + splitview.dispose(); + view3.dispose(); + view2.dispose(); + view1.dispose(); + }); }); \ No newline at end of file From 47af16f20a0153be36db25de4808371b2a0e9e25 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 14 Sep 2017 23:38:46 +0200 Subject: [PATCH 101/145] splitview tests --- .../base/browser/ui/splitview/splitview2.ts | 193 ++++++------------ .../browser/ui/splitview/splitview.test.ts | 17 +- 2 files changed, 79 insertions(+), 131 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index 3d357223596..bee93a2e7cb 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -6,24 +6,17 @@ 'use strict'; import 'vs/css!./splitview'; -import { IDisposable, combinedDisposable, empty as EmptyDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; import Event, { fromEventEmitter, mapEvent } from 'vs/base/common/event'; import types = require('vs/base/common/types'); import dom = require('vs/base/browser/dom'); import { clamp } from 'vs/base/common/numbers'; -import { range, firstIndex, weave } from 'vs/base/common/arrays'; +import { range, firstIndex } from 'vs/base/common/arrays'; import { Sash, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash'; -interface ISashEvent { - sash: Sash; - start: number; - current: number; -} - export interface IOptions { orientation?: Orientation; // default Orientation.VERTICAL - canChangeOrderByDragAndDrop?: boolean; } export interface IView { @@ -35,6 +28,12 @@ export interface IView { focus(): void; } +interface ISashEvent { + sash: Sash; + start: number; + current: number; +} + interface IViewItem { view: IView; size: number; @@ -43,16 +42,6 @@ interface IViewItem { disposable: IDisposable; } -function layoutViewItem(item: IViewItem, orientation: Orientation): void { - if (orientation === Orientation.VERTICAL) { - item.container.style.height = `${item.size}px`; - } else { - item.container.style.width = `${item.size}px`; - } - - item.view.layout(item.size, orientation); -} - interface ISashItem { sash: Sash; disposable: IDisposable; @@ -71,33 +60,25 @@ interface ISashDragState { const sum = (a: number[]) => a.reduce((a, b) => a + b, 0); +function layoutViewItem(item: IViewItem, orientation: Orientation): void { + if (orientation === Orientation.VERTICAL) { + item.container.style.height = `${item.size}px`; + } else { + item.container.style.width = `${item.size}px`; + } + + item.view.layout(item.size, orientation); +} + export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider { private orientation: Orientation; - private el: HTMLElement; private size = 0; - // private viewElements: HTMLElement[]; private viewItems: IViewItem[] = []; private sashItems: ISashItem[] = []; - // private viewChangeListeners: IDisposable[]; - // private viewFocusPreviousListeners: IDisposable[]; - // private viewFocusNextListeners: IDisposable[]; - // private viewFocusListeners: IDisposable[]; - // private viewDnDListeners: IDisposable[][]; - // private sashOrientation: Orientation; - // private sashes: Sash[]; - // private sashesListeners: IDisposable[]; - // private eventWrapper: (event: ISashEvent) => ISashEvent; - // private animationTimeout: number; private sashDragState: ISashDragState; - // private _onFocus: Emitter = this._register(new Emitter()); - // readonly onFocus: Event = this._onFocus.event; - - // private _onDidOrderChange: Emitter = this._register(new Emitter()); - // readonly onDidOrderChange: Event = this._onDidOrderChange.event; - get length(): number { return this.viewItems.length; } @@ -110,64 +91,26 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV dom.addClass(this.el, 'monaco-split-view'); dom.addClass(this.el, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal'); container.appendChild(this.el); - - // this.size = null; - // this.viewElements = []; - // this.views = []; - // this.viewChangeListeners = []; - // this.viewFocusPreviousListeners = []; - // this.viewFocusNextListeners = []; - // this.viewFocusListeners = []; - // this.viewDnDListeners = []; - // this.sashes = []; - // this.sashesListeners = []; - // this.animationTimeout = null; - - // this.sashOrientation = this.orientation === Orientation.VERTICAL - // ? Orientation.HORIZONTAL - // : Orientation.VERTICAL; - - // if (this.orientation === Orientation.VERTICAL) { - // this.eventWrapper = e => { return { start: e.startY, current: e.currentY }; }; - // } else { - // this.eventWrapper = e => { return { start: e.startX, current: e.currentX }; }; - // } - - // The void space exists to handle the case where all other views are fixed size - // this.addView(new VoidView(), 0); } - // private getContainerSize(): number { - // return this.orientation === Orientation.VERTICAL - // ? dom.getContentHeight(this.container) - // : dom.getContentWidth(this.container); - // } - addView(view: IView, size: number, index = this.viewItems.length): void { - // Create view container - const container = document.createElement('div'); - dom.addClass(container, 'split-view-view'); - const containerDisposable = toDisposable(() => this.el.removeChild(container)); + // Add view + const container = dom.$('.split-view-view'); - // Create item - const item: IViewItem = { view, container, explicitSize: size, size, disposable: EmptyDisposable }; - this.viewItems.splice(index, 0, item); - - const onChangeDisposable = mapEvent(view.onDidChange, () => item)(this.onViewChange, this); - - // Disposable - item.disposable = combinedDisposable([onChangeDisposable, containerDisposable]); - - // Render view - view.render(container, this.orientation); - - // Attach view if (this.viewItems.length === 1) { this.el.appendChild(container); } else { this.el.insertBefore(container, this.el.children.item(index)); } + const onChangeDisposable = mapEvent(view.onDidChange, () => item)(this.onViewChange, this); + const containerDisposable = toDisposable(() => this.el.removeChild(container)); + const disposable = combinedDisposable([onChangeDisposable, containerDisposable]); + + const explicitSize = size; + const item: IViewItem = { view, container, explicitSize, size, disposable }; + this.viewItems.splice(index, 0, item); + // Add sash if (this.viewItems.length > 1) { const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; @@ -186,16 +129,8 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV this.sashItems.splice(index - 1, 0, sashItem); } - // TODO: layout - // go through all viewitems, set their size to preferred size - // sum all sizes up - // run expandcollapse - - this.viewItems.forEach(i => i.size = clamp(i.explicitSize, i.view.minimumSize, i.view.maximumSize)); - - const previousSize = this.size; - this.size = this.viewItems.reduce((r, i) => r + i.size, 0); - this.layout(previousSize); + view.render(container, this.orientation); + this.relayout(); } removeView(index: number): void { @@ -205,7 +140,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // Remove view const viewItem = this.viewItems.splice(index, 1)[0]; - const collapse = viewItem.size; viewItem.disposable.dispose(); // Remove sash @@ -215,21 +149,18 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV sashItem.disposable.dispose(); } - // Layout views - const up = range(index - 1, -1); - const down = range(index, this.viewItems.length); - const indexes = weave(up, down); - const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + this.relayout(); + } - this.expandCollapse(collapse, collapses, [], indexes, []); + private relayout(): void { + this.viewItems.forEach(i => i.size = clamp(i.explicitSize, i.view.minimumSize, i.view.maximumSize)); + + const previousSize = this.size; + this.size = this.viewItems.reduce((r, i) => r + i.size, 0); + this.layout(previousSize); } layout(size: number): void { - // size = size || this.getContainerSize(); - - // size = Math.max(size, this.viewItems.reduce((t, i) => t + i.view.minimumSize, 0)); - - if (this.size === size) { return; } @@ -237,11 +168,12 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV const indexes = range(this.viewItems.length - 1, -1); const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - const diff = Math.abs(this.size - size); + const totalViewsSize = this.viewItems.reduce((r, i) => r + i.size, 0); + const diff = Math.abs(totalViewsSize - size); - if (size < this.size) { + if (size < totalViewsSize) { this.expandCollapse(Math.min(diff, sum(collapses)), collapses, expands, indexes, []); - } else if (size > this.size) { + } else if (size > totalViewsSize) { this.expandCollapse(Math.min(diff, sum(expands)), collapses, expands, [], indexes); } @@ -288,8 +220,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV return; } - // this could maybe use the same code than the addView() does - // this.setupAnimation(); const index = this.viewItems.indexOf(item); @@ -302,7 +232,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - let collapse: number, collapseIndexes: number[], expandIndexes: number[]; if (size < item.size) { @@ -317,7 +246,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } this.expandCollapse(collapse, collapses, expands, collapseIndexes, expandIndexes); - // this.layoutViews(); } // private setupAnimation(): void { @@ -355,26 +283,26 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV this.sashItems.forEach(item => item.sash.layout()); // Update sashes enablement - // let previous = false; - // let collapsesDown = this.views.map(v => previous = (v.size - v.minimumSize > 0) || previous); + let previous = false; + const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous); - // previous = false; - // let expandsDown = this.views.map(v => previous = (v.maximumSize - v.size > 0) || previous); + previous = false; + const expandsDown = this.viewItems.map(i => previous = (i.view.maximumSize - i.size > 0) || previous); - // let reverseViews = this.views.slice().reverse(); - // previous = false; - // let collapsesUp = reverseViews.map(v => previous = (v.size - v.minimumSize > 0) || previous).reverse(); + const reverseViews = [...this.viewItems].reverse(); + previous = false; + const collapsesUp = reverseViews.map(i => previous = (i.size - i.view.minimumSize > 0) || previous).reverse(); - // previous = false; - // let expandsUp = reverseViews.map(v => previous = (v.maximumSize - v.size > 0) || previous).reverse(); + previous = false; + const expandsUp = reverseViews.map(i => previous = (i.view.maximumSize - i.size > 0) || previous).reverse(); - // this.sashes.forEach((s, i) => { - // if ((collapsesDown[i] && expandsUp[i + 1]) || (expandsDown[i] && collapsesUp[i + 1])) { - // s.enable(); - // } else { - // s.disable(); - // } - // }); + this.sashItems.forEach((s, i) => { + if ((collapsesDown[i] && expandsUp[i + 1]) || (expandsDown[i] && collapsesUp[i + 1])) { + s.sash.enable(); + } else { + s.sash.disable(); + } + }); } getVerticalSashLeft(sash: Sash): number { @@ -400,5 +328,10 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } dispose(): void { + this.viewItems.forEach(i => i.disposable.dispose()); + this.viewItems = []; + + this.sashItems.forEach(i => i.disposable.dispose()); + this.sashItems = []; } } diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 60d531b6c41..8ae66da6710 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -155,11 +155,26 @@ suite('Splitview', () => { splitview.addView(view, 20); assert.equal(view.size, TOTAL_SIZE, 'view was stretched'); + splitview.layout(TOTAL_SIZE); + assert.equal(view.size, TOTAL_SIZE, 'view stayed the same'); + + splitview.layout(100); + assert.equal(view.size, 100, 'view was collapsed'); + + splitview.layout(20); + assert.equal(view.size, 20, 'view was collapsed'); + + splitview.layout(10); + assert.equal(view.size, 20, 'view was clamped'); + + splitview.layout(TOTAL_SIZE); + assert.equal(view.size, TOTAL_SIZE, 'view was stretched'); + splitview.dispose(); view.dispose(); }); - test('splitview respects preferred sizes', () => { + test('splitview respects preferred sizes with structural changes', () => { const view1 = new TestView(20, Number.POSITIVE_INFINITY); const view2 = new TestView(20, Number.POSITIVE_INFINITY); const view3 = new TestView(20, Number.POSITIVE_INFINITY); From 845fa13b416abd6ee5cf34c5ffbbfa7bf12d0575 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 14 Sep 2017 14:45:16 -0700 Subject: [PATCH 102/145] Tweak colorization of regexp for light+ and dark+ --- .../colorize-results/test-regex_coffee.json | 16 ++-- .../test/colorize-results/test_coffee.json | 36 ++++----- .../make/test/colorize-results/makefile.json | 20 ++--- .../perl/test/colorize-results/test2_pl.json | 16 ++-- .../perl/test/colorize-results/test_pl.json | 36 ++++----- extensions/php/package.json | 2 +- .../colorize-results/issue-28354_php.json | 8 +- .../python/test/colorize-results/test_py.json | 76 +++++++++---------- .../ruby/test/colorize-results/test_rb.json | 16 ++-- .../scss/test/colorize-results/test_scss.json | 12 +-- .../theme-defaults/themes/dark_plus.json | 39 +++++++--- .../theme-defaults/themes/light_plus.json | 31 ++++++-- 12 files changed, 170 insertions(+), 138 deletions(-) diff --git a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json index 909a6112f35..445fab1f1c2 100644 --- a/extensions/coffeescript/test/colorize-results/test-regex_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test-regex_coffee.json @@ -69,8 +69,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -80,8 +80,8 @@ "c": "\\d", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.character-class.regexp: #D16969", + "light_plus": "constant.character.character-class.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -91,8 +91,8 @@ "c": "+", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -102,8 +102,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" diff --git a/extensions/coffeescript/test/colorize-results/test_coffee.json b/extensions/coffeescript/test/colorize-results/test_coffee.json index 4320ae579e6..a36d10633bf 100644 --- a/extensions/coffeescript/test/colorize-results/test_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test_coffee.json @@ -1378,8 +1378,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1389,8 +1389,8 @@ "c": "\\d", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.character-class.regexp: #D16969", + "light_plus": "constant.character.character-class.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1400,8 +1400,8 @@ "c": "+", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -1411,8 +1411,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1466,8 +1466,8 @@ "c": "(", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1477,8 +1477,8 @@ "c": "\\w", "t": "source.coffee string.regexp.coffee meta.group.regexp constant.character.character-class.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.character-class.regexp: #D16969", + "light_plus": "constant.character.character-class.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1488,8 +1488,8 @@ "c": "*", "t": "source.coffee string.regexp.coffee meta.group.regexp keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -1499,8 +1499,8 @@ "c": ")", "t": "source.coffee string.regexp.coffee meta.group.regexp punctuation.definition.group.regexp", "r": { - "dark_plus": "punctuation.definition.group.regexp: #D7BA7D", - "light_plus": "punctuation.definition.group.regexp: #FF0000", + "dark_plus": "punctuation.definition.group.regexp: #CE9178", + "light_plus": "punctuation.definition.group.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -1554,8 +1554,8 @@ "c": "$", "t": "source.coffee string.regexp.coffee keyword.control.anchor.regexp", "r": { - "dark_plus": "keyword.control.anchor.regexp: #C586C0", - "light_plus": "keyword.control.anchor.regexp: #09885A", + "dark_plus": "keyword.control.anchor.regexp: #DCDCAA", + "light_plus": "keyword.control.anchor.regexp: #FF0000", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0" diff --git a/extensions/make/test/colorize-results/makefile.json b/extensions/make/test/colorize-results/makefile.json index 1fb93bab87c..94d9b456703 100644 --- a/extensions/make/test/colorize-results/makefile.json +++ b/extensions/make/test/colorize-results/makefile.json @@ -135,8 +135,8 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -278,8 +278,8 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -322,8 +322,8 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "comment: #608B4E", "light_vs": "comment: #008000", "hc_black": "constant.character: #569CD6" @@ -377,8 +377,8 @@ "c": "\\", "t": "source.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "comment: #608B4E", "light_vs": "comment: #008000", "hc_black": "constant.character: #569CD6" @@ -553,8 +553,8 @@ "c": "\\", "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" diff --git a/extensions/perl/test/colorize-results/test2_pl.json b/extensions/perl/test/colorize-results/test2_pl.json index af312ff8930..bf690458af4 100644 --- a/extensions/perl/test/colorize-results/test2_pl.json +++ b/extensions/perl/test/colorize-results/test2_pl.json @@ -1301,8 +1301,8 @@ "c": "\\d\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1323,8 +1323,8 @@ "c": "\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1345,8 +1345,8 @@ "c": "\\d\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1774,8 +1774,8 @@ "c": "\\d", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" diff --git a/extensions/perl/test/colorize-results/test_pl.json b/extensions/perl/test/colorize-results/test_pl.json index 8062166dc5c..e6551c2c639 100644 --- a/extensions/perl/test/colorize-results/test_pl.json +++ b/extensions/perl/test/colorize-results/test_pl.json @@ -388,8 +388,8 @@ "c": "\\s", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -410,8 +410,8 @@ "c": "\\s", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -432,8 +432,8 @@ "c": "\\(", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -454,8 +454,8 @@ "c": "\\)", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -476,8 +476,8 @@ "c": "\\)", "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -674,8 +674,8 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -949,8 +949,8 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -1444,8 +1444,8 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -2280,8 +2280,8 @@ "c": "\\n", "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/php/package.json b/extensions/php/package.json index e3b313bb321..3f50c17669b 100644 --- a/extensions/php/package.json +++ b/extensions/php/package.json @@ -27,7 +27,7 @@ "PHP", "php" ], - "firstLine": "^#!/.*\\bphp\\b", + "firstLine": "^#!/.*\\bphp\\b", "mimetypes": [ "application/x-php" ], diff --git a/extensions/php/test/colorize-results/issue-28354_php.json b/extensions/php/test/colorize-results/issue-28354_php.json index 5f1b87f3834..10314265464 100644 --- a/extensions/php/test/colorize-results/issue-28354_php.json +++ b/extensions/php/test/colorize-results/issue-28354_php.json @@ -278,8 +278,8 @@ "c": "\\'", "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -377,8 +377,8 @@ "c": "\\'", "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/python/test/colorize-results/test_py.json b/extensions/python/test/colorize-results/test_py.json index ef8d364c52b..235958f078f 100644 --- a/extensions/python/test/colorize-results/test_py.json +++ b/extensions/python/test/colorize-results/test_py.json @@ -5294,8 +5294,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5305,8 +5305,8 @@ "c": "[", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "meta.character.set.regexp: #D7BA7D", - "light_plus": "meta.character.set.regexp: #FF0000", + "dark_plus": "punctuation.character.set.begin.regexp: #CE9178", + "light_plus": "punctuation.character.set.begin.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5316,8 +5316,8 @@ "c": "0-9-", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.set.regexp: #D16969", + "light_plus": "constant.character.set.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -5327,8 +5327,8 @@ "c": "]", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp", "r": { - "dark_plus": "meta.character.set.regexp: #D7BA7D", - "light_plus": "meta.character.set.regexp: #FF0000", + "dark_plus": "punctuation.character.set.end.regexp: #CE9178", + "light_plus": "punctuation.character.set.end.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5338,8 +5338,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5349,8 +5349,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5371,8 +5371,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5382,8 +5382,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5393,8 +5393,8 @@ "c": "[", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "meta.character.set.regexp: #D7BA7D", - "light_plus": "meta.character.set.regexp: #FF0000", + "dark_plus": "punctuation.character.set.begin.regexp: #CE9178", + "light_plus": "punctuation.character.set.begin.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5404,8 +5404,8 @@ "c": "A-Za-z", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.set.regexp: #D16969", + "light_plus": "constant.character.set.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -5415,8 +5415,8 @@ "c": "]", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python meta.character.set.regexp punctuation.character.set.end.regexp constant.other.set.regexp", "r": { - "dark_plus": "meta.character.set.regexp: #D7BA7D", - "light_plus": "meta.character.set.regexp: #FF0000", + "dark_plus": "punctuation.character.set.end.regexp: #CE9178", + "light_plus": "punctuation.character.set.end.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5426,8 +5426,8 @@ "c": "+", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5437,8 +5437,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5470,8 +5470,8 @@ "c": "+", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5481,8 +5481,8 @@ "c": "(", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.begin.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -5503,8 +5503,8 @@ "c": "*", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python keyword.operator.quantifier.regexp", "r": { - "dark_plus": "keyword.operator.quantifier.regexp: #D4D4D4", - "light_plus": "keyword.operator.quantifier.regexp: #0000FF", + "dark_plus": "keyword.operator.quantifier.regexp: #D7BA7D", + "light_plus": "keyword.operator.quantifier.regexp: #000000", "dark_vs": "keyword.operator: #D4D4D4", "light_vs": "keyword.operator: #000000", "hc_black": "keyword.operator: #D4D4D4" @@ -5514,8 +5514,8 @@ "c": ")", "t": "source.python meta.function-call.python meta.function-call.arguments.python string.regexp.quoted.single.python support.other.parenthesis.regexp punctuation.parenthesis.end.regexp", "r": { - "dark_plus": "support.other.parenthesis.regexp: #D7BA7D", - "light_plus": "support.other.parenthesis.regexp: #FF0000", + "dark_plus": "support.other.parenthesis.regexp: #CE9178", + "light_plus": "support.other.parenthesis.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -6504,8 +6504,8 @@ "c": "[", "t": "source.python string.regexp.quoted.multi.python meta.character.set.regexp punctuation.character.set.begin.regexp constant.other.set.regexp", "r": { - "dark_plus": "meta.character.set.regexp: #D7BA7D", - "light_plus": "meta.character.set.regexp: #FF0000", + "dark_plus": "punctuation.character.set.begin.regexp: #CE9178", + "light_plus": "punctuation.character.set.begin.regexp: #D16969", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "string.regexp: #D16969" @@ -6515,8 +6515,8 @@ "c": "1,2)`` leads to", "t": "source.python string.regexp.quoted.multi.python meta.character.set.regexp constant.character.set.regexp", "r": { - "dark_plus": "constant.character: #569CD6", - "light_plus": "constant.character: #0000FF", + "dark_plus": "constant.character.set.regexp: #D16969", + "light_plus": "constant.character.set.regexp: #811F3F", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" diff --git a/extensions/ruby/test/colorize-results/test_rb.json b/extensions/ruby/test/colorize-results/test_rb.json index 005f04f37c3..996dbbf0192 100644 --- a/extensions/ruby/test/colorize-results/test_rb.json +++ b/extensions/ruby/test/colorize-results/test_rb.json @@ -2500,8 +2500,8 @@ "c": "\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2522,8 +2522,8 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2544,8 +2544,8 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2577,8 +2577,8 @@ "c": "\\.\\d", "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" diff --git a/extensions/scss/test/colorize-results/test_scss.json b/extensions/scss/test/colorize-results/test_scss.json index 301d6fc35fd..cc598d4c7a2 100644 --- a/extensions/scss/test/colorize-results/test_scss.json +++ b/extensions/scss/test/colorize-results/test_scss.json @@ -20716,8 +20716,8 @@ "c": "\\\\", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -20837,8 +20837,8 @@ "c": "\\'", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -20914,8 +20914,8 @@ "c": "\\\"", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.double.scss constant.character.escape.scss", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index 55052a69d66..6fdfb2263ce 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -103,28 +103,44 @@ } }, { + "name": "Regular expression groups", "scope": [ "punctuation.definition.group.regexp", "punctuation.definition.group.assertion.regexp", "punctuation.definition.character-class.regexp", + "punctuation.character.set.begin.regexp", + "punctuation.character.set.end.regexp", "keyword.operator.negation.regexp", - "support.other.parenthesis.regexp", - "meta.character.set.regexp" + "support.other.parenthesis.regexp" ], "settings": { - "foreground": "#d7ba7d" + "foreground": "#CE9178" + } + }, + { + "scope": [ + "constant.character.character-class.regexp", + "constant.other.character-class.set.regexp", + "constant.other.character-class.regexp", + "constant.character.set.regexp" + ], + "settings": { + "foreground": "#d16969" + } + }, + { + "scope": [ + "keyword.operator.or.regexp", + "keyword.control.anchor.regexp" + ], + "settings": { + "foreground": "#DCDCAA" } }, { "scope": "keyword.operator.quantifier.regexp", "settings": { - "foreground": "#d4d4d4" - } - }, - { - "scope": "keyword.control.anchor.regexp", - "settings": { - "foreground": "#C586C0" + "foreground": "#d7ba7d" } }, { @@ -136,9 +152,8 @@ { "scope": "constant.character.escape", "settings": { - "foreground": "#C586C0" + "foreground": "#d7ba7d" } } - ] } \ No newline at end of file diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index b533627c9f2..3d5775ecec5 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -103,28 +103,44 @@ } }, { + "name": "Regular expression groups", "scope": [ "punctuation.definition.group.regexp", "punctuation.definition.group.assertion.regexp", "punctuation.definition.character-class.regexp", + "punctuation.character.set.begin.regexp", + "punctuation.character.set.end.regexp", "keyword.operator.negation.regexp", - "support.other.parenthesis.regexp", - "meta.character.set.regexp" + "support.other.parenthesis.regexp" ], "settings": { - "foreground": "#ff0000" + "foreground": "#d16969" + } + }, + { + "scope": [ + "constant.character.character-class.regexp", + "constant.other.character-class.set.regexp", + "constant.other.character-class.regexp", + "constant.character.set.regexp" + ], + "settings": { + "foreground": "#811f3f" } }, { "scope": "keyword.operator.quantifier.regexp", "settings": { - "foreground": "#0000ff" + "foreground": "#000000" } }, { - "scope": "keyword.control.anchor.regexp", + "scope": [ + "keyword.operator.or.regexp", + "keyword.control.anchor.regexp" + ], "settings": { - "foreground": "#09885a" + "foreground": "#ff0000" } }, { @@ -136,8 +152,9 @@ { "scope": "constant.character.escape", "settings": { - "foreground": "#ff0000" + "foreground": "#a31515" } } + ] } \ No newline at end of file From bf9671193fa053914c16929d63e2397a488d88e2 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Fri, 15 Sep 2017 00:42:32 +0200 Subject: [PATCH 103/145] node-debug@1.17.5 --- build/gulpfile.vscode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index bfa2a0bd8a3..f1807d26252 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -43,7 +43,7 @@ const nodeModules = ['electron', 'original-fs'] // Build const builtInExtensions = [ - { name: 'ms-vscode.node-debug', version: '1.17.4' }, + { name: 'ms-vscode.node-debug', version: '1.17.5' }, { name: 'ms-vscode.node-debug2', version: '1.17.1' } ]; From 6c4274d7e53913cc905dcd20e59f6d7a9c4b7697 Mon Sep 17 00:00:00 2001 From: Ramya Achutha Rao Date: Thu, 14 Sep 2017 19:25:18 -0700 Subject: [PATCH 104/145] Find exe based recommendations only when needed #34371 --- .../electron-browser/extensionTipsService.ts | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index cedea9bb663..6761e846ab6 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -26,7 +26,7 @@ import { IExtensionsConfiguration, ConfigurationKey } from 'vs/workbench/parts/e import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import * as cp from 'child_process'; +import * as fs from 'fs'; import { distinct } from 'vs/base/common/arrays'; interface IExtensionsContent { @@ -68,7 +68,6 @@ export class ExtensionTipsService implements IExtensionTipsService { this._suggestTips(); this._suggestWorkspaceRecommendations(); - this._suggestBasedOnExecutables(); } getWorkspaceRecommendations(): TPromise { @@ -92,7 +91,7 @@ export class ExtensionTipsService implements IExtensionTipsService { const fileBased = Object.keys(this._fileBasedRecommendations) .filter(recommendation => allRecomendations.indexOf(recommendation) !== -1); - const exeBased = distinct(this._exeBasedRecommendations); + const exeBased = distinct(this._suggestBasedOnExecutables()); this.telemetryService.publicLog('extensionRecommendations:unfiltered', { fileBased, exeBased }); @@ -319,15 +318,42 @@ export class ExtensionTipsService implements IExtensionTipsService { }); } - private _suggestBasedOnExecutables() { - const cmd = process.platform === 'win32' ? 'where' : 'which'; + private _suggestBasedOnExecutables(): string[] { + if (!process.env.PATH || this._exeBasedRecommendations.length > 0) { + return this._exeBasedRecommendations; + } + + let envpaths = process.env.PATH.split(process.platform === 'win32' ? ';' : ':'); + let foundExecutables: Set = new Set(); + + // Loop through recommended extensions forEach(product.exeBasedExtensionTips, entry => { - cp.exec(`${cmd} ${entry.value.replace(/,/g, ' ')}`, (err, stdout, stderr) => { - if (stdout) { - this._exeBasedRecommendations.push(entry.key); + let executables = entry.value.split(','); + + // Loop through executables that would result in recommending current extension + for (let i = 0; i < executables.length; i++) { + if (!foundExecutables.has(executables[i])) { + + // Loop through paths in PATH to find current executable + for (let pathEntry of envpaths) { + let fullPath = paths.join(pathEntry, executables[i]); + if (process.platform === 'win32') { + fullPath += '.exe'; + } + if (fs.existsSync(fullPath)) { + foundExecutables.add(executables[i]); + break; + } + } } - }); + if (foundExecutables.has(executables[i])) { + this._exeBasedRecommendations.push(entry.key); + break; + } + } }); + + return this._exeBasedRecommendations; } private setIgnoreRecommendationsConfig(configVal: boolean) { From 9a38cc36a5a908abf9b510e753d158c6f3783df4 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 14 Sep 2017 16:20:41 -0700 Subject: [PATCH 105/145] Fix missing colorization test update --- extensions/json/test/colorize-results/test_json.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/json/test/colorize-results/test_json.json b/extensions/json/test/colorize-results/test_json.json index facb8d52a57..f5295bcf70a 100644 --- a/extensions/json/test/colorize-results/test_json.json +++ b/extensions/json/test/colorize-results/test_json.json @@ -388,8 +388,8 @@ "c": "\\u0056", "t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json constant.character.escape.json", "r": { - "dark_plus": "constant.character.escape: #C586C0", - "light_plus": "constant.character.escape: #FF0000", + "dark_plus": "constant.character.escape: #D7BA7D", + "light_plus": "constant.character.escape: #A31515", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" From 7683db24b205be619520eb8992003b593e93c3af Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 15 Sep 2017 07:34:32 +0200 Subject: [PATCH 106/145] Create File overwrites existing files without warning (fixes #33899) --- src/vs/platform/files/common/files.ts | 11 +++++- .../files/electron-browser/fileService.ts | 6 +-- .../services/files/node/fileService.ts | 36 ++++++++++++----- .../files/test/node/fileService.test.ts | 39 +++++++++++++++++++ .../workbench/test/workbenchTestServices.ts | 4 +- 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 455db1408ec..c89cc6399bf 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -93,7 +93,7 @@ export interface IFileService { * * The optional parameter content can be used as value to fill into the new file. */ - createFile(resource: URI, content?: string): TPromise; + createFile(resource: URI, content?: string, options?: ICreateFileOptions): TPromise; /** * Creates a new folder with the given path. The returned promise @@ -491,6 +491,15 @@ export interface IResolveFileOptions { resolveSingleChildDescendants?: boolean; } +export interface ICreateFileOptions { + + /** + * Overwrite the file to create if it already exists on disk. Otherwise + * an error will be thrown (FILE_MODIFIED_SINCE). + */ + overwrite?: boolean; +} + export interface IImportResult { stat: IFileStat; isNew: boolean; diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 980b301890a..5c63068eddf 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -12,7 +12,7 @@ import encoding = require('vs/base/node/encoding'); import errors = require('vs/base/common/errors'); import uri from 'vs/base/common/uri'; import { toResource } from 'vs/workbench/common/editor'; -import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent } from 'vs/platform/files/common/files'; +import { FileOperation, FileOperationEvent, IFileService, IFilesConfiguration, IResolveFileOptions, IFileStat, IResolveFileResult, IContent, IStreamContent, IImportResult, IResolveContentOptions, IUpdateContentOptions, FileChangesEvent, ICreateFileOptions } from 'vs/platform/files/common/files'; import { FileService as NodeFileService, IFileServiceOptions, IEncodingOverride } from 'vs/workbench/services/files/node/fileService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -224,8 +224,8 @@ export class FileService implements IFileService { return this.raw.copyFile(source, target, overwrite); } - public createFile(resource: uri, content?: string): TPromise { - return this.raw.createFile(resource, content); + public createFile(resource: uri, content?: string, options?: ICreateFileOptions): TPromise { + return this.raw.createFile(resource, content, options); } public createFolder(resource: uri): TPromise { diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index 02be0c0be68..5d08ba12177 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -11,7 +11,7 @@ import os = require('os'); import crypto = require('crypto'); import assert = require('assert'); -import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, MAX_FILE_SIZE, FileChangesEvent, IFilesConfiguration } from 'vs/platform/files/common/files'; +import { isParent, FileOperation, FileOperationEvent, IContent, IFileService, IResolveFileOptions, IResolveFileResult, IResolveContentOptions, IFileStat, IStreamContent, FileOperationError, FileOperationResult, IUpdateContentOptions, FileChangeType, IImportResult, MAX_FILE_SIZE, FileChangesEvent, IFilesConfiguration, ICreateFileOptions } from 'vs/platform/files/common/files'; import { isEqualOrParent } from 'vs/base/common/paths'; import { ResourceMap } from 'vs/base/common/map'; import arrays = require('vs/base/common/arrays'); @@ -220,7 +220,7 @@ export class FileService implements IFileService { // Guard early against attempts to resolve an invalid file path if (resource.scheme !== 'file' || !resource.fsPath) { return TPromise.wrapError(new FileOperationError( - nls.localize('fileInvalidPath', "Invalid file resource ({0})", resource.toString()), + nls.localize('fileInvalidPath', "Invalid file resource ({0})", resource.toString(true)), FileOperationResult.FILE_INVALID_PATH )); } @@ -292,7 +292,7 @@ export class FileService implements IFileService { // Return if file not found if (!exists) { return TPromise.wrapError(new FileOperationError( - nls.localize('fileNotFoundError', "File not found ({0})", resource.toString()), + nls.localize('fileNotFoundError', "File not found ({0})", resource.toString(true)), FileOperationResult.FILE_NOT_FOUND )); } @@ -381,15 +381,33 @@ export class FileService implements IFileService { }); } - public createFile(resource: uri, content: string = ''): TPromise { + public createFile(resource: uri, content: string = '', options: ICreateFileOptions = Object.create(null)): TPromise { + const absolutePath = this.toAbsolutePath(resource); - // Create file - return this.updateContent(resource, content).then(result => { + let checkFilePromise: TPromise; + if (options.overwrite) { + checkFilePromise = TPromise.as(false); + } else { + checkFilePromise = pfs.exists(absolutePath); + } - // Events - this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); + // Check file exists + return checkFilePromise.then(exists => { + if (exists && !options.overwrite) { + return TPromise.wrapError(new FileOperationError( + nls.localize('fileExists', "File to create already exits ({0})", resource.toString(true)), + FileOperationResult.FILE_MODIFIED_SINCE + )); + } - return result; + // Create file + return this.updateContent(resource, content).then(result => { + + // Events + this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, result)); + + return result; + }); }); } diff --git a/src/vs/workbench/services/files/test/node/fileService.test.ts b/src/vs/workbench/services/files/test/node/fileService.test.ts index e345b6a0d2d..c9ebdeabde9 100644 --- a/src/vs/workbench/services/files/test/node/fileService.test.ts +++ b/src/vs/workbench/services/files/test/node/fileService.test.ts @@ -71,6 +71,45 @@ suite('FileService', () => { }, error => onError(error, done)); }); + test('createFile (does not overwrite by default)', function (done: () => void) { + const contents = 'Hello World'; + const resource = uri.file(path.join(testDir, 'test.txt')); + + fs.writeFileSync(resource.fsPath, ''); // create file + + service.createFile(resource, contents).done(null, error => { + assert.ok(error); + + done(); + }); + }); + + test('createFile (allows to overwrite existing)', function (done: () => void) { + let event: FileOperationEvent; + const toDispose = service.onAfterOperation(e => { + event = e; + }); + + const contents = 'Hello World'; + const resource = uri.file(path.join(testDir, 'test.txt')); + + fs.writeFileSync(resource.fsPath, ''); // create file + + service.createFile(resource, contents, { overwrite: true }).done(s => { + assert.equal(s.name, 'test.txt'); + assert.equal(fs.existsSync(s.resource.fsPath), true); + assert.equal(fs.readFileSync(s.resource.fsPath), contents); + + assert.ok(event); + assert.equal(event.resource.fsPath, resource.fsPath); + assert.equal(event.operation, FileOperation.CREATE); + assert.equal(event.target.resource.fsPath, resource.fsPath); + toDispose.dispose(); + + done(); + }, error => onError(error, done)); + }); + test('createFolder', function (done: () => void) { let event: FileOperationEvent; const toDispose = service.onAfterOperation(e => { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index d9ef1d58aff..80a54b01068 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -34,7 +34,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { IEditorGroupService, GroupArrangement, GroupOrientation, IEditorTabOptions, IMoveOptions } from 'vs/workbench/services/group/common/groupService'; import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService'; -import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent } from 'vs/platform/files/common/files'; +import { FileOperationEvent, IFileService, IResolveContentOptions, FileOperationError, IFileStat, IResolveFileResult, IImportResult, FileChangesEvent, IResolveFileOptions, IContent, IUpdateContentOptions, IStreamContent, ICreateFileOptions } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl'; import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; @@ -749,7 +749,7 @@ export class TestFileService implements IFileService { return TPromise.as(null); } - createFile(resource: URI, content?: string): TPromise { + createFile(resource: URI, content?: string, options?: ICreateFileOptions): TPromise { return TPromise.as(null); } From d23dce6a7c0f89602b27ddfbd8d2ecb9f9131458 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 10:34:19 +0200 Subject: [PATCH 107/145] smoke: loosen up localization assertions --- test/smoke/src/areas/workbench/localization.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index 64170e8bf11..ebed884c5ed 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -21,26 +21,26 @@ describe('Localization', () => { let text = await app.workbench.explorer.getOpenEditorsViewTitle(); await app.screenCapturer.capture('Open editors title'); - assert.equal(text.toLowerCase(), 'geöffnete editoren'); + assert(/geöffnete editoren/i.test(text)); await app.workbench.search.openSearchViewlet(); text = await app.workbench.search.getTitle(); await app.screenCapturer.capture('Search title'); - assert.equal(text.toLowerCase(), 'suchen'); + assert(/suchen/i.test(text)); await app.workbench.scm.openSCMViewlet(); text = await app.workbench.scm.getTitle(); await app.screenCapturer.capture('Scm title'); - assert.equal(text.toLowerCase(), 'quellcodeverwaltung: vscode-smoketest-express (git)'); + assert(/quellcodeverwaltung/i.test(text)); await app.workbench.debug.openDebugViewlet(); text = await app.workbench.debug.getTitle(); await app.screenCapturer.capture('Debug title'); - assert.equal(text.toLowerCase(), 'debuggen'); + assert(/debuggen/i.test(text)); await app.workbench.extensions.openExtensionsViewlet(); text = await app.workbench.extensions.getTitle(); await app.screenCapturer.capture('Extensions title'); - assert.equal(text.toLowerCase(), 'erweiterungen'); + assert(/erweiterungen/i.test(text)); }); }); \ No newline at end of file From e3a05e01869b76e552e83c4aa0b0e8dc2c4e1ae8 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 10:41:58 +0200 Subject: [PATCH 108/145] smoke: wait for marketplace for longer than 5 seconds --- test/smoke/src/areas/extensions/extensions.ts | 6 +++++- test/smoke/src/spectron/client.ts | 9 +++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/test/smoke/src/areas/extensions/extensions.ts b/test/smoke/src/areas/extensions/extensions.ts index 85e31128658..af4fdbb47a0 100644 --- a/test/smoke/src/areas/extensions/extensions.ts +++ b/test/smoke/src/areas/extensions/extensions.ts @@ -33,7 +33,11 @@ export class Extensions extends Viewlet { public async installExtension(name: string): Promise { await this.searchForExtension(name); - await this.spectron.client.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.install`); + + // we might want to wait for a while longer since the Marketplace can be slow + // a minute should do + await this.spectron.client.waitFor(() => this.spectron.client.click(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.install`), void 0, 'waiting for install button', 600); + await this.spectron.client.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.reload`); return true; } diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index ddc67fb7a1e..e04cdd7b73a 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -145,14 +145,15 @@ export class SpectronClient { return this.spectron.client.getTitle(); } - public async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string): Promise; - public async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string): Promise { + public async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; + public async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { let trial = 1; + retryCount = typeof retryCount === 'number' ? retryCount : this.retryCount; while (true) { - if (trial > this.retryCount) { + if (trial > retryCount) { this.application.screenCapturer.capture('timeout'); - throw new Error(`${timeoutMessage}: Timed out after ${(this.retryCount * this.retryDuration) / 1000} seconds.`); + throw new Error(`${timeoutMessage}: Timed out after ${(retryCount * this.retryDuration) / 1000} seconds.`); } let result; From dfe003d75ea40c8881b1bdb8f9949699f1b9cc5a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 10:59:07 +0200 Subject: [PATCH 109/145] smoke: careful with screeshot capturing --- test/smoke/src/helpers/screenshot.ts | 2 +- test/smoke/src/spectron/client.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/smoke/src/helpers/screenshot.ts b/test/smoke/src/helpers/screenshot.ts index e991a4fb9fe..289e600b728 100644 --- a/test/smoke/src/helpers/screenshot.ts +++ b/test/smoke/src/helpers/screenshot.ts @@ -25,7 +25,6 @@ export class ScreenCapturer { return; } - const image = await this.application.browserWindow.capturePage(); const screenshotPath = path.join( SCREENSHOTS_DIR, sanitize(this.suiteName), @@ -33,6 +32,7 @@ export class ScreenCapturer { `${ScreenCapturer.counter++}-${sanitize(name)}.png` ); + const image = await this.application.browserWindow.capturePage(); await new Promise((c, e) => mkdirp(path.dirname(screenshotPath), err => err ? e(err) : c())); await new Promise((c, e) => fs.writeFile(screenshotPath, image, err => err ? e(err) : c())); } diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index e04cdd7b73a..2d48c427cd4 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -152,7 +152,7 @@ export class SpectronClient { while (true) { if (trial > retryCount) { - this.application.screenCapturer.capture('timeout'); + await this.application.screenCapturer.capture('timeout'); throw new Error(`${timeoutMessage}: Timed out after ${(retryCount * this.retryDuration) / 1000} seconds.`); } From 4c26c77894e60d1db0f70852a5b74b2e4662c186 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 10:59:17 +0200 Subject: [PATCH 110/145] smoke: more debug screenshots --- test/smoke/src/areas/debug/debug.test.ts | 36 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index e3f2a52b980..1d5e0c080cf 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -62,47 +62,65 @@ describe('Debug', () => { it('breakpoints', async function () { await app.workbench.openFile('index.js'); await app.workbench.debug.setBreakpointOnLine(6); + await app.screenCapturer.capture('breakpoints are set'); }); it('start debugging', async function () { port = await app.workbench.debug.startDebugging(); - http.get(`http://localhost:${port}`).on('error', e => void 0); + await app.screenCapturer.capture('debugging has started'); + + await new Promise((c, e) => http.get(`http://localhost:${port}`).on('response', c).on('error', e)); + await app.screenCapturer.capture('server was pinged'); await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); + await app.screenCapturer.capture('debugging is paused'); }); it('focus stack frames and variables', async function () { - assert.equal(await app.workbench.debug.getLocalVariableCount(), 4); + await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables'); + await app.workbench.debug.focusStackFrame('layer.js'); - assert.equal(await app.workbench.debug.getLocalVariableCount(), 5); + await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 5, 'there should be 5 local variables'); + await app.workbench.debug.focusStackFrame('route.js'); - assert.equal(await app.workbench.debug.getLocalVariableCount(), 3); + await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 3, 'there should be 3 local variables'); + await app.workbench.debug.focusStackFrame('index.js'); - assert.equal(await app.workbench.debug.getLocalVariableCount(), 4); + await app.client.waitFor(() => app.workbench.debug.getLocalVariableCount(), c => c === 4, 'there should be 4 local variables'); }); it('stepOver, stepIn, stepOut', async function () { await app.workbench.debug.stepIn(); + await app.screenCapturer.capture('debugging has stepped in'); + const first = await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js'); await app.workbench.debug.stepOver(); + await app.screenCapturer.capture('debugging has stepped over'); + await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js' && sf.lineNumber === first.lineNumber + 1); await app.workbench.debug.stepOut(); + await app.screenCapturer.capture('debugging has stepped out'); + await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 7); }); - it('continue', async function () { await app.workbench.debug.continue(); - http.get(`http://localhost:${port}`).on('error', e => void 0); + await app.screenCapturer.capture('debugging has continued'); + + await new Promise((c, e) => http.get(`http://localhost:${port}`).on('response', c).on('error', e)); + await app.screenCapturer.capture('server was pinged'); + await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); + await app.screenCapturer.capture('debugging is paused'); }); it('debug console', async function () { - const result = await app.workbench.debug.console('2 + 2 \n'); - assert.equal(result, '4'); + await app.client.waitFor(() => app.workbench.debug.console('2 + 2 \n'), r => r === '4', 'debug console should return 2 + 2 = 4'); }); it('stop debugging', async function () { await app.workbench.debug.stopDebugging(); + await app.screenCapturer.capture('debugging has stopped'); }); }); From 655527d1564fe8de05e2c5a5337e11373efe950c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 15 Sep 2017 10:59:20 +0200 Subject: [PATCH 111/145] parse pattern for file watching --- .../api/node/extHostFileSystemEventService.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/api/node/extHostFileSystemEventService.ts b/src/vs/workbench/api/node/extHostFileSystemEventService.ts index 822298414c3..3ffcf452a3a 100644 --- a/src/vs/workbench/api/node/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/node/extHostFileSystemEventService.ts @@ -6,7 +6,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Disposable } from './extHostTypes'; -import { match } from 'vs/base/common/glob'; +import { parse, ParsedPattern } from 'vs/base/common/glob'; import { Uri, FileSystemWatcher as _FileSystemWatcher } from 'vscode'; import { FileSystemEvents, ExtHostFileSystemEventServiceShape } from './extHost.protocol'; @@ -17,6 +17,7 @@ class FileSystemWatcher implements _FileSystemWatcher { private _onDidDelete = new Emitter(); private _disposable: Disposable; private _config: number; + private _parsedPattern: ParsedPattern; get ignoreCreateEvents(): boolean { return Boolean(this._config & 0b001); @@ -43,24 +44,26 @@ class FileSystemWatcher implements _FileSystemWatcher { this._config += 0b100; } + this._parsedPattern = parse(globPattern); + let subscription = dispatcher(events => { if (!ignoreCreateEvents) { for (let created of events.created) { - if (match(globPattern, created.fsPath)) { + if (this._parsedPattern(created.fsPath)) { this._onDidCreate.fire(created); } } } if (!ignoreChangeEvents) { for (let changed of events.changed) { - if (match(globPattern, changed.fsPath)) { + if (this._parsedPattern(changed.fsPath)) { this._onDidChange.fire(changed); } } } if (!ignoreDeleteEvents) { for (let deleted of events.deleted) { - if (match(globPattern, deleted.fsPath)) { + if (this._parsedPattern(deleted.fsPath)) { this._onDidDelete.fire(deleted); } } From 48a286f962e3f417e377dbb9e61c05a3ac4c98c7 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Tue, 12 Sep 2017 21:56:36 +0200 Subject: [PATCH 112/145] Making tasks.json parser workspace folder aware --- src/vs/workbench/parts/tasks/common/tasks.ts | 6 + .../electron-browser/task.contribution.ts | 160 +++++++++++++++++- .../parts/tasks/node/taskConfiguration.ts | 47 ++--- .../electron-browser/configuration.test.ts | 6 +- 4 files changed, 174 insertions(+), 45 deletions(-) diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index fd9b28ce2d5..fab0ff45015 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import URI from 'vs/base/common/uri'; import * as Types from 'vs/base/common/types'; import { IJSONSchemaMap } from 'vs/base/common/jsonSchema'; @@ -221,7 +222,12 @@ export namespace TaskSourceKind { export const Composite: 'composite' = 'composite'; } +export interface WorkspaceFolder { + uri: URI; +} + export interface TaskSourceConfigElement { + workspaceFolder: WorkspaceFolder; file: string; index: number; element: any; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 5d30f4a319b..35223caa5fc 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -76,7 +76,7 @@ import { Scope, IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal'; import { ITaskSystem, ITaskResolver, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, TaskSystemEvents, TaskTerminateResponse } from 'vs/workbench/parts/tasks/common/taskSystem'; -import { Task, CustomTask, ConfiguringTask, ContributedTask, CompositeTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier } from 'vs/workbench/parts/tasks/common/tasks'; +import { Task, CustomTask, ConfiguringTask, ContributedTask, CompositeTask, TaskSet, TaskGroup, ExecutionEngine, JsonSchemaVersion, TaskSourceKind, TaskIdentifier, WorkspaceFolder } from 'vs/workbench/parts/tasks/common/tasks'; import { ITaskService, TaskServiceEvents, ITaskProvider, TaskEvent, RunOptions, CustomizationProperties } from 'vs/workbench/parts/tasks/common/taskService'; import { templates as taskTemplates } from 'vs/workbench/parts/tasks/common/taskTemplates'; @@ -618,7 +618,12 @@ interface WorkspaceTaskResult { hasErrors: boolean; } -interface WorkspaceConfigurationResult { +interface WorkspaceFolderTaskResult extends WorkspaceTaskResult { + workspaceFolder: WorkspaceFolder; +} + +interface WorkspaceFolderConfigurationResult { + workspaceFolder: WorkspaceFolder; config: TaskConfig.ExternalTaskRunnerConfiguration; hasErrors: boolean; } @@ -657,6 +662,9 @@ class TaskService extends EventEmitter implements ITaskService { private quickOpenService: IQuickOpenService; private _configHasErrors: boolean; + private _schemaVersion: JsonSchemaVersion; + private _executionEngine: ExecutionEngine; + private _workspaceFolders: WorkspaceFolder[]; private _providers: Map; private _workspaceTasksPromise: TPromise; @@ -736,6 +744,7 @@ class TaskService extends EventEmitter implements ITaskService { ); } }); + this.updateWorkspaceFolders(); lifecycleService.onWillShutdown(event => event.veto(this.beforeShutdown())); this.registerCommands(); } @@ -1449,8 +1458,9 @@ class TaskService extends EventEmitter implements ITaskService { }); } - private computeWorkspaceTasks(): TPromise { - let configPromise: TPromise; + /* + private computeWorkspaceTasks2(): TPromise { + let configPromise: TPromise; { let { config, hasParseErrors } = this.getConfiguration(); if (hasParseErrors) { @@ -1461,7 +1471,7 @@ class TaskService extends EventEmitter implements ITaskService { engine = TaskConfig.ExecutionEngine.from(config); if (engine === ExecutionEngine.Process) { if (this.hasDetectorSupport(config)) { - configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService, config).detect(true).then((value): WorkspaceConfigurationResult => { + configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService, config).detect(true).then((value): WorkspaceFolderConfigurationResult => { let hasErrors = this.printStderr(value.stderr); let detectedConfig = value.config; if (!detectedConfig) { @@ -1529,17 +1539,145 @@ class TaskService extends EventEmitter implements ITaskService { }); }); } + */ - private getExecutionEngine(): ExecutionEngine { - let { config } = this.getConfiguration(); + private computeWorkspaceTasks(): TPromise> { + if (this._workspaceFolders.length === 0) { + return TPromise.as(new Map()); + } else { + let promises: TPromise[] = []; + for (let folder of this._workspaceFolders) { + promises.push(this.computeWorkspaceFolderTasks(folder).then((value) => value, () => undefined)); + } + return TPromise.join(promises).then((values) => { + let result = new Map(); + for (let value of values) { + if (value) { + result.set(value.workspaceFolder.uri.toString(), value); + } + } + return result; + }); + } + } + + private computeWorkspaceFolderTasks(workspaceFolder: WorkspaceFolder): TPromise { + return (this._executionEngine === ExecutionEngine.Process + ? this.computeLegacyConfiguration(workspaceFolder) + : this.computeConfiguration(workspaceFolder)). + then((workspaceFolderConfiguration) => { + if (!workspaceFolderConfiguration || !workspaceFolderConfiguration.config || workspaceFolderConfiguration.hasErrors) { + return TPromise.as({ workspaceFolder, set: undefined, configurations: undefined, hasErrors: workspaceFolderConfiguration ? workspaceFolderConfiguration.hasErrors : false }); + } + return ProblemMatcherRegistry.onReady().then((): WorkspaceFolderTaskResult => { + let problemReporter = new ProblemReporter(this._outputChannel); + let parseResult = TaskConfig.parse(workspaceFolder, workspaceFolderConfiguration.config, problemReporter); + let hasErrors = false; + if (!parseResult.validationStatus.isOK()) { + hasErrors = true; + this.showOutput(); + } + if (problemReporter.status.isFatal()) { + problemReporter.fatal(nls.localize('TaskSystem.configurationErrors', 'Error: the provided task configuration has validation errors and can\'t not be used. Please correct the errors first.')); + return { workspaceFolder, set: undefined, configurations: undefined, hasErrors }; + } + let customizedTasks: { byIdentifier: IStringDictionary; }; + if (parseResult.configured && parseResult.configured.length > 0) { + customizedTasks = { + byIdentifier: Object.create(null) + }; + for (let task of parseResult.configured) { + customizedTasks.byIdentifier[task.configures._key] = task; + } + } + return { workspaceFolder, set: { tasks: parseResult.custom }, configurations: customizedTasks, hasErrors }; + }); + }); + } + + private computeConfiguration(workspaceFolder: WorkspaceFolder): TPromise { + let { config, hasParseErrors } = this.getConfiguration(workspaceFolder); + return TPromise.as({ workspaceFolder, config, hasErrors: hasParseErrors }); + } + + private computeLegacyConfiguration(workspaceFolder: WorkspaceFolder): TPromise { + let { config, hasParseErrors } = this.getConfiguration(workspaceFolder); + if (hasParseErrors) { + return TPromise.as({ workspaceFolder: workspaceFolder, hasErrors: true, config: undefined }); + } + if (config) { + if (this.hasDetectorSupport(config)) { + return new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService, config).detect(true).then((value): WorkspaceFolderConfigurationResult => { + let hasErrors = this.printStderr(value.stderr); + let detectedConfig = value.config; + if (!detectedConfig) { + return { workspaceFolder, config, hasErrors }; + } + let result: TaskConfig.ExternalTaskRunnerConfiguration = Objects.clone(config); + let configuredTasks: IStringDictionary = Object.create(null); + if (!result.tasks) { + if (detectedConfig.tasks) { + result.tasks = detectedConfig.tasks; + } + } else { + result.tasks.forEach(task => configuredTasks[task.taskName] = task); + detectedConfig.tasks.forEach((task) => { + if (!configuredTasks[task.taskName]) { + result.tasks.push(task); + } + }); + } + return { workspaceFolder, config: result, hasErrors }; + }); + } else { + return TPromise.as({ workspaceFolder, config, hasErrors: false }); + } + } else { + return new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService).detect(true).then((value) => { + let hasErrors = this.printStderr(value.stderr); + return { workspaceFolder, config: value.config, hasErrors }; + }); + } + } + + private updateWorkspaceFolders(): void { + if (this.contextService.hasFolderWorkspace()) { + let workspaceFolder = { uri: this.contextService.getWorkspace().roots[0] }; + this._workspaceFolders = [workspaceFolder]; + this._executionEngine = this.computeExecutionEngine(workspaceFolder); + this._schemaVersion = this.computeJsonSchemaVersion(workspaceFolder); + } else if (this.contextService.hasMultiFolderWorkspace()) { + this._executionEngine = ExecutionEngine.Terminal; + this._schemaVersion = JsonSchemaVersion.V2_0_0; + this._workspaceFolders = []; + for (let folder of this.contextService.getWorkspace().roots) { + let workspaceFolder = { uri: folder }; + if (this._schemaVersion === this.computeJsonSchemaVersion(workspaceFolder)) { + this._workspaceFolders.push(workspaceFolder); + } else { + this._outputChannel.append(nls.localize( + 'taskService.ignoreingFolder', + 'Ignoring task configurations for workspace folder {0}. Multi root folder support requires that all folders use task version 2.0.', + folder.fsPath)); + } + } + } else { + this._workspaceFolders = []; + this._executionEngine = ExecutionEngine.Terminal; + this._schemaVersion = JsonSchemaVersion.V2_0_0; + } + } + + private computeExecutionEngine(workspaceFolder: WorkspaceFolder): ExecutionEngine { + let { config } = this.getConfiguration(workspaceFolder); if (!config) { return ExecutionEngine._default; } return TaskConfig.ExecutionEngine.from(config); } - private getJsonSchemaVersion(): JsonSchemaVersion { - let { config } = this.getConfiguration(); + private computeJsonSchemaVersion(workspaceFolder: WorkspaceFolder): JsonSchemaVersion { + let { config } = this.getConfiguration(workspaceFolder); if (!config) { return JsonSchemaVersion.V2_0_0; } @@ -1548,6 +1686,10 @@ class TaskService extends EventEmitter implements ITaskService { private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().folders[0] }) : undefined; + private getConfiguration(workspaceFolder: WorkspaceFolder): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { + let result = this.contextService.hasWorkspace() + ? this.configurationService.getConfiguration('tasks', { resource: workspaceFolder.uri }) + : undefined; if (!result) { return { config: undefined, hasParseErrors: false }; } diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index 513e890116a..c16b90342fe 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -561,6 +561,7 @@ function _freeze(this: void, target: T, properties: MetaData[]): Read } interface ParseContext { + workspaceFolder: Tasks.WorkspaceFolder; problemReporter: IProblemReporter; namedProblemMatchers: IStringDictionary; uuidMap: UUIDMap; @@ -1160,6 +1161,7 @@ namespace ConfiguringTask { } let taskIdentifier = TaskIdentifier.from(identifier); let configElement: Tasks.TaskSourceConfigElement = { + workspaceFolder: context.workspaceFolder, file: '.vscode\\tasks.json', index, element: external @@ -1678,10 +1680,12 @@ class UUIDMap { class ConfigurationParser { + private workspaceFolder: Tasks.WorkspaceFolder; private problemReporter: IProblemReporter; private uuidMap: UUIDMap; - constructor(problemReporter: IProblemReporter, uuidMap: UUIDMap) { + constructor(workspaceFolder: Tasks.WorkspaceFolder, problemReporter: IProblemReporter, uuidMap: UUIDMap) { + this.workspaceFolder = workspaceFolder; this.problemReporter = problemReporter; this.uuidMap = uuidMap; } @@ -1693,6 +1697,7 @@ class ConfigurationParser { this.problemReporter.clearOutput(); } let context: ParseContext = { + workspaceFolder: this.workspaceFolder, problemReporter: this.problemReporter, uuidMap: this.uuidMap, namedProblemMatchers: undefined, @@ -1783,11 +1788,16 @@ class ConfigurationParser { } } -let uuidMap: UUIDMap = new UUIDMap(); -export function parse(configuration: ExternalTaskRunnerConfiguration, logger: IProblemReporter): ParseResult { +let uuidMaps: Map = new Map(); +export function parse(workspaceFolder: Tasks.WorkspaceFolder, configuration: ExternalTaskRunnerConfiguration, logger: IProblemReporter): ParseResult { + let uuidMap = uuidMaps.get(workspaceFolder.uri.toString()); + if (!uuidMap) { + uuidMap = new UUIDMap(); + uuidMaps.set(workspaceFolder.uri.toString(), uuidMap); + } try { uuidMap.start(); - return (new ConfigurationParser(logger, uuidMap)).run(configuration); + return (new ConfigurationParser(workspaceFolder, logger, uuidMap)).run(configuration); } finally { uuidMap.finish(); } @@ -1801,35 +1811,6 @@ export function getTaskIdentifier(value: TaskIdentifier): Tasks.TaskIdentifier { return TaskIdentifier.from(value); } -export function findTaskIndex(fileConfig: ExternalTaskRunnerConfiguration, task: Tasks.Task): number { - if (!fileConfig || !fileConfig.tasks) { - return undefined; - } - if (fileConfig.tasks.length === 0) { - return -1; - } - let localMap = new UUIDMap(uuidMap); - let context: ParseContext = { - problemReporter: this.problemReporter, - uuidMap: localMap, - namedProblemMatchers: undefined, - engine: ExecutionEngine.from(fileConfig), - schemaVersion: JsonSchemaVersion.from(fileConfig) - }; - try { - localMap.start(); - let tasks = TaskParser.quickParse(fileConfig.tasks, context); - for (let i = 0; i < tasks.length; i++) { - if (task._id === tasks[i]._id) { - return i; - } - } - return -1; - } finally { - localMap.finish(); - } -} - /* class VersionConverter { constructor(private problemReporter: IProblemReporter) { diff --git a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts index c89319b81dd..d045dc5c153 100644 --- a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts +++ b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts @@ -177,7 +177,7 @@ class CustomTaskBuilder { this.commandBuilder = new CommandConfigurationBuilder(this, command); this.result = { _id: name, - _source: { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace', config: { element: undefined, index: -1, file: '.vscode/tasks.json' } }, + _source: { kind: Tasks.TaskSourceKind.Workspace, label: 'workspace', config: { workspaceFolder: { uri: undefined }, element: undefined, index: -1, file: '.vscode/tasks.json' } }, _label: name, type: 'custom', identifier: name, @@ -347,7 +347,7 @@ class PatternBuilder { function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, resolved: number) { let reporter = new ProblemReporter(); - let result = parse(external, reporter); + let result = parse(external, { uri: undefined }, reporter); assert.ok(!reporter.receivedMessage); assert.strictEqual(result.custom.length, 1); let task = result.custom[0]; @@ -358,7 +358,7 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void { builder.done(); let reporter = new ProblemReporter(); - let result = parse(external, reporter); + let result = parse(external, { uri: undefined }, reporter); if (reporter.receivedMessage) { assert.ok(false, reporter.lastMessage); } From 9c6880cb327bd414fc37436b5f3ea7941e22b2bb Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Thu, 14 Sep 2017 11:31:05 +0200 Subject: [PATCH 113/145] Add workspace folders to task API --- src/vs/vscode.d.ts | 20 ++ src/vs/workbench/api/node/extHostTask.ts | 6 +- src/vs/workbench/api/node/extHostTypes.ts | 29 +- src/vs/workbench/parts/tasks/common/tasks.ts | 11 + .../electron-browser/task.contribution.ts | 269 ++++++++++-------- .../electron-browser/configuration.test.ts | 5 +- 6 files changed, 207 insertions(+), 133 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index ac6500b1860..2ddff64f2dd 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3887,11 +3887,31 @@ declare module 'vscode' { */ constructor(taskDefinition: TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + /** + * Creates a new task. + * + * @param definition The task definition as defined in the taskDefinitions extension point. + * @param workspaceFolder The workspace folder this task is created for. + * @param name The task's name. Is presented in the user interface. + * @param source The task's source (e.g. 'gulp', 'npm', ...). Is presented in the user interface. + * @param execution The process or shell execution. + * @param problemMatchers the names of problem matchers to use, like '$tsc' + * or '$eslint'. Problem matchers can be contributed by an extension using + * the `problemMatchers` extension point. + */ + constructor(taskDefinition: TaskDefinition, workspaceFolder: WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + /** * The task's definition. */ definition: TaskDefinition; + /** + * The workspace folder this task is associated with. Can be undefined if + * the task is not associated with any workspace folder. + */ + workspaceFolder?: WorkspaceFolder; + /** * The task's name */ diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index a174c82f1b7..34c441a635d 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import URI from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import * as Objects from 'vs/base/common/objects'; @@ -326,10 +327,11 @@ namespace Tasks { return undefined; } command.presentation = PresentationOptions.from(task.presentationOptions); - let source = { + let source: TaskSystem.ExtensionTaskSource = { kind: TaskSystem.TaskSourceKind.Extension, label: typeof task.source === 'string' ? task.source : extension.name, - extension: extension.id + extension: extension.id, + workspaceFolder: task.workspaceFolder ? { uri: task.workspaceFolder.uri as URI } : undefined }; let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); let key = (task as types.Task).definitionKey; diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index e1b60f1ba51..d198bae11a9 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1218,6 +1218,7 @@ export class Task implements vscode.Task { private _definition: vscode.TaskDefinition; private _definitionKey: string; + private _workspaceFolder: vscode.WorkspaceFolder; private _name: string; private _execution: ProcessExecution | ShellExecution; private _problemMatchers: string[]; @@ -1227,11 +1228,23 @@ export class Task implements vscode.Task { private _group: TaskGroup; private _presentationOptions: vscode.TaskPresentationOptions; - constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]) { + constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + constructor(definition: vscode.TaskDefinition, workspaceFolder: vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + constructor(definition: vscode.TaskDefinition, arg2: string | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) { this.definition = definition; - this.name = name; - this.source = source; - this.execution = execution; + let problemMatchers: string | string[]; + if (typeof arg2 === 'string') { + this.name = arg2; + this.source = arg3; + this.execution = arg4; + problemMatchers = arg5; + } else { + this.workspaceFolder = arg2; + this.name = arg3; + this.source = arg4; + this.execution = arg5; + problemMatchers = arg6; + } if (typeof problemMatchers === 'string') { this._problemMatchers = [problemMatchers]; this._hasDefinedMatchers = true; @@ -1266,6 +1279,14 @@ export class Task implements vscode.Task { return this._definitionKey; } + get workspaceFolder(): vscode.WorkspaceFolder { + return this._workspaceFolder; + } + + set workspaceFolder(value: vscode.WorkspaceFolder) { + this._workspaceFolder = value; + } + get name(): string { return this._name; } diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index fab0ff45015..c14c121b4b0 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -244,6 +244,7 @@ export interface ExtensionTaskSource { kind: 'extension'; label: string; extension: string; + workspaceFolder: WorkspaceFolder | undefined; } export interface CompositeTaskSource { @@ -417,6 +418,16 @@ export namespace Task { } } + export function getWorkspaceFolder(task: Task): WorkspaceFolder | undefined { + if (CustomTask.is(task)) { + return task._source.config.workspaceFolder; + } else if (ContributedTask.is(task)) { + return task._source.workspaceFolder; + } else { + return undefined; + } + } + export function getTelemetryKind(task: Task): string { if (ContributedTask.is(task)) { return 'extension'; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 35223caa5fc..891859d782a 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -667,7 +667,7 @@ class TaskService extends EventEmitter implements ITaskService { private _workspaceFolders: WorkspaceFolder[]; private _providers: Map; - private _workspaceTasksPromise: TPromise; + private _workspaceTasksPromise: TPromise>; private _taskSystem: ITaskSystem; private _taskSystemListeners: IDisposable[]; @@ -719,22 +719,14 @@ class TaskService extends EventEmitter implements ITaskService { if (!this._taskSystem && !this._workspaceTasksPromise) { return; } - this.updateWorkspaceTasks(); - if (!this._taskSystem) { - return; - } - let currentExecutionEngine = this._taskSystem instanceof TerminalTaskSystem - ? ExecutionEngine.Terminal - : this._taskSystem instanceof ProcessTaskSystem - ? ExecutionEngine.Process - : ExecutionEngine._default; - if (currentExecutionEngine !== this.getExecutionEngine()) { + let folderSetup = this.computeWorkspaceFolders(); + if (this._executionEngine !== folderSetup[1] && this._taskSystem && this._taskSystem.getActiveTasks().length > 0) { this.messageService.show( Severity.Info, { message: nls.localize( 'TaskSystem.noHotSwap', - 'Changing the task execution engine requires to reload the Window' + 'Changing the task execution engine with an active task running requires to reload the Window' ), actions: [ new ReloadWindowAction(ReloadWindowAction.ID, ReloadWindowAction.LABEL, this._windowServive), @@ -742,9 +734,17 @@ class TaskService extends EventEmitter implements ITaskService { ] } ); + return; } + this._workspaceFolders = folderSetup[0]; + this._executionEngine = folderSetup[1]; + this._schemaVersion = folderSetup[2]; + this.updateWorkspaceTasks(); }); - this.updateWorkspaceFolders(); + let folderSetup = this.computeWorkspaceFolders(); + this._workspaceFolders = folderSetup[0]; + this._executionEngine = folderSetup[1]; + this._schemaVersion = folderSetup[2]; lifecycleService.onWillShutdown(event => event.veto(this.beforeShutdown())); this.registerCommands(); } @@ -823,20 +823,14 @@ class TaskService extends EventEmitter implements ITaskService { } public getTask(identifier: string): TPromise { - return this.getTaskSets().then((sets) => { - let resolver = this.createResolver(sets); + return this.getAllTasks().then((tasks) => { + let resolver = this.createResolver(tasks); return resolver.resolve(identifier); }); } public tasks(): TPromise { - return this.getTaskSets().then((sets) => { - let result: Task[] = []; - for (let set of sets) { - result.push(...set.tasks); - } - return result; - }); + return this.getAllTasks(); }; public isActive(): TPromise { @@ -890,10 +884,10 @@ class TaskService extends EventEmitter implements ITaskService { } public build(): TPromise { - return this.getTaskSets().then((values) => { - let runnable = this.createRunnableTask(values, TaskGroup.Build); + return this.getAllTasks().then((tasks) => { + let runnable = this.createRunnableTask(tasks, TaskGroup.Build); if (!runnable || !runnable.task) { - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V0_1_0) { + if (this._schemaVersion === JsonSchemaVersion.V0_1_0) { throw new TaskError(Severity.Info, nls.localize('TaskService.noBuildTask1', 'No build task defined. Mark a task with \'isBuildCommand\' in the tasks.json file.'), TaskErrors.NoBuildTask); } else { throw new TaskError(Severity.Info, nls.localize('TaskService.noBuildTask2', 'No build task defined. Mark a task with as a \'build\' group in the tasks.json file.'), TaskErrors.NoBuildTask); @@ -915,10 +909,10 @@ class TaskService extends EventEmitter implements ITaskService { } public runTest(): TPromise { - return this.getTaskSets().then((values) => { - let runnable = this.createRunnableTask(values, TaskGroup.Test); + return this.getAllTasks().then((tasks) => { + let runnable = this.createRunnableTask(tasks, TaskGroup.Test); if (!runnable || !runnable.task) { - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V0_1_0) { + if (this._schemaVersion === JsonSchemaVersion.V0_1_0) { throw new TaskError(Severity.Info, nls.localize('TaskService.noTestTask1', 'No test task defined. Mark a task with \'isTestCommand\' in the tasks.json file.'), TaskErrors.NoTestTask); } else { throw new TaskError(Severity.Info, nls.localize('TaskService.noTestTask2', 'No test task defined. Mark a task with as a \'test\' group in the tasks.json file.'), TaskErrors.NoTestTask); @@ -932,8 +926,8 @@ class TaskService extends EventEmitter implements ITaskService { } public run(task: string | Task, options?: RunOptions): TPromise { - return this.getTaskSets().then((values) => { - let resolver = this.createResolver(values); + return this.getAllTasks().then((tasks) => { + let resolver = this.createResolver(tasks); let requested: string; let toExecute: Task; if (Types.isString(task)) { @@ -1042,13 +1036,11 @@ class TaskService extends EventEmitter implements ITaskService { } public getTasksForGroup(group: string): TPromise { - return this.getTaskSets().then((values) => { + return this.getAllTasks().then((tasks) => { let result: Task[] = []; - for (let value of values) { - for (let task of value.tasks) { - if (task.group === group) { - result.push(task); - } + for (let task of tasks) { + if (task.group === group) { + result.push(task); } } return result; @@ -1056,11 +1048,15 @@ class TaskService extends EventEmitter implements ITaskService { } public canCustomize(): boolean { - return this.getJsonSchemaVersion() === JsonSchemaVersion.V2_0_0; + return this._schemaVersion === JsonSchemaVersion.V2_0_0; } public customize(task: ContributedTask | CustomTask, properties?: CustomizationProperties, openConfig?: boolean): TPromise { - let configuration = this.getConfiguration(); + let workspaceFolder = Task.getWorkspaceFolder(task); + if (!workspaceFolder) { + return TPromise.as(undefined); + } + let configuration = this.getConfiguration(workspaceFolder); if (configuration.hasParseErrors) { this.messageService.show(Severity.Warning, nls.localize('customizeParseErrors', 'The current task configuration has errors. Please fix the errors first before customizing a task.')); return TPromise.as(undefined); @@ -1166,6 +1162,7 @@ class TaskService extends EventEmitter implements ITaskService { } public openConfig(task: CustomTask): TPromise { + // @ToDo need to adopt since this is not working anymore let resource = this.contextService.toResource(task._source.config.file); return this.editorService.openEditor({ resource: resource, @@ -1176,26 +1173,24 @@ class TaskService extends EventEmitter implements ITaskService { }, false).then(() => undefined); } - private createRunnableTask(sets: TaskSet[], group: TaskGroup): { task: Task; resolver: ITaskResolver } { + private createRunnableTask(tasks: Task[], group: TaskGroup): { task: Task; resolver: ITaskResolver } { let idMap: IStringDictionary = Object.create(null); let labelMap: IStringDictionary = Object.create(null); let identifierMap: IStringDictionary = Object.create(null); let workspaceTasks: Task[] = []; let extensionTasks: Task[] = []; - sets.forEach((set) => { - set.tasks.forEach((task) => { - idMap[task._id] = task; - labelMap[task._label] = task; - identifierMap[task.identifier] = task; - if (group && task.group === group) { - if (task._source.kind === TaskSourceKind.Workspace) { - workspaceTasks.push(task); - } else { - extensionTasks.push(task); - } + tasks.forEach((task) => { + idMap[task._id] = task; + labelMap[task._label] = task; + identifierMap[task.identifier] = task; + if (group && task.group === group) { + if (task._source.kind === TaskSourceKind.Workspace) { + workspaceTasks.push(task); + } else { + extensionTasks.push(task); } - }); + } }); let resolver: ITaskResolver = { resolve: (id: string) => { @@ -1231,15 +1226,13 @@ class TaskService extends EventEmitter implements ITaskService { } } - private createResolver(sets: TaskSet[]): ITaskResolver { + private createResolver(tasks: Task[]): ITaskResolver { let labelMap: IStringDictionary = Object.create(null); let identifierMap: IStringDictionary = Object.create(null); - sets.forEach((set) => { - set.tasks.forEach((task) => { - labelMap[task._label] = task; - identifierMap[task.identifier] = task; - }); + tasks.forEach((task) => { + labelMap[task._label] = task; + identifierMap[task.identifier] = task; }); return { resolve: (id: string) => { @@ -1308,8 +1301,7 @@ class TaskService extends EventEmitter implements ITaskService { if (this._taskSystem) { return this._taskSystem; } - let engine = this.getExecutionEngine(); - if (engine === ExecutionEngine.Terminal) { + if (this._executionEngine === ExecutionEngine.Terminal) { this._taskSystem = new TerminalTaskSystem( this.terminalService, this.outputService, this.markerService, this.modelService, this.configurationResolverService, this.telemetryService, @@ -1331,7 +1323,7 @@ class TaskService extends EventEmitter implements ITaskService { return this._taskSystem; } - private getTaskSets(): TPromise { + private getAllTasks(): TPromise { return this.extensionService.activateByEvent('onCommand:workbench.action.tasks.runTask').then(() => { return new TPromise((resolve, reject) => { let result: TaskSet[] = []; @@ -1349,7 +1341,7 @@ class TaskService extends EventEmitter implements ITaskService { resolve(result); } }; - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V2_0_0 && this._providers.size > 0) { + if (this._schemaVersion === JsonSchemaVersion.V2_0_0 && this._providers.size > 0) { this._providers.forEach((provider) => { counter++; provider.provideTasks().done(done, error); @@ -1358,57 +1350,83 @@ class TaskService extends EventEmitter implements ITaskService { resolve(result); } }); - }).then((result) => { - return this.getWorkspaceTasks().then((workspaceTaskResult) => { - let workspaceTasksToDelete: Task[] = []; - let configurations = workspaceTaskResult.configurations; - let legacyTaskConfigurations = workspaceTaskResult.set ? this.getLegacyTaskConfigurations(workspaceTaskResult.set) : undefined; - if (configurations || legacyTaskConfigurations) { - for (let set of result) { - for (let i = 0; i < set.tasks.length; i++) { - let task = set.tasks[i]; - if (!ContributedTask.is(task)) { - continue; - } - if (configurations) { - let configuringTask = configurations.byIdentifier[task.defines._key]; - if (configuringTask) { - set.tasks[i] = TaskConfig.createCustomTask(task, configuringTask); + }).then((contributedTaskSets) => { + let result: Task[] = []; + let contributedTasks: Map = new Map(); + for (let set of contributedTaskSets) { + for (let task of set.tasks) { + if (!ContributedTask.is(task)) { + continue; + } + let workspaceFolder = task._source.workspaceFolder; + if (workspaceFolder) { + let values = contributedTasks.get(workspaceFolder.uri.toString()); + if (!values) { + values = [task]; + contributedTasks.set(workspaceFolder.uri.toString(), values); + } else { + values.push(task); + } + } else { + result.push(task); + } + } + } + return this.getWorkspaceTasks().then((customTasks) => { + customTasks.forEach((folderTasks, key) => { + let contributed = contributedTasks.get(key); + if (!contributed) { + result.push(...folderTasks.set.tasks); + } else { + let configurations = folderTasks.configurations; + let legacyTaskConfigurations = folderTasks.set ? this.getLegacyTaskConfigurations(folderTasks.set) : undefined; + let customTasksToDelete: Task[] = []; + if (configurations || legacyTaskConfigurations) { + for (let task of contributed) { + if (!ContributedTask.is(task)) { continue; } - } - if (legacyTaskConfigurations) { - let configuringTask = legacyTaskConfigurations[task.defines._key]; - if (configuringTask) { - set.tasks[i] = TaskConfig.createCustomTask(task, configuringTask); - workspaceTasksToDelete.push(configuringTask); - set.tasks[i] = configuringTask; - continue; + if (configurations) { + let configuringTask = configurations.byIdentifier[task.defines._key]; + if (configuringTask) { + result.push(TaskConfig.createCustomTask(task, configuringTask)); + continue; + } + } else if (legacyTaskConfigurations) { + let configuringTask = legacyTaskConfigurations[task.defines._key]; + if (configuringTask) { + result.push(TaskConfig.createCustomTask(task, configuringTask)); + customTasksToDelete.push(configuringTask); + continue; + } + } else { + result.push(task); } } } + if (customTasksToDelete.length > 0) { + let toDelete = customTasksToDelete.reduce>((map, task) => { + map[task._id] = true; + return map; + }, Object.create(null)); + for (let task of folderTasks.set.tasks) { + if (toDelete[task._id]) { + continue; + } + result.push(task); + } + } else { + result.push(...folderTasks.set.tasks); + } } - } - if (workspaceTaskResult.set) { - if (workspaceTasksToDelete.length > 0) { - let tasks = workspaceTaskResult.set.tasks; - let newSet: TaskSet = { - extension: workspaceTaskResult.set.extension, - tasks: [] - }; - let toDelete = workspaceTasksToDelete.reduce>((map, task) => { - map[task._id] = true; - return map; - }, Object.create(null)); - newSet.tasks = tasks.filter(task => !toDelete[task._id]); - result.push(newSet); - } else { - result.push(workspaceTaskResult.set); - } - } + }); return result; }, () => { // If we can't read the tasks.json file provide at least the contributed tasks + let result: Task[] = []; + for (let set of contributedTaskSets) { + result.push(...set.tasks); + } return result; }); }); @@ -1440,7 +1458,7 @@ class TaskService extends EventEmitter implements ITaskService { return result; } - private getWorkspaceTasks(): TPromise { + private getWorkspaceTasks(): TPromise> { if (this._workspaceTasksPromise) { return this._workspaceTasksPromise; } @@ -1450,9 +1468,12 @@ class TaskService extends EventEmitter implements ITaskService { private updateWorkspaceTasks(): void { this._workspaceTasksPromise = this.computeWorkspaceTasks().then(value => { - this._configHasErrors = value.hasErrors; - if (this._taskSystem instanceof ProcessTaskSystem) { - this._taskSystem.hasErrors(this._configHasErrors); + if (this._executionEngine === ExecutionEngine.Process && this._taskSystem instanceof ProcessTaskSystem) { + // We can only have a process engine if we have one folder. + value.forEach((value) => { + this._configHasErrors = value.hasErrors; + (this._taskSystem as ProcessTaskSystem).hasErrors(this._configHasErrors); + }); } return value; }); @@ -1640,20 +1661,21 @@ class TaskService extends EventEmitter implements ITaskService { } } - private updateWorkspaceFolders(): void { + private computeWorkspaceFolders(): [WorkspaceFolder[], ExecutionEngine, JsonSchemaVersion] { + let workspaceFolders: WorkspaceFolder[] = []; + let executionEngine = ExecutionEngine.Terminal; + let schemaVersion = JsonSchemaVersion.V2_0_0; + if (this.contextService.hasFolderWorkspace()) { - let workspaceFolder = { uri: this.contextService.getWorkspace().roots[0] }; - this._workspaceFolders = [workspaceFolder]; - this._executionEngine = this.computeExecutionEngine(workspaceFolder); - this._schemaVersion = this.computeJsonSchemaVersion(workspaceFolder); + let workspaceFolder: WorkspaceFolder = { uri: this.contextService.getWorkspace().roots[0] }; + workspaceFolders.push(workspaceFolder); + executionEngine = this.computeExecutionEngine(workspaceFolder); + schemaVersion = this.computeJsonSchemaVersion(workspaceFolder); } else if (this.contextService.hasMultiFolderWorkspace()) { - this._executionEngine = ExecutionEngine.Terminal; - this._schemaVersion = JsonSchemaVersion.V2_0_0; - this._workspaceFolders = []; for (let folder of this.contextService.getWorkspace().roots) { let workspaceFolder = { uri: folder }; if (this._schemaVersion === this.computeJsonSchemaVersion(workspaceFolder)) { - this._workspaceFolders.push(workspaceFolder); + workspaceFolders.push(workspaceFolder); } else { this._outputChannel.append(nls.localize( 'taskService.ignoreingFolder', @@ -1661,11 +1683,8 @@ class TaskService extends EventEmitter implements ITaskService { folder.fsPath)); } } - } else { - this._workspaceFolders = []; - this._executionEngine = ExecutionEngine.Terminal; - this._schemaVersion = JsonSchemaVersion.V2_0_0; } + return [workspaceFolders, executionEngine, schemaVersion]; } private computeExecutionEngine(workspaceFolder: WorkspaceFolder): ExecutionEngine { @@ -1727,7 +1746,7 @@ class TaskService extends EventEmitter implements ITaskService { if (this._taskSystem) { return this._taskSystem instanceof TerminalTaskSystem; } - return this.getExecutionEngine() === ExecutionEngine.Terminal; + return this._executionEngine === ExecutionEngine.Terminal; } private hasDetectorSupport(config: TaskConfig.ExternalTaskRunnerConfiguration): boolean { @@ -1939,7 +1958,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!this.canRunCommand()) { return; } - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V0_1_0) { + if (this._schemaVersion === JsonSchemaVersion.V0_1_0) { this.build(); return; } @@ -1982,7 +2001,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!this.canRunCommand()) { return; } - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V0_1_0) { + if (this._schemaVersion === JsonSchemaVersion.V0_1_0) { this.runTest(); return; } @@ -2088,7 +2107,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!this.canRunCommand()) { return; } - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V2_0_0) { + if (this._schemaVersion === JsonSchemaVersion.V2_0_0) { this.tasks().then((tasks => { if (tasks.length === 0) { this.configureBuildTask().run(); @@ -2123,7 +2142,7 @@ class TaskService extends EventEmitter implements ITaskService { if (!this.canRunCommand()) { return; } - if (this.getJsonSchemaVersion() === JsonSchemaVersion.V2_0_0) { + if (this._schemaVersion === JsonSchemaVersion.V2_0_0) { this.tasks().then((tasks => { if (tasks.length === 0) { this.configureAction().run(); diff --git a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts index d045dc5c153..c9601239fb1 100644 --- a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts +++ b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import URI from 'vs/base/common/uri'; import * as assert from 'assert'; import Severity from 'vs/base/common/severity'; import * as UUID from 'vs/base/common/uuid'; @@ -347,7 +348,7 @@ class PatternBuilder { function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, resolved: number) { let reporter = new ProblemReporter(); - let result = parse(external, { uri: undefined }, reporter); + let result = parse({ uri: URI.file('/Workspace/folderOne') }, external, reporter); assert.ok(!reporter.receivedMessage); assert.strictEqual(result.custom.length, 1); let task = result.custom[0]; @@ -358,7 +359,7 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void { builder.done(); let reporter = new ProblemReporter(); - let result = parse(external, { uri: undefined }, reporter); + let result = parse({ uri: URI.file('/Workspace/folderOne') }, external, reporter); if (reporter.receivedMessage) { assert.ok(false, reporter.lastMessage); } From cc5cc9a2d6ee534b0f1bc475e41b2ed208e5e576 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 15 Sep 2017 11:03:57 +0200 Subject: [PATCH 114/145] Adopt task multi folder API --- src/vs/vscode.d.ts | 27 ++- src/vs/workbench/api/node/extHost.api.impl.ts | 3 +- src/vs/workbench/api/node/extHostTask.ts | 32 +++- src/vs/workbench/api/node/extHostTypes.ts | 27 ++- .../parts/tasks/browser/quickOpen.ts | 13 +- .../parts/tasks/browser/taskQuickOpen.ts | 11 +- .../parts/tasks/common/taskService.ts | 3 +- src/vs/workbench/parts/tasks/common/tasks.ts | 27 +-- .../electron-browser/task.contribution.ts | 161 ++++++------------ .../parts/tasks/node/taskConfiguration.ts | 4 +- 10 files changed, 159 insertions(+), 149 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 2ddff64f2dd..92310b76a73 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3869,6 +3869,21 @@ declare module 'vscode' { options?: ShellExecutionOptions; } + /** + * The scope of a task. + */ + export enum TaskScope { + /** + * The task is a global task + */ + Global = 1, + + /** + * The task is a workspace task + */ + Workspace = 2 + } + /** * A task to execute */ @@ -3877,8 +3892,10 @@ declare module 'vscode' { /** * Creates a new task. * + * @deprecated: Use the new constructors that allow specifying a target for the task. + * * @param definition The task definition as defined in the taskDefinitions extension point. - * @param name The task's name. Is presented in the user interface. + * @param scope The task's name. Is presented in the user interface. * @param source The task's source (e.g. 'gulp', 'npm', ...). Is presented in the user interface. * @param execution The process or shell execution. * @param problemMatchers the names of problem matchers to use, like '$tsc' @@ -3891,6 +3908,7 @@ declare module 'vscode' { * Creates a new task. * * @param definition The task definition as defined in the taskDefinitions extension point. + * @param scope Specifies the task's scope. It is either a global or a workspace task or a task for a specific workspace folder. * @param workspaceFolder The workspace folder this task is created for. * @param name The task's name. Is presented in the user interface. * @param source The task's source (e.g. 'gulp', 'npm', ...). Is presented in the user interface. @@ -3899,7 +3917,7 @@ declare module 'vscode' { * or '$eslint'. Problem matchers can be contributed by an extension using * the `problemMatchers` extension point. */ - constructor(taskDefinition: TaskDefinition, workspaceFolder: WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + constructor(taskDefinition: TaskDefinition, target: TaskScope.Global | TaskScope.Workspace | WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); /** * The task's definition. @@ -3907,10 +3925,9 @@ declare module 'vscode' { definition: TaskDefinition; /** - * The workspace folder this task is associated with. Can be undefined if - * the task is not associated with any workspace folder. + * The task's scope. */ - workspaceFolder?: WorkspaceFolder; + scope?: TaskScope.Global | TaskScope.Workspace | WorkspaceFolder; /** * The task's name diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index b1829b9387f..4c9ed5a511f 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -97,7 +97,7 @@ export function createApiFactory( const extHostQuickOpen = threadService.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(threadService)); const extHostTerminalService = threadService.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(threadService)); const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands)); - const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService)); + const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService, extHostWorkspace)); const extHostCredentials = threadService.set(ExtHostContext.ExtHostCredentials, new ExtHostCredentials(threadService)); const extHostWindow = threadService.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(threadService)); threadService.set(ExtHostContext.ExtHostExtensionService, extensionService); @@ -599,6 +599,7 @@ export function createApiFactory( TaskGroup: extHostTypes.TaskGroup, ProcessExecution: extHostTypes.ProcessExecution, ShellExecution: extHostTypes.ShellExecution, + TaskScope: extHostTypes.TaskScope, Task: extHostTypes.Task, ConfigurationTarget: extHostTypes.ConfigurationTarget }; diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 34c441a635d..b644dfb2424 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -16,6 +16,7 @@ import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks'; import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol'; import * as types from 'vs/workbench/api/node/extHostTypes'; +import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import * as vscode from 'vscode'; interface StringMap { @@ -296,13 +297,13 @@ namespace ShellConfiguration { namespace Tasks { - export function from(tasks: vscode.Task[], extension: IExtensionDescription): TaskSystem.Task[] { + export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.Task[] { if (tasks === void 0 || tasks === null) { return []; } let result: TaskSystem.Task[] = []; for (let task of tasks) { - let converted = fromSingle(task, extension); + let converted = fromSingle(task, rootFolder, extension); if (converted) { result.push(converted); } @@ -310,7 +311,7 @@ namespace Tasks { return result; } - function fromSingle(task: vscode.Task, extension: IExtensionDescription): TaskSystem.ContributedTask { + function fromSingle(task: vscode.Task, rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask { if (typeof task.name !== 'string') { return undefined; } @@ -327,11 +328,27 @@ namespace Tasks { return undefined; } command.presentation = PresentationOptions.from(task.presentationOptions); + + let taskScope: types.TaskScope.Global | types.TaskScope.Workspace | vscode.WorkspaceFolder | undefined = task.scope; + let workspaceFolder: vscode.WorkspaceFolder | undefined; + let scope: TaskSystem.TaskScope; + // For backwards compatibility + if (taskScope === void 0) { + scope = TaskSystem.TaskScope.Folder; + workspaceFolder = rootFolder; + } else if (taskScope === types.TaskScope.Global) { + scope = TaskSystem.TaskScope.Global; + } else if (taskScope === types.TaskScope.Workspace) { + scope = TaskSystem.TaskScope.Workspace; + } else { + workspaceFolder = taskScope; + } let source: TaskSystem.ExtensionTaskSource = { kind: TaskSystem.TaskSourceKind.Extension, label: typeof task.source === 'string' ? task.source : extension.name, extension: extension.id, - workspaceFolder: task.workspaceFolder ? { uri: task.workspaceFolder.uri as URI } : undefined + scope: scope, + workspaceFolder: workspaceFolder ? { uri: workspaceFolder.uri as URI } : undefined }; let label = nls.localize('task.label', '{0}: {1}', source.label, task.name); let key = (task as types.Task).definitionKey; @@ -400,11 +417,13 @@ interface HandlerData { export class ExtHostTask implements ExtHostTaskShape { private _proxy: MainThreadTaskShape; + private _extHostWorkspace: ExtHostWorkspace; private _handleCounter: number; private _handlers: Map; - constructor(mainContext: IMainContext) { + constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) { this._proxy = mainContext.get(MainContext.MainThreadTask); + this._extHostWorkspace = extHostWorkspace; this._handleCounter = 0; this._handlers = new Map(); }; @@ -428,8 +447,9 @@ export class ExtHostTask implements ExtHostTaskShape { return TPromise.wrapError(new Error('no handler found')); } return asWinJsPromise(token => handler.provider.provideTasks(token)).then(value => { + let workspaceFolders = this._extHostWorkspace.getWorkspaceFolders(); return { - tasks: Tasks.from(value, handler.extension), + tasks: Tasks.from(value, workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0] : undefined, handler.extension), extension: handler.extension }; }); diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index d198bae11a9..a9b213648b8 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1214,11 +1214,16 @@ export class ShellExecution implements vscode.ShellExecution { } } +export enum TaskScope { + Global = 1, + Workspace = 2 +} + export class Task implements vscode.Task { private _definition: vscode.TaskDefinition; private _definitionKey: string; - private _workspaceFolder: vscode.WorkspaceFolder; + private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder; private _name: string; private _execution: ProcessExecution | ShellExecution; private _problemMatchers: string[]; @@ -1229,8 +1234,8 @@ export class Task implements vscode.Task { private _presentationOptions: vscode.TaskPresentationOptions; constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); - constructor(definition: vscode.TaskDefinition, workspaceFolder: vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); - constructor(definition: vscode.TaskDefinition, arg2: string | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) { + constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + constructor(definition: vscode.TaskDefinition, arg2: string | (vscode.TaskScope.Global | vscode.TaskScope.Workspace) | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) { this.definition = definition; let problemMatchers: string | string[]; if (typeof arg2 === 'string') { @@ -1238,8 +1243,14 @@ export class Task implements vscode.Task { this.source = arg3; this.execution = arg4; problemMatchers = arg5; + } else if (arg2 === TaskScope.Global || arg2 === TaskScope.Workspace) { + this.target = arg2; + this.name = arg3; + this.source = arg4; + this.execution = arg5; + problemMatchers = arg6; } else { - this.workspaceFolder = arg2; + this.target = arg2; this.name = arg3; this.source = arg4; this.execution = arg5; @@ -1279,12 +1290,12 @@ export class Task implements vscode.Task { return this._definitionKey; } - get workspaceFolder(): vscode.WorkspaceFolder { - return this._workspaceFolder; + get scope(): vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder { + return this._scope; } - set workspaceFolder(value: vscode.WorkspaceFolder) { - this._workspaceFolder = value; + set target(value: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder) { + this._scope = value; } get name(): string { diff --git a/src/vs/workbench/parts/tasks/browser/quickOpen.ts b/src/vs/workbench/parts/tasks/browser/quickOpen.ts index 2f64e812655..32a4d495b83 100644 --- a/src/vs/workbench/parts/tasks/browser/quickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/quickOpen.ts @@ -21,7 +21,7 @@ import { ActionBarContributor, ContributableActionProvider } from 'vs/workbench/ export class TaskEntry extends Model.QuickOpenEntry { - constructor(protected taskService: ITaskService, protected quickOpenService: IQuickOpenService, protected _task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { + constructor(protected quickOpenService: IQuickOpenService, protected taskService: ITaskService, protected _task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { super(highlights); } @@ -29,6 +29,17 @@ export class TaskEntry extends Model.QuickOpenEntry { return this.task._label; } + public getDescription(): string { + if (!this.taskService.hasMultipleFolders()) { + return null; + } + let workspaceFolder = Task.getWorkspaceFolder(this.task); + if (!workspaceFolder) { + return null; + } + return workspaceFolder.uri.fsPath; + } + public getAriaLabel(): string { return nls.localize('entryAriaLabel', "{0}, tasks", this.getLabel()); } diff --git a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts index 46d3c023200..b7325389b2b 100644 --- a/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts +++ b/src/vs/workbench/parts/tasks/browser/taskQuickOpen.ts @@ -14,12 +14,11 @@ import { CustomTask, ContributedTask } from 'vs/workbench/parts/tasks/common/tas import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService'; import { IExtensionService } from 'vs/platform/extensions/common/extensions'; - import * as base from './quickOpen'; class TaskEntry extends base.TaskEntry { - constructor(taskService: ITaskService, quickOpenService: IQuickOpenService, task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { - super(taskService, quickOpenService, task, highlights); + constructor(quickOpenService: IQuickOpenService, taskService: ITaskService, task: CustomTask | ContributedTask, highlights: Model.IHighlight[] = []) { + super(quickOpenService, taskService, task, highlights); } public run(mode: QuickOpen.Mode, context: Model.IContext): boolean { @@ -36,8 +35,8 @@ export class QuickOpenHandler extends base.QuickOpenHandler { constructor( @IQuickOpenService quickOpenService: IQuickOpenService, - @ITaskService taskService: ITaskService, - @IExtensionService extensionService: IExtensionService + @IExtensionService extensionService: IExtensionService, + @ITaskService taskService: ITaskService ) { super(quickOpenService, taskService); this.activationPromise = extensionService.activateByEvent('onCommand:workbench.action.tasks.runTask'); @@ -54,7 +53,7 @@ export class QuickOpenHandler extends base.QuickOpenHandler { } protected createEntry(task: CustomTask | ContributedTask, highlights: Model.IHighlight[]): base.TaskEntry { - return new TaskEntry(this.taskService, this.quickOpenService, task, highlights); + return new TaskEntry(this.quickOpenService, this.taskService, task, highlights); } public getEmptyLabel(searchString: string): string { diff --git a/src/vs/workbench/parts/tasks/common/taskService.ts b/src/vs/workbench/parts/tasks/common/taskService.ts index 7598b170398..d56ad59ce58 100644 --- a/src/vs/workbench/parts/tasks/common/taskService.ts +++ b/src/vs/workbench/parts/tasks/common/taskService.ts @@ -59,7 +59,8 @@ export interface ITaskService extends IEventEmitter { getTasksForGroup(group: string): TPromise; getRecentlyUsedTasks(): LinkedMap; - canCustomize(): boolean; + hasMultipleFolders(); + canCustomize(task: ContributedTask | CustomTask): boolean; customize(task: ContributedTask | CustomTask, properties?: {}, openConfig?: boolean): TPromise; openConfig(task: CustomTask): TPromise; diff --git a/src/vs/workbench/parts/tasks/common/tasks.ts b/src/vs/workbench/parts/tasks/common/tasks.ts index c14c121b4b0..9c15a51436b 100644 --- a/src/vs/workbench/parts/tasks/common/tasks.ts +++ b/src/vs/workbench/parts/tasks/common/tasks.ts @@ -216,6 +216,12 @@ export namespace TaskGroup { export type TaskGroup = 'clean' | 'build' | 'rebuild' | 'test'; +export enum TaskScope { + Global = 1, + Workspace = 2, + Folder = 3 +} + export namespace TaskSourceKind { export const Workspace: 'workspace' = 'workspace'; export const Extension: 'extension' = 'extension'; @@ -234,22 +240,23 @@ export interface TaskSourceConfigElement { } export interface WorkspaceTaskSource { - kind: 'workspace'; - label: string; - config: TaskSourceConfigElement; - customizes?: TaskIdentifier; + readonly kind: 'workspace'; + readonly label: string; + readonly config: TaskSourceConfigElement; + readonly customizes?: TaskIdentifier; } export interface ExtensionTaskSource { - kind: 'extension'; - label: string; - extension: string; - workspaceFolder: WorkspaceFolder | undefined; + readonly kind: 'extension'; + readonly label: string; + readonly extension: string; + readonly scope: TaskScope; + readonly workspaceFolder: WorkspaceFolder | undefined; } export interface CompositeTaskSource { - kind: 'composite'; - label: string; + readonly kind: 'composite'; + readonly label: string; } export type TaskSource = WorkspaceTaskSource | ExtensionTaskSource | CompositeTaskSource; diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index 891859d782a..b66c93ce362 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -958,7 +958,7 @@ class TaskService extends EventEmitter implements ITaskService { } private shouldAttachProblemMatcher(task: Task): boolean { - if (!this.canCustomize()) { + if (!this.canCustomize(task)) { return false; } if (task.group !== void 0 && task.group !== TaskGroup.Build) { @@ -1047,8 +1047,21 @@ class TaskService extends EventEmitter implements ITaskService { }); } - public canCustomize(): boolean { - return this._schemaVersion === JsonSchemaVersion.V2_0_0; + public hasMultipleFolders(): boolean { + return this._workspaceFolders && this._workspaceFolders.length > 1; + } + + public canCustomize(task: Task): boolean { + if (this._schemaVersion !== JsonSchemaVersion.V2_0_0) { + return false; + } + if (CustomTask.is(task)) { + return true; + } + if (ContributedTask.is(task)) { + return !!Task.getWorkspaceFolder(task); + } + return false; } public customize(task: ContributedTask | CustomTask, properties?: CustomizationProperties, openConfig?: boolean): TPromise { @@ -1119,12 +1132,12 @@ class TaskService extends EventEmitter implements ITaskService { fileConfig.problemMatcher = properties.problemMatcher; value.key = 'tasks.problemMatchers'; value.value = fileConfig.problemMatcher; - promise = this.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, value); + promise = this.writeConfiguration(workspaceFolder, value); } else if (properties.group !== void 0) { fileConfig.group = properties.group; value.key = 'tasks.group'; value.value = fileConfig.group; - promise = this.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, value); + promise = this.writeConfiguration(workspaceFolder, value); } } else { if (!Array.isArray(fileConfig.tasks)) { @@ -1137,7 +1150,7 @@ class TaskService extends EventEmitter implements ITaskService { } else { fileConfig.tasks[index] = toCustomize; } - promise = this.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, value); + promise = this.writeConfiguration(workspaceFolder, value); } }; if (!promise) { @@ -1161,6 +1174,16 @@ class TaskService extends EventEmitter implements ITaskService { }); } + private writeConfiguration(workspaceFolder: WorkspaceFolder, value: IConfigurationValue): TPromise { + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + return this.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, value); + } else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + return this.configurationEditingService.writeConfiguration(ConfigurationTarget.FOLDER, value, { scopes: { resource: workspaceFolder.uri } }); + } else { + return undefined; + } + } + public openConfig(task: CustomTask): TPromise { // @ToDo need to adopt since this is not working anymore let resource = this.contextService.toResource(task._source.config.file); @@ -1390,33 +1413,38 @@ class TaskService extends EventEmitter implements ITaskService { let configuringTask = configurations.byIdentifier[task.defines._key]; if (configuringTask) { result.push(TaskConfig.createCustomTask(task, configuringTask)); - continue; + } else { + result.push(task); } } else if (legacyTaskConfigurations) { let configuringTask = legacyTaskConfigurations[task.defines._key]; if (configuringTask) { result.push(TaskConfig.createCustomTask(task, configuringTask)); customTasksToDelete.push(configuringTask); - continue; + } else { + result.push(task); } } else { result.push(task); } } - } - if (customTasksToDelete.length > 0) { - let toDelete = customTasksToDelete.reduce>((map, task) => { - map[task._id] = true; - return map; - }, Object.create(null)); - for (let task of folderTasks.set.tasks) { - if (toDelete[task._id]) { - continue; + if (customTasksToDelete.length > 0) { + let toDelete = customTasksToDelete.reduce>((map, task) => { + map[task._id] = true; + return map; + }, Object.create(null)); + for (let task of folderTasks.set.tasks) { + if (toDelete[task._id]) { + continue; + } + result.push(task); } - result.push(task); + } else { + result.push(...folderTasks.set.tasks); } } else { result.push(...folderTasks.set.tasks); + result.push(...contributed); } } }); @@ -1479,89 +1507,6 @@ class TaskService extends EventEmitter implements ITaskService { }); } - /* - private computeWorkspaceTasks2(): TPromise { - let configPromise: TPromise; - { - let { config, hasParseErrors } = this.getConfiguration(); - if (hasParseErrors) { - return TPromise.as({ set: undefined, hasErrors: true, configurations: undefined }); - } - let engine = ExecutionEngine._default; - if (config) { - engine = TaskConfig.ExecutionEngine.from(config); - if (engine === ExecutionEngine.Process) { - if (this.hasDetectorSupport(config)) { - configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService, config).detect(true).then((value): WorkspaceFolderConfigurationResult => { - let hasErrors = this.printStderr(value.stderr); - let detectedConfig = value.config; - if (!detectedConfig) { - return { config, hasErrors }; - } - let result: TaskConfig.ExternalTaskRunnerConfiguration = Objects.clone(config); - let configuredTasks: IStringDictionary = Object.create(null); - if (!result.tasks) { - if (detectedConfig.tasks) { - result.tasks = detectedConfig.tasks; - } - } else { - result.tasks.forEach(task => configuredTasks[task.taskName] = task); - detectedConfig.tasks.forEach((task) => { - if (!configuredTasks[task.taskName]) { - result.tasks.push(task); - } - }); - } - return { config: result, hasErrors }; - }); - } else { - configPromise = TPromise.as({ config, hasErrors: false }); - } - } else { - configPromise = TPromise.as({ config, hasErrors: false }); - } - } else { - if (engine === ExecutionEngine.Terminal) { - configPromise = TPromise.as({ config, hasErrors: false }); - } else { - configPromise = new ProcessRunnerDetector(this.fileService, this.contextService, this.configurationResolverService).detect(true).then((value) => { - let hasErrors = this.printStderr(value.stderr); - return { config: value.config, hasErrors }; - }); - } - } - } - return configPromise.then((resolved) => { - return ProblemMatcherRegistry.onReady().then((): WorkspaceTaskResult => { - if (!resolved || !resolved.config) { - return { set: undefined, configurations: undefined, hasErrors: resolved !== void 0 ? resolved.hasErrors : false }; - } - let problemReporter = new ProblemReporter(this._outputChannel); - let parseResult = TaskConfig.parse(resolved.config, problemReporter); - let hasErrors = false; - if (!parseResult.validationStatus.isOK()) { - hasErrors = true; - this.showOutput(); - } - if (problemReporter.status.isFatal()) { - problemReporter.fatal(nls.localize('TaskSystem.configurationErrors', 'Error: the provided task configuration has validation errors and can\'t not be used. Please correct the errors first.')); - return { set: undefined, configurations: undefined, hasErrors }; - } - let customizedTasks: { byIdentifier: IStringDictionary; }; - if (parseResult.configured && parseResult.configured.length > 0) { - customizedTasks = { - byIdentifier: Object.create(null) - }; - for (let task of parseResult.configured) { - customizedTasks.byIdentifier[task.configures._key] = task; - } - } - return { set: { tasks: parseResult.custom }, configurations: customizedTasks, hasErrors }; - }); - }); - } - */ - private computeWorkspaceTasks(): TPromise> { if (this._workspaceFolders.length === 0) { return TPromise.as(new Map()); @@ -1666,15 +1611,15 @@ class TaskService extends EventEmitter implements ITaskService { let executionEngine = ExecutionEngine.Terminal; let schemaVersion = JsonSchemaVersion.V2_0_0; - if (this.contextService.hasFolderWorkspace()) { - let workspaceFolder: WorkspaceFolder = { uri: this.contextService.getWorkspace().roots[0] }; + if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { + let workspaceFolder: WorkspaceFolder = { uri: this.contextService.getWorkspace().folders[0] }; workspaceFolders.push(workspaceFolder); executionEngine = this.computeExecutionEngine(workspaceFolder); schemaVersion = this.computeJsonSchemaVersion(workspaceFolder); - } else if (this.contextService.hasMultiFolderWorkspace()) { - for (let folder of this.contextService.getWorkspace().roots) { + } else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) { + for (let folder of this.contextService.getWorkspace().folders) { let workspaceFolder = { uri: folder }; - if (this._schemaVersion === this.computeJsonSchemaVersion(workspaceFolder)) { + if (schemaVersion === this.computeJsonSchemaVersion(workspaceFolder)) { workspaceFolders.push(workspaceFolder); } else { this._outputChannel.append(nls.localize( @@ -1703,10 +1648,8 @@ class TaskService extends EventEmitter implements ITaskService { return TaskConfig.JsonSchemaVersion.from(config); } - private getConfiguration(): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: this.contextService.getWorkspace().folders[0] }) : undefined; private getConfiguration(workspaceFolder: WorkspaceFolder): { config: TaskConfig.ExternalTaskRunnerConfiguration; hasParseErrors: boolean } { - let result = this.contextService.hasWorkspace() + let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY ? this.configurationService.getConfiguration('tasks', { resource: workspaceFolder.uri }) : undefined; if (!result) { diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index c16b90342fe..9bd43c3080f 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -1222,7 +1222,7 @@ namespace CustomTask { let result: Tasks.CustomTask = { type: 'custom', _id: context.uuidMap.getUUID(taskName), - _source: Objects.assign({}, source, { config: { index, element: external, file: '.vscode\\tasks.json' } }), + _source: Objects.assign({}, source, { config: { index, element: external, file: '.vscode\\tasks.json', workspaceFolder: context.workspaceFolder } }), _label: taskName, name: taskName, identifier: taskName, @@ -1756,7 +1756,7 @@ class ConfigurationParser { let isBackground = fileConfig.isBackground ? !!fileConfig.isBackground : fileConfig.isWatching ? !!fileConfig.isWatching : undefined; let task: Tasks.CustomTask = { _id: context.uuidMap.getUUID(globals.command.name), - _source: Objects.assign({}, source, { config: { index: -1, element: fileConfig } }), + _source: Objects.assign({}, source, { config: { index: -1, element: fileConfig, workspaceFolder: context.workspaceFolder } }), _label: globals.command.name, type: 'custom', name: globals.command.name, From 46189edc740610bdef2828a60c98247611c8a9ae Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 15 Sep 2017 11:19:51 +0200 Subject: [PATCH 115/145] :lipstick: --- .../api/node/extHostFileSystemEventService.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/api/node/extHostFileSystemEventService.ts b/src/vs/workbench/api/node/extHostFileSystemEventService.ts index 3ffcf452a3a..6038446ffc4 100644 --- a/src/vs/workbench/api/node/extHostFileSystemEventService.ts +++ b/src/vs/workbench/api/node/extHostFileSystemEventService.ts @@ -6,7 +6,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { Disposable } from './extHostTypes'; -import { parse, ParsedPattern } from 'vs/base/common/glob'; +import { parse } from 'vs/base/common/glob'; import { Uri, FileSystemWatcher as _FileSystemWatcher } from 'vscode'; import { FileSystemEvents, ExtHostFileSystemEventServiceShape } from './extHost.protocol'; @@ -17,7 +17,6 @@ class FileSystemWatcher implements _FileSystemWatcher { private _onDidDelete = new Emitter(); private _disposable: Disposable; private _config: number; - private _parsedPattern: ParsedPattern; get ignoreCreateEvents(): boolean { return Boolean(this._config & 0b001); @@ -44,26 +43,26 @@ class FileSystemWatcher implements _FileSystemWatcher { this._config += 0b100; } - this._parsedPattern = parse(globPattern); + const parsedPattern = parse(globPattern); let subscription = dispatcher(events => { if (!ignoreCreateEvents) { for (let created of events.created) { - if (this._parsedPattern(created.fsPath)) { + if (parsedPattern(created.fsPath)) { this._onDidCreate.fire(created); } } } if (!ignoreChangeEvents) { for (let changed of events.changed) { - if (this._parsedPattern(changed.fsPath)) { + if (parsedPattern(changed.fsPath)) { this._onDidChange.fire(changed); } } } if (!ignoreDeleteEvents) { for (let deleted of events.deleted) { - if (this._parsedPattern(deleted.fsPath)) { + if (parsedPattern(deleted.fsPath)) { this._onDidDelete.fire(deleted); } } From a4d233065cbdc397904e4766022c60ad1a2da4e3 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 15 Sep 2017 11:39:51 +0200 Subject: [PATCH 116/145] Fixed bug in old legacy auto detection --- .../parts/tasks/electron-browser/task.contribution.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index b66c93ce362..c02e59693d7 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -1398,6 +1398,13 @@ class TaskService extends EventEmitter implements ITaskService { return this.getWorkspaceTasks().then((customTasks) => { customTasks.forEach((folderTasks, key) => { let contributed = contributedTasks.get(key); + if (!folderTasks.set) { + if (contributed) { + result.push(...contributed); + } + return; + } + if (!contributed) { result.push(...folderTasks.set.tasks); } else { From af0cc2ee2303ece9a6414309f69283d825ea63aa Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 12:54:11 +0200 Subject: [PATCH 117/145] smoke: omg, they were all using the same port! --- test/smoke/package.json | 1 + test/smoke/src/spectron/application.ts | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/test/smoke/package.json b/test/smoke/package.json index 1ab31447938..99c529813c7 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -19,6 +19,7 @@ "htmlparser2": "^3.9.2", "mocha": "^3.2.0", "ncp": "^2.0.0", + "portastic": "^1.0.1", "rimraf": "^2.6.1", "spectron": "~3.6.4", "strip-json-comments": "^2.0.1", diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index ea6fb20ed16..e4dfb9932fc 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Application, SpectronClient as WebClient } from 'spectron'; +import { test as testPort } from 'portastic'; import { SpectronClient } from './client'; import { ScreenCapturer } from '../helpers/screenshot'; import { Workbench } from '../areas/workbench/workbench'; @@ -26,6 +27,18 @@ export enum VSCODE_BUILD { STABLE } +async function findFreePort(): Promise { + for (let i = 0; i < 10; i++) { + const port = 10000 + Math.round(Math.random() * 5000); + + if (await testPort(port)) { + return port; + } + } + + throw new Error('Could not find free port!'); +} + /** * Wraps Spectron's Application instance with its used methods. */ @@ -116,8 +129,15 @@ export class SpectronApplication { chromeDriverArgs.push(`--user-data-dir=${path.join(this._userDir, new Date().getTime().toString())}`); + // Spectron always uses the same port number for the chrome driver + // and it handles gracefully when two instances use the same port number + // This works, but when one of the instances quits, it takes down + // chrome driver with it, leaving the other instance in DISPAIR!!! :( + const port = await findFreePort(); + this.spectron = new Application({ path: this._electronPath, + port, args, chromeDriverArgs, startTimeout: 10000, @@ -135,7 +155,7 @@ export class SpectronApplication { // Spectron opens multiple terminals in Windows platform // Workaround to focus the right window - https://github.com/electron/spectron/issues/60 await this.client.windowByIndex(1); - await this.app.browserWindow.focus(); + // await this.app.browserWindow.focus(); await this.client.waitForHTML('[id="workbench.main.container"]'); } From 867e521341fc39ca6f1c7e10e1d4d27d1b85b963 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 12:57:09 +0200 Subject: [PATCH 118/145] dont read XDG_RUNTIME_DIR --- extensions/git/src/askpass.ts | 4 ---- src/vs/platform/environment/node/environmentService.ts | 7 ------- 2 files changed, 11 deletions(-) diff --git a/extensions/git/src/askpass.ts b/extensions/git/src/askpass.ts index 597cc043d4e..e241ced459a 100644 --- a/extensions/git/src/askpass.ts +++ b/extensions/git/src/askpass.ts @@ -27,10 +27,6 @@ function getIPCHandlePath(nonce: string): string { return `\\\\.\\pipe\\vscode-git-askpass-${nonce}-sock`; } - if (process.env['XDG_RUNTIME_DIR']) { - return path.join(process.env['XDG_RUNTIME_DIR'], `vscode-git-askpass-${nonce}.sock`); - } - return path.join(os.tmpdir(), `vscode-git-askpass-${nonce}.sock`); } diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 36a1ed42492..01222188e6a 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -31,14 +31,7 @@ function getUniqueUserId(): string { return crypto.createHash('sha256').update(username).digest('hex').substr(0, 6); } -// Read this before there's any chance it is overwritten -// Related to https://github.com/Microsoft/vscode/issues/30624 -const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR']; - function getNixIPCHandle(userDataPath: string, type: string): string { - if (xdgRuntimeDir) { - return path.join(xdgRuntimeDir, `${pkg.name}-${pkg.version}-${type}.sock`); - } return path.join(userDataPath, `${pkg.version}-${type}.sock`); } From 575efe5a5dc8ae933642f2cc0af425ba53f752b8 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 15 Sep 2017 13:18:01 +0200 Subject: [PATCH 119/145] Make gulp auto detection multi folder aware --- extensions/gulp/package.json | 1 + extensions/gulp/src/main.ts | 349 ++++++++++++++++++++++++----------- 2 files changed, 242 insertions(+), 108 deletions(-) diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 235f3e2d138..498384f3fa7 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -31,6 +31,7 @@ "title": "Gulp", "properties": { "gulp.autoDetect": { + "scope": "resource", "type": "string", "enum": [ "off", diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index 24d7370cf13..28240a29f18 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -13,49 +13,6 @@ import * as nls from 'vscode-nls'; const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); type AutoDetect = 'on' | 'off'; -let taskProvider: vscode.Disposable | undefined; - -export function activate(_context: vscode.ExtensionContext): void { - let workspaceRoot = vscode.workspace.rootPath; - if (!workspaceRoot) { - return; - } - let pattern = path.join(workspaceRoot, 'gulpfile{.babel.js,.js}'); - let gulpPromise: Thenable | undefined = undefined; - let fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); - fileWatcher.onDidChange(() => gulpPromise = undefined); - fileWatcher.onDidCreate(() => gulpPromise = undefined); - fileWatcher.onDidDelete(() => gulpPromise = undefined); - - function onConfigurationChanged() { - let autoDetect = vscode.workspace.getConfiguration('gulp').get('autoDetect'); - if (taskProvider && autoDetect === 'off') { - gulpPromise = undefined; - taskProvider.dispose(); - taskProvider = undefined; - } else if (!taskProvider && autoDetect === 'on') { - taskProvider = vscode.workspace.registerTaskProvider('gulp', { - provideTasks: () => { - if (!gulpPromise) { - gulpPromise = getGulpTasks(); - } - return gulpPromise; - }, - resolveTask(_task: vscode.Task): vscode.Task | undefined { - return undefined; - } - }); - } - } - vscode.workspace.onDidChangeConfiguration(onConfigurationChanged); - onConfigurationChanged(); -} - -export function deactivate(): void { - if (taskProvider) { - taskProvider.dispose(); - } -} function exists(file: string): Promise { return new Promise((resolve, _reject) => { @@ -76,19 +33,6 @@ function exec(command: string, options: cp.ExecOptions): Promise<{ stdout: strin }); } -let _channel: vscode.OutputChannel; -function getOutputChannel(): vscode.OutputChannel { - if (!_channel) { - _channel = vscode.window.createOutputChannel('Gulp Auto Detection'); - } - return _channel; -} - -interface GulpTaskDefinition extends vscode.TaskDefinition { - task: string; - file?: string; -} - const buildNames: string[] = ['build', 'compile', 'watch']; function isBuildTask(name: string): boolean { for (let buildName of buildNames) { @@ -109,69 +53,258 @@ function isTestTask(name: string): boolean { return false; } -async function getGulpTasks(): Promise { - let workspaceRoot = vscode.workspace.rootPath; - let emptyTasks: vscode.Task[] = []; - if (!workspaceRoot) { - return emptyTasks; +let _channel: vscode.OutputChannel; +function getOutputChannel(): vscode.OutputChannel { + if (!_channel) { + _channel = vscode.window.createOutputChannel('Gulp Auto Detection'); } - let gulpfile = path.join(workspaceRoot, 'gulpfile.js'); - if (!await exists(gulpfile)) { - gulpfile = path.join(workspaceRoot, 'gulpfile.babel.js'); - if (! await exists(gulpfile)) { + return _channel; +} + +interface GulpTaskDefinition extends vscode.TaskDefinition { + task: string; + file?: string; +} + +class FolderDetector { + + private fileWatcher: vscode.FileSystemWatcher; + private promise: Thenable | undefined; + + constructor(private _workspaceFolder: vscode.WorkspaceFolder) { + } + + public get workspaceFolder(): vscode.WorkspaceFolder { + return this._workspaceFolder; + } + + public isEnabled(): boolean { + return vscode.workspace.getConfiguration('gulp', this._workspaceFolder.uri).get('autoDetect') === 'on'; + } + + public start(): void { + let pattern = path.join(this._workspaceFolder.uri.fsPath, 'gulpfile{.babel.js,.js}'); + this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + this.fileWatcher.onDidChange(() => this.promise = undefined); + this.fileWatcher.onDidCreate(() => this.promise = undefined); + this.fileWatcher.onDidDelete(() => this.promise = undefined); + } + + public async getTasks(): Promise { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } + + private async computeTasks(): Promise { + let rootPath = this._workspaceFolder.uri.scheme === 'file' ? this._workspaceFolder.uri.fsPath : undefined; + let emptyTasks: vscode.Task[] = []; + if (!rootPath) { + return emptyTasks; + } + let gulpfile = path.join(rootPath, 'gulpfile.js'); + if (!await exists(gulpfile)) { + gulpfile = path.join(rootPath, 'gulpfile.babel.js'); + if (! await exists(gulpfile)) { + return emptyTasks; + } + } + + let gulpCommand: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'gulp.cmd'))) { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd'); + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'gulp'))) { + gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp'); + } else { + gulpCommand = 'gulp'; + } + + let commandLine = `${gulpCommand} --tasks-simple --no-color`; + try { + let { stdout, stderr } = await exec(commandLine, { cwd: rootPath }); + if (stderr && stderr.length > 0) { + getOutputChannel().appendLine(stderr); + getOutputChannel().show(true); + } + let result: vscode.Task[] = []; + if (stdout) { + let lines = stdout.split(/\r{0,1}\n/); + for (let line of lines) { + if (line.length === 0) { + continue; + } + let kind: GulpTaskDefinition = { + type: 'gulp', + task: line + }; + let task = new vscode.Task(kind, this.workspaceFolder, line, 'gulp', new vscode.ShellExecution(`${gulpCommand} ${line}`)); + result.push(task); + let lowerCaseLine = line.toLowerCase(); + if (isBuildTask(lowerCaseLine)) { + task.group = vscode.TaskGroup.Build; + } else if (isTestTask(lowerCaseLine)) { + task.group = vscode.TaskGroup.Test; + } + } + } + return result; + } catch (err) { + let channel = getOutputChannel(); + if (err.stderr) { + channel.appendLine(err.stderr); + } + if (err.stdout) { + channel.appendLine(err.stdout); + } + channel.appendLine(localize('execFailed', 'Auto detecting gulp failed with error: {0}', err.error ? err.error.toString() : 'unknown')); + channel.show(true); return emptyTasks; } } - let gulpCommand: string; - let platform = process.platform; - if (platform === 'win32' && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp.cmd'))) { - gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd'); - } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'gulp'))) { - gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp'); - } else { - gulpCommand = 'gulp'; + public dispose() { + this.promise = undefined; + if (this.fileWatcher) { + this.fileWatcher.dispose(); + } + } +} + +class TaskDetector { + + private taskProvider: vscode.Disposable | undefined; + private detectors: Map = new Map(); + private promise: Promise | undefined; + + constructor() { } - let commandLine = `${gulpCommand} --tasks-simple --no-color`; - try { - let { stdout, stderr } = await exec(commandLine, { cwd: workspaceRoot }); - if (stderr && stderr.length > 0) { - getOutputChannel().appendLine(stderr); - getOutputChannel().show(true); + public start(): void { + let folders = vscode.workspace.workspaceFolders; + if (folders) { + this.updateWorkspaceFolders(folders, []); } - let result: vscode.Task[] = []; - if (stdout) { - let lines = stdout.split(/\r{0,1}\n/); - for (let line of lines) { - if (line.length === 0) { - continue; - } - let kind: GulpTaskDefinition = { - type: 'gulp', - task: line - }; - let task = new vscode.Task(kind, line, 'gulp', new vscode.ShellExecution(`${gulpCommand} ${line}`)); - result.push(task); - let lowerCaseLine = line.toLowerCase(); - if (isBuildTask(lowerCaseLine)) { - task.group = vscode.TaskGroup.Build; - } else if (isTestTask(lowerCaseLine)) { - task.group = vscode.TaskGroup.Test; + vscode.workspace.onDidChangeWorkspaceFolders((event) => this.updateWorkspaceFolders(event.added, event.removed)); + vscode.workspace.onDidChangeConfiguration(this.updateConfiguration, this); + } + + public dispose(): void { + if (this.taskProvider) { + this.taskProvider.dispose(); + this.taskProvider = undefined; + } + this.detectors.clear(); + this.promise = undefined; + } + + private updateWorkspaceFolders(added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[]): void { + let changed = false; + for (let remove of removed) { + let detector = this.detectors.get(remove.uri.toString()); + if (detector) { + changed = true; + detector.dispose(); + this.detectors.delete(remove.uri.toString()); + } + } + for (let add of added) { + let detector = new FolderDetector(add); + if (detector.isEnabled()) { + changed = true; + this.detectors.set(add.uri.toString(), detector); + detector.start(); + } + } + if (changed) { + this.promise = undefined; + } + this.updateProvider(); + } + + private updateConfiguration(): void { + let changed = false; + for (let detector of this.detectors.values()) { + if (!detector.isEnabled()) { + changed = true; + detector.dispose(); + this.detectors.delete(detector.workspaceFolder.uri.toString()); + } + } + let folders = vscode.workspace.workspaceFolders; + if (folders) { + for (let folder of folders) { + if (!this.detectors.has(folder.uri.toString())) { + let detector = new FolderDetector(folder); + if (detector.isEnabled()) { + changed = true; + this.detectors.set(folder.uri.toString(), detector); + detector.start(); + } } } } - return result; - } catch (err) { - let channel = getOutputChannel(); - if (err.stderr) { - channel.appendLine(err.stderr); + if (changed) { + this.promise = undefined; } - if (err.stdout) { - channel.appendLine(err.stdout); - } - channel.appendLine(localize('execFailed', 'Auto detecting gulp failed with error: {0}', err.error ? err.error.toString() : 'unknown')); - channel.show(true); - return emptyTasks; + this.updateProvider(); } + + private updateProvider(): void { + if (!this.taskProvider && this.detectors.size > 0) { + this.taskProvider = vscode.workspace.registerTaskProvider('gulp', { + provideTasks: () => { + return this.getTasks(); + }, + resolveTask(_task: vscode.Task): vscode.Task | undefined { + return undefined; + } + }); + } + else if (this.taskProvider && this.detectors.size === 0) { + this.taskProvider.dispose(); + this.taskProvider = undefined; + this.promise = undefined; + } + } + + public getTasks(): Promise { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } + + private computeTasks(): Promise { + if (this.detectors.size === 0) { + return Promise.resolve([]); + } else if (this.detectors.size === 1) { + return this.detectors.values().next().value.getTasks(); + } else { + let promises: Promise[] = []; + for (let detector of this.detectors.values()) { + promises.push(detector.getTasks().then((value) => value, () => [])); + } + return Promise.all(promises).then((values) => { + let result: vscode.Task[] = []; + for (let tasks of values) { + if (tasks && tasks.length > 0) { + result.push(...tasks); + } + } + return result; + }); + } + } +} + +let detector: TaskDetector; +export function activate(_context: vscode.ExtensionContext): void { + detector = new TaskDetector(); + detector.start(); +} + +export function deactivate(): void { + detector.dispose(); } \ No newline at end of file From 48b2d7a964b77517a432833085d1b9f2dd437f69 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 15 Sep 2017 13:36:45 +0200 Subject: [PATCH 120/145] Make grunt auto detect multi folder aware --- extensions/grunt/package.json | 1 + extensions/grunt/src/main.ts | 402 ++++++++++++++++++++++------------ extensions/gulp/src/main.ts | 3 +- 3 files changed, 271 insertions(+), 135 deletions(-) diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index 0758d440b08..4c028b73312 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -31,6 +31,7 @@ "title": "Grunt", "properties": { "grunt.autoDetect": { + "scope": "resource", "type": "string", "enum": [ "off", diff --git a/extensions/grunt/src/main.ts b/extensions/grunt/src/main.ts index 554bb4963e6..a5e74585e8e 100644 --- a/extensions/grunt/src/main.ts +++ b/extensions/grunt/src/main.ts @@ -13,49 +13,6 @@ import * as nls from 'vscode-nls'; const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); type AutoDetect = 'on' | 'off'; -let taskProvider: vscode.Disposable | undefined; - -export function activate(_context: vscode.ExtensionContext): void { - let workspaceRoot = vscode.workspace.rootPath; - if (!workspaceRoot) { - return; - } - let pattern = path.join(workspaceRoot, '[Gg]runtfile.js'); - let detectorPromise: Thenable | undefined = undefined; - let fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); - fileWatcher.onDidChange(() => detectorPromise = undefined); - fileWatcher.onDidCreate(() => detectorPromise = undefined); - fileWatcher.onDidDelete(() => detectorPromise = undefined); - - function onConfigurationChanged() { - let autoDetect = vscode.workspace.getConfiguration('grunt').get('autoDetect'); - if (taskProvider && autoDetect === 'off') { - detectorPromise = undefined; - taskProvider.dispose(); - taskProvider = undefined; - } else if (!taskProvider && autoDetect === 'on') { - taskProvider = vscode.workspace.registerTaskProvider('grunt', { - provideTasks: () => { - if (!detectorPromise) { - detectorPromise = getGruntTasks(); - } - return detectorPromise; - }, - resolveTask(_task: vscode.Task): vscode.Task | undefined { - return undefined; - } - }); - } - } - vscode.workspace.onDidChangeConfiguration(onConfigurationChanged); - onConfigurationChanged(); -} - -export function deactivate(): void { - if (taskProvider) { - taskProvider.dispose(); - } -} function exists(file: string): Promise { return new Promise((resolve, _reject) => { @@ -76,19 +33,6 @@ function exec(command: string, options: cp.ExecOptions): Promise<{ stdout: strin }); } -let _channel: vscode.OutputChannel; -function getOutputChannel(): vscode.OutputChannel { - if (!_channel) { - _channel = vscode.window.createOutputChannel('Grunt Auto Detection'); - } - return _channel; -} - -interface GruntTaskDefinition extends vscode.TaskDefinition { - task: string; - file?: string; -} - const buildNames: string[] = ['build', 'compile', 'watch']; function isBuildTask(name: string): boolean { for (let buildName of buildNames) { @@ -109,97 +53,287 @@ function isTestTask(name: string): boolean { return false; } -async function getGruntTasks(): Promise { - let workspaceRoot = vscode.workspace.rootPath; - let emptyTasks: vscode.Task[] = []; - if (!workspaceRoot) { - return emptyTasks; +let _channel: vscode.OutputChannel; +function getOutputChannel(): vscode.OutputChannel { + if (!_channel) { + _channel = vscode.window.createOutputChannel('Gulp Auto Detection'); } - if (!await exists(path.join(workspaceRoot, 'gruntfile.js')) && !await exists(path.join(workspaceRoot, 'Gruntfile.js'))) { - return emptyTasks; + return _channel; +} + +interface GruntTaskDefinition extends vscode.TaskDefinition { + task: string; + file?: string; +} + +class FolderDetector { + + private fileWatcher: vscode.FileSystemWatcher; + private promise: Thenable | undefined; + + constructor(private _workspaceFolder: vscode.WorkspaceFolder) { } - let command: string; - let platform = process.platform; - if (platform === 'win32' && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'grunt.cmd'))) { - command = path.join('.', 'node_modules', '.bin', 'grunt.cmd'); - } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(workspaceRoot!, 'node_modules', '.bin', 'grunt'))) { - command = path.join('.', 'node_modules', '.bin', 'grunt'); - } else { - command = 'grunt'; + public get workspaceFolder(): vscode.WorkspaceFolder { + return this._workspaceFolder; } - let commandLine = `${command} --help --no-color`; - try { - let { stdout, stderr } = await exec(commandLine, { cwd: workspaceRoot }); - if (stderr) { - getOutputChannel().appendLine(stderr); - getOutputChannel().show(true); + public isEnabled(): boolean { + return vscode.workspace.getConfiguration('grunt', this._workspaceFolder.uri).get('autoDetect') === 'on'; + } + + public start(): void { + let pattern = path.join(this._workspaceFolder.uri.fsPath, '[Gg]runtfile.js'); + this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); + this.fileWatcher.onDidChange(() => this.promise = undefined); + this.fileWatcher.onDidCreate(() => this.promise = undefined); + this.fileWatcher.onDidDelete(() => this.promise = undefined); + } + + public async getTasks(): Promise { + if (!this.promise) { + this.promise = this.computeTasks(); } - let result: vscode.Task[] = []; - if (stdout) { - // grunt lists tasks as follows (description is wrapped into a new line if too long): - // ... - // Available tasks - // uglify Minify files with UglifyJS. * - // jshint Validate files with JSHint. * - // test Alias for "jshint", "qunit" tasks. - // default Alias for "jshint", "qunit", "concat", "uglify" tasks. - // long Alias for "eslint", "qunit", "browserify", "sass", - // "autoprefixer", "uglify", tasks. - // - // Tasks run in the order specified + return this.promise; + } - let lines = stdout.split(/\r{0,1}\n/); - let tasksStart = false; - let tasksEnd = false; - for (let line of lines) { - if (line.length === 0) { - continue; - } - if (!tasksStart && !tasksEnd) { - if (line.indexOf('Available tasks') === 0) { - tasksStart = true; + private async computeTasks(): Promise { + let rootPath = this._workspaceFolder.uri.scheme === 'file' ? this._workspaceFolder.uri.fsPath : undefined; + let emptyTasks: vscode.Task[] = []; + if (!rootPath) { + return emptyTasks; + } + if (!await exists(path.join(rootPath, 'gruntfile.js')) && !await exists(path.join(rootPath, 'Gruntfile.js'))) { + return emptyTasks; + } + + let command: string; + let platform = process.platform; + if (platform === 'win32' && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt.cmd'))) { + command = path.join('.', 'node_modules', '.bin', 'grunt.cmd'); + } else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath!, 'node_modules', '.bin', 'grunt'))) { + command = path.join('.', 'node_modules', '.bin', 'grunt'); + } else { + command = 'grunt'; + } + + let commandLine = `${command} --help --no-color`; + try { + let { stdout, stderr } = await exec(commandLine, { cwd: rootPath }); + if (stderr) { + getOutputChannel().appendLine(stderr); + getOutputChannel().show(true); + } + let result: vscode.Task[] = []; + if (stdout) { + // grunt lists tasks as follows (description is wrapped into a new line if too long): + // ... + // Available tasks + // uglify Minify files with UglifyJS. * + // jshint Validate files with JSHint. * + // test Alias for "jshint", "qunit" tasks. + // default Alias for "jshint", "qunit", "concat", "uglify" tasks. + // long Alias for "eslint", "qunit", "browserify", "sass", + // "autoprefixer", "uglify", tasks. + // + // Tasks run in the order specified + + let lines = stdout.split(/\r{0,1}\n/); + let tasksStart = false; + let tasksEnd = false; + for (let line of lines) { + if (line.length === 0) { + continue; } - } else if (tasksStart && !tasksEnd) { - if (line.indexOf('Tasks run in the order specified') === 0) { - tasksEnd = true; - } else { - let regExp = /^\s*(\S.*\S) \S/g; - let matches = regExp.exec(line); - if (matches && matches.length === 2) { - let name = matches[1]; - let kind: GruntTaskDefinition = { - type: 'grunt', - task: name - }; - let source = 'grunt'; - let task = name.indexOf(' ') === -1 - ? new vscode.Task(kind, name, source, new vscode.ShellExecution(`${command} ${name}`)) - : new vscode.Task(kind, name, source, new vscode.ShellExecution(`${command} "${name}"`)); - result.push(task); - let lowerCaseTaskName = name.toLowerCase(); - if (isBuildTask(lowerCaseTaskName)) { - task.group = vscode.TaskGroup.Build; - } else if (isTestTask(lowerCaseTaskName)) { - task.group = vscode.TaskGroup.Test; + if (!tasksStart && !tasksEnd) { + if (line.indexOf('Available tasks') === 0) { + tasksStart = true; + } + } else if (tasksStart && !tasksEnd) { + if (line.indexOf('Tasks run in the order specified') === 0) { + tasksEnd = true; + } else { + let regExp = /^\s*(\S.*\S) \S/g; + let matches = regExp.exec(line); + if (matches && matches.length === 2) { + let name = matches[1]; + let kind: GruntTaskDefinition = { + type: 'grunt', + task: name + }; + let source = 'grunt'; + let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; + let task = name.indexOf(' ') === -1 + ? new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${command} ${name}`, options)) + : new vscode.Task(kind, this.workspaceFolder, name, source, new vscode.ShellExecution(`${command} "${name}"`, options)); + result.push(task); + let lowerCaseTaskName = name.toLowerCase(); + if (isBuildTask(lowerCaseTaskName)) { + task.group = vscode.TaskGroup.Build; + } else if (isTestTask(lowerCaseTaskName)) { + task.group = vscode.TaskGroup.Test; + } } } } } } + return result; + } catch (err) { + let channel = getOutputChannel(); + if (err.stderr) { + channel.appendLine(err.stderr); + } + if (err.stdout) { + channel.appendLine(err.stdout); + } + channel.appendLine(localize('execFailed', 'Auto detecting Grunt failed with error: {0}', err.error ? err.error.toString() : 'unknown')); + channel.show(true); + return emptyTasks; } - return result; - } catch (err) { - let channel = getOutputChannel(); - if (err.stderr) { - channel.appendLine(err.stderr); - } - if (err.stdout) { - channel.appendLine(err.stdout); - } - channel.appendLine(localize('execFailed', 'Auto detecting Grunt failed with error: {0}', err.error ? err.error.toString() : 'unknown')); - channel.show(true); - return emptyTasks; } + + public dispose() { + this.promise = undefined; + if (this.fileWatcher) { + this.fileWatcher.dispose(); + } + } +} + +class TaskDetector { + + private taskProvider: vscode.Disposable | undefined; + private detectors: Map = new Map(); + private promise: Promise | undefined; + + constructor() { + } + + public start(): void { + let folders = vscode.workspace.workspaceFolders; + if (folders) { + this.updateWorkspaceFolders(folders, []); + } + vscode.workspace.onDidChangeWorkspaceFolders((event) => this.updateWorkspaceFolders(event.added, event.removed)); + vscode.workspace.onDidChangeConfiguration(this.updateConfiguration, this); + } + + public dispose(): void { + if (this.taskProvider) { + this.taskProvider.dispose(); + this.taskProvider = undefined; + } + this.detectors.clear(); + this.promise = undefined; + } + + private updateWorkspaceFolders(added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[]): void { + let changed = false; + for (let remove of removed) { + let detector = this.detectors.get(remove.uri.toString()); + if (detector) { + changed = true; + detector.dispose(); + this.detectors.delete(remove.uri.toString()); + } + } + for (let add of added) { + let detector = new FolderDetector(add); + if (detector.isEnabled()) { + changed = true; + this.detectors.set(add.uri.toString(), detector); + detector.start(); + } + } + if (changed) { + this.promise = undefined; + } + this.updateProvider(); + } + + private updateConfiguration(): void { + let changed = false; + for (let detector of this.detectors.values()) { + if (!detector.isEnabled()) { + changed = true; + detector.dispose(); + this.detectors.delete(detector.workspaceFolder.uri.toString()); + } + } + let folders = vscode.workspace.workspaceFolders; + if (folders) { + for (let folder of folders) { + if (!this.detectors.has(folder.uri.toString())) { + let detector = new FolderDetector(folder); + if (detector.isEnabled()) { + changed = true; + this.detectors.set(folder.uri.toString(), detector); + detector.start(); + } + } + } + } + if (changed) { + this.promise = undefined; + } + this.updateProvider(); + } + + private updateProvider(): void { + if (!this.taskProvider && this.detectors.size > 0) { + this.taskProvider = vscode.workspace.registerTaskProvider('gulp', { + provideTasks: () => { + return this.getTasks(); + }, + resolveTask(_task: vscode.Task): vscode.Task | undefined { + return undefined; + } + }); + } + else if (this.taskProvider && this.detectors.size === 0) { + this.taskProvider.dispose(); + this.taskProvider = undefined; + this.promise = undefined; + } + } + + public getTasks(): Promise { + if (!this.promise) { + this.promise = this.computeTasks(); + } + return this.promise; + } + + private computeTasks(): Promise { + if (this.detectors.size === 0) { + return Promise.resolve([]); + } else if (this.detectors.size === 1) { + return this.detectors.values().next().value.getTasks(); + } else { + let promises: Promise[] = []; + for (let detector of this.detectors.values()) { + promises.push(detector.getTasks().then((value) => value, () => [])); + } + return Promise.all(promises).then((values) => { + let result: vscode.Task[] = []; + for (let tasks of values) { + if (tasks && tasks.length > 0) { + result.push(...tasks); + } + } + return result; + }); + } + } +} + +let detector: TaskDetector; +export function activate(_context: vscode.ExtensionContext): void { + detector = new TaskDetector(); + detector.start(); +} + +export function deactivate(): void { + detector.dispose(); } \ No newline at end of file diff --git a/extensions/gulp/src/main.ts b/extensions/gulp/src/main.ts index 28240a29f18..127e07afd64 100644 --- a/extensions/gulp/src/main.ts +++ b/extensions/gulp/src/main.ts @@ -139,7 +139,8 @@ class FolderDetector { type: 'gulp', task: line }; - let task = new vscode.Task(kind, this.workspaceFolder, line, 'gulp', new vscode.ShellExecution(`${gulpCommand} ${line}`)); + let options: vscode.ShellExecutionOptions = { cwd: this.workspaceFolder.uri.fsPath }; + let task = new vscode.Task(kind, this.workspaceFolder, line, 'gulp', new vscode.ShellExecution(`${gulpCommand} ${line}`, options)); result.push(task); let lowerCaseLine = line.toLowerCase(); if (isBuildTask(lowerCaseLine)) { From bcd81812382b5385ad647e2d612e50237bcd50e5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 15 Sep 2017 15:20:58 +0200 Subject: [PATCH 121/145] more strict (and correct) URI.file, #34449 --- src/vs/base/common/uri.ts | 15 +++++++--- src/vs/base/test/common/uri.test.ts | 44 ++++++++++++++++------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 39ad9e80805..4dfeff378ee 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -56,6 +56,7 @@ export default class URI { private static _empty = ''; private static _slash = '/'; private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; + private static _driveLetter = /^[a-zA-Z]:/; private static _driveLetterPath = /^\/[a-zA-Z]:/; private static _upperCaseDrive = /^(\/)?([A-Z]:)/; @@ -212,19 +213,25 @@ export default class URI { let idx = path.indexOf(URI._slash, 2); if (idx === -1) { authority = path.substring(2); - path = URI._empty; + path = URI._slash; } else { authority = path.substring(2, idx); path = path.substring(idx); } } - // Ensure that path starts with a slash - // or that it is at least a slash - if (path[0] !== URI._slash) { + // absolute windows paths get another slash + if (URI._driveLetter.test(path)) { path = URI._slash + path; } + // path must be absolute because we cannot format them + // otherwise: `file:./foo` -> file://./foo -> `{ authority: '.', path: 'foo' }` + // https://tools.ietf.org/html/rfc8089#section-2 + else if (path[0] !== URI._slash) { + throw new Error('[UriError]: relative paths are not supported.'); + } + return new URI('file', authority, path, URI._empty, URI._empty); } diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 3341b0bcb6a..df2d989d26c 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -38,13 +38,11 @@ suite('URI', () => { assert.equal(URI.file('c:/win/path/').fsPath, 'c:\\win\\path\\'); assert.equal(URI.file('C:/win/path').fsPath, 'c:\\win\\path'); assert.equal(URI.file('/c:/win/path').fsPath, 'c:\\win\\path'); - assert.equal(URI.file('./c/win/path').fsPath, '\\.\\c\\win\\path'); } else { assert.equal(URI.file('c:/win/path').fsPath, 'c:/win/path'); assert.equal(URI.file('c:/win/path/').fsPath, 'c:/win/path/'); assert.equal(URI.file('C:/win/path').fsPath, 'c:/win/path'); assert.equal(URI.file('/c:/win/path').fsPath, 'c:/win/path'); - assert.equal(URI.file('./c/win/path').fsPath, '/./c/win/path'); } }); @@ -318,27 +316,12 @@ suite('URI', () => { test('URI#file, no path-is-uri check', () => { // we don't complain here - let value = URI.file('file://path/to/file'); + let value = URI.file('/file://path/to/file'); assert.equal(value.scheme, 'file'); assert.equal(value.authority, ''); assert.equal(value.path, '/file://path/to/file'); }); - test('URI#file, always slash', () => { - - var value = URI.file('a.file'); - assert.equal(value.scheme, 'file'); - assert.equal(value.authority, ''); - assert.equal(value.path, '/a.file'); - assert.equal(value.toString(), 'file:///a.file'); - - value = URI.parse(value.toString()); - assert.equal(value.scheme, 'file'); - assert.equal(value.authority, ''); - assert.equal(value.path, '/a.file'); - assert.equal(value.toString(), 'file:///a.file'); - }); - test('URI.toString, only scheme and query', () => { var value = URI.parse('stuff:?qüery'); assert.equal(value.toString(), 'stuff:?q%C3%BCery'); @@ -427,13 +410,36 @@ suite('URI', () => { assert.equal(uri.toString(true), 'https://twitter.com/search?src=typd&q=%23tag'); }); + test('class URI cannot represent relative file paths, #34449', function () { + const uri = URI.parse('file:./relative/path'); + assert.equal(uri.scheme, 'file'); + assert.equal(uri.authority, ''); + assert.equal(uri.path, './relative/path'); + + assert.equal(uri.toString(), 'file://./relative/path'); + + // this is asymetric to be spec-compliant + const uri2 = URI.parse(uri.toString()); + assert.equal(uri2.authority, '.'); + assert.equal(uri2.path, '/relative/path'); + }); + + test('class URI cannot represent relative file paths, #34449', function () { + + const path = '/foo/bar'; + assert.equal(URI.file(path).path, path); + + // no relative paths + assert.throws(() => URI.file('foo/bar')); + assert.throws(() => URI.file('./foo/bar')); + }); test('URI - (de)serialize', function () { var values = [ URI.parse('http://localhost:8080/far'), URI.file('c:\\test with %25\\c#code'), - URI.file('\\\\shäres\\path\\c#\\plugin.json'), + URI.file('//shäres/path/c#/plugin.json'), URI.parse('http://api/files/test.me?t=1234'), URI.parse('http://api/files/test.me?t=1234#fff'), URI.parse('http://api/files/test.me#fff'), From 04bf2a2a500b10932aebdcb68c51dc969e29aa71 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 15:20:45 +0200 Subject: [PATCH 122/145] smoke: fix broken http ping --- test/smoke/src/areas/debug/debug.test.ts | 18 +++++++++++------- test/smoke/src/areas/debug/debug.ts | 11 +++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 1d5e0c080cf..4aeeba790ee 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -69,10 +69,12 @@ describe('Debug', () => { port = await app.workbench.debug.startDebugging(); await app.screenCapturer.capture('debugging has started'); - await new Promise((c, e) => http.get(`http://localhost:${port}`).on('response', c).on('error', e)); - await app.screenCapturer.capture('server was pinged'); + await new Promise((c, e) => { + const request = http.get(`http://localhost:${port}`); + request.on('error', e); + app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6).then(c, e); + }); - await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); await app.screenCapturer.capture('debugging is paused'); }); @@ -108,15 +110,17 @@ describe('Debug', () => { await app.workbench.debug.continue(); await app.screenCapturer.capture('debugging has continued'); - await new Promise((c, e) => http.get(`http://localhost:${port}`).on('response', c).on('error', e)); - await app.screenCapturer.capture('server was pinged'); + await new Promise((c, e) => { + const request = http.get(`http://localhost:${port}`); + request.on('error', e); + app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6).then(c, e); + }); - await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6); await app.screenCapturer.capture('debugging is paused'); }); it('debug console', async function () { - await app.client.waitFor(() => app.workbench.debug.console('2 + 2 \n'), r => r === '4', 'debug console should return 2 + 2 = 4'); + await app.workbench.debug.waitForReplCommand('2 + 2 \n', r => r === '4'); }); it('stop debugging', async function () { diff --git a/test/smoke/src/areas/debug/debug.ts b/test/smoke/src/areas/debug/debug.ts index ddca2631983..e16e3a51bc5 100644 --- a/test/smoke/src/areas/debug/debug.ts +++ b/test/smoke/src/areas/debug/debug.ts @@ -25,7 +25,6 @@ const STACK_FRAME = `${VIEWLET} .monaco-tree-row .stack-frame`; const VARIABLE = `${VIEWLET} .debug-variables .monaco-tree-row .expression`; const CONSOLE_OUTPUT = `.repl .output.expression`; const CONSOLE_INPUT_OUTPUT = `.repl .input-output-pair .output.expression .value`; -const SCOPE = `${VIEWLET} .debug-variables .scope`; const REPL_FOCUSED = '.repl-input-wrapper .monaco-editor.focused'; @@ -112,18 +111,18 @@ export class Debug extends Viewlet { await this.spectron.workbench.waitForTab(name); } - async console(text: string): Promise { + async waitForReplCommand(text: string, accept: (result: string) => boolean): Promise { await this.spectron.workbench.quickopen.runCommand('Debug: Focus Debug Console'); await this.spectron.client.waitForElement(REPL_FOCUSED); await this.spectron.client.type(text); await this.spectron.client.waitForElement(CONSOLE_INPUT_OUTPUT); - - const result = await this.getConsoleOutput(); - return result[result.length - 1] || ''; + await this.spectron.client.waitFor(async () => { + const result = await this.getConsoleOutput(); + return result[result.length - 1] || ''; + }, accept); } async getLocalVariableCount(): Promise { - await this.spectron.client.waitForElement(SCOPE); return await this.spectron.webclient.selectorExecute(VARIABLE, div => (Array.isArray(div) ? div : [div]).length); } From 16ad2b784523ce1409e1837097fcf1db7e30585f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 15:31:36 +0200 Subject: [PATCH 123/145] smoke: enable concurrent debug runs using different ports --- test/smoke/src/areas/debug/debug.test.ts | 6 ++++-- test/smoke/src/spectron/application.ts | 12 +++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test/smoke/src/areas/debug/debug.test.ts b/test/smoke/src/areas/debug/debug.test.ts index 4aeeba790ee..a6e35ef4ea7 100644 --- a/test/smoke/src/areas/debug/debug.test.ts +++ b/test/smoke/src/areas/debug/debug.test.ts @@ -9,7 +9,7 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as stripJsonComments from 'strip-json-comments'; -import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR } from '../../spectron/application'; +import { SpectronApplication, VSCODE_BUILD, EXTENSIONS_DIR, findFreePort } from '../../spectron/application'; describe('Debug', () => { let app: SpectronApplication = new SpectronApplication(); @@ -38,7 +38,9 @@ describe('Debug', () => { fs.symlinkSync(debug2Path, path.join(EXTENSIONS_DIR, 'vscode-node-debug2')); } - before(() => app.start('Debug')); + // We must get a different port for our smoketest express app + // otherwise concurrent test runs will clash on those ports + before(async () => await app.start('Debug', [], { PORT: String(await findFreePort()), ...process.env })); after(() => app.stop()); beforeEach(function () { app.screenCapturer.testName = this.currentTest.title; }); diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index e4dfb9932fc..6fe520c9280 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -27,9 +27,10 @@ export enum VSCODE_BUILD { STABLE } -async function findFreePort(): Promise { +// Just hope random helps us here, cross your fingers! +export async function findFreePort(): Promise { for (let i = 0; i < 10; i++) { - const port = 10000 + Math.round(Math.random() * 5000); + const port = 10000 + Math.round(Math.random() * 10000); if (await testPort(port)) { return port; @@ -83,10 +84,10 @@ export class SpectronApplication { return this._workbench; } - public async start(testSuiteName: string, codeArgs: string[] = []): Promise { + public async start(testSuiteName: string, codeArgs: string[] = [], env = process.env): Promise { await this.retrieveKeybindings(); cp.execSync('git checkout .', { cwd: WORKSPACE_PATH }); - await this.startApplication(testSuiteName, codeArgs); + await this.startApplication(testSuiteName, codeArgs, env); await this.checkWindowReady(); await this.waitForWelcome(); await this.screenCapturer.capture('Application started'); @@ -110,7 +111,7 @@ export class SpectronApplication { return new Promise(resolve => setTimeout(resolve, seconds * 1000)); } - private async startApplication(testSuiteName: string, codeArgs: string[] = []): Promise { + private async startApplication(testSuiteName: string, codeArgs: string[] = [], env = process.env): Promise { let args: string[] = []; let chromeDriverArgs: string[] = []; @@ -139,6 +140,7 @@ export class SpectronApplication { path: this._electronPath, port, args, + env, chromeDriverArgs, startTimeout: 10000, requireName: 'nodeRequire' From 04a94d18a9a7b9f29ffa7cf39b6841c6b0bd967d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 15:52:19 +0200 Subject: [PATCH 124/145] smoke: --sticky-quickopen cli option --- src/vs/platform/environment/common/environment.ts | 1 + src/vs/platform/environment/node/argv.ts | 3 ++- .../browser/parts/quickopen/quickOpenController.ts | 7 ++++++- test/smoke/src/spectron/application.ts | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index b4ee3dfcca3..540f812d271 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -40,6 +40,7 @@ export interface ParsedArgs { 'enable-proposed-api'?: string | string[]; 'open-url'?: string | string[]; 'skip-getting-started'?: boolean; + 'sticky-quickopen'?: boolean; } export const IEnvironmentService = createDecorator('environmentService'); diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index ad6e24e0eb2..6eb3036e94a 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -46,7 +46,8 @@ const options: minimist.Opts = { 'list-extensions', 'show-versions', 'nolazy', - 'skip-getting-started' + 'skip-getting-started', + 'sticky-quickopen' ], alias: { add: 'a', diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index ab33817c228..10d32871c4b 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -111,6 +111,7 @@ export class QuickOpenController extends Component implements IQuickOpenService @IInstantiationService private instantiationService: IInstantiationService, @IPartService private partService: IPartService, @IListService private listService: IListService, + @IEnvironmentService private environmentService: IEnvironmentService, @IThemeService themeService: IThemeService ) { super(QuickOpenController.ID, themeService); @@ -138,7 +139,11 @@ export class QuickOpenController extends Component implements IQuickOpenService } private updateConfiguration(settings: IWorkbenchQuickOpenConfiguration): void { - this.closeOnFocusLost = settings.workbench && settings.workbench.quickOpen && settings.workbench.quickOpen.closeOnFocusLost; + if (this.environmentService.args['sticky-quickopen']) { + this.closeOnFocusLost = false; + } else { + this.closeOnFocusLost = settings.workbench && settings.workbench.quickOpen && settings.workbench.quickOpen.closeOnFocusLost; + } } public get onShow(): Event { diff --git a/test/smoke/src/spectron/application.ts b/test/smoke/src/spectron/application.ts index 6fe520c9280..abdeb24ff01 100644 --- a/test/smoke/src/spectron/application.ts +++ b/test/smoke/src/spectron/application.ts @@ -121,8 +121,13 @@ export class SpectronApplication { } args.push(this._workspace); + // Prevent 'Getting Started' web page from opening on clean user-data-dir args.push('--skip-getting-started'); + + // Prevent Quick Open from closing when focus is stolen, this allows concurrent smoketest suite running + args.push('--sticky-quickopen'); + // Ensure that running over custom extensions directory, rather than picking up the one that was used by a tester previously args.push(`--extensions-dir=${EXTENSIONS_DIR}`); From 8e0581bae4183d30f44f1f9b08b38a5d0a009bf3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 15:55:17 +0200 Subject: [PATCH 125/145] smoke: prevent nested waitFor calls --- test/smoke/src/spectron/client.ts | 51 +++++++++++++++++++------------ 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/test/smoke/src/spectron/client.ts b/test/smoke/src/spectron/client.ts index 2d48c427cd4..72697d5d903 100644 --- a/test/smoke/src/spectron/client.ts +++ b/test/smoke/src/spectron/client.ts @@ -145,30 +145,41 @@ export class SpectronClient { return this.spectron.client.getTitle(); } + private running = false; public async waitFor(func: () => T | Promise, accept?: (result: T) => boolean | Promise, timeoutMessage?: string, retryCount?: number): Promise; public async waitFor(func: () => T | Promise, accept: (result: T) => boolean | Promise = result => !!result, timeoutMessage?: string, retryCount?: number): Promise { - let trial = 1; - retryCount = typeof retryCount === 'number' ? retryCount : this.retryCount; + if (this.running) { + throw new Error('Not allowed to run nested waitFor calls!'); + } - while (true) { - if (trial > retryCount) { - await this.application.screenCapturer.capture('timeout'); - throw new Error(`${timeoutMessage}: Timed out after ${(retryCount * this.retryDuration) / 1000} seconds.`); + this.running = true; + + try { + let trial = 1; + retryCount = typeof retryCount === 'number' ? retryCount : this.retryCount; + + while (true) { + if (trial > retryCount) { + await this.application.screenCapturer.capture('timeout'); + throw new Error(`${timeoutMessage}: Timed out after ${(retryCount * this.retryDuration) / 1000} seconds.`); + } + + let result; + try { + result = await func(); + } catch (e) { + // console.log(e); + } + + if (accept(result)) { + return result; + } + + await new Promise(resolve => setTimeout(resolve, this.retryDuration)); + trial++; } - - let result; - try { - result = await func(); - } catch (e) { - // console.log(e); - } - - if (accept(result)) { - return result; - } - - await new Promise(resolve => setTimeout(resolve, this.retryDuration)); - trial++; + } finally { + this.running = false; } } From e5fb2c8291648630471ef955576ce0b25001731a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 15:57:40 +0200 Subject: [PATCH 126/145] smoke: different slow number --- test/smoke/test/mocha.opts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/test/mocha.opts b/test/smoke/test/mocha.opts index f7385dc1642..102d5b65ade 100644 --- a/test/smoke/test/mocha.opts +++ b/test/smoke/test/mocha.opts @@ -1,3 +1,3 @@ --timeout 60000 ---slow 10000 +--slow 20000 out/main.js \ No newline at end of file From 2d32c952761707b439ef20fb6873d601336ae108 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 16:00:28 +0200 Subject: [PATCH 127/145] smoke: forgot await --- test/smoke/src/areas/statusbar/statusbar.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 42a71882469..b5f38b67194 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -79,7 +79,7 @@ describe('Statusbar', () => { await app.workbench.quickopen.waitForQuickOpenOpened(); - app.workbench.quickopen.selectQuickOpenElement(1); + await app.workbench.quickopen.selectQuickOpenElement(1); await app.workbench.statusbar.waitForEOL('CRLF'); }); }); \ No newline at end of file From e8a6fea08cd3f0efc8e04a223a4f1e2d57fe8d4e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 15 Sep 2017 16:33:05 +0200 Subject: [PATCH 128/145] Revert "more strict (and correct) URI.file, #34449" This reverts commit bcd81812382b5385ad647e2d612e50237bcd50e5. --- src/vs/base/common/uri.ts | 15 +++------- src/vs/base/test/common/uri.test.ts | 44 +++++++++++++---------------- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 4dfeff378ee..39ad9e80805 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -56,7 +56,6 @@ export default class URI { private static _empty = ''; private static _slash = '/'; private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; - private static _driveLetter = /^[a-zA-Z]:/; private static _driveLetterPath = /^\/[a-zA-Z]:/; private static _upperCaseDrive = /^(\/)?([A-Z]:)/; @@ -213,25 +212,19 @@ export default class URI { let idx = path.indexOf(URI._slash, 2); if (idx === -1) { authority = path.substring(2); - path = URI._slash; + path = URI._empty; } else { authority = path.substring(2, idx); path = path.substring(idx); } } - // absolute windows paths get another slash - if (URI._driveLetter.test(path)) { + // Ensure that path starts with a slash + // or that it is at least a slash + if (path[0] !== URI._slash) { path = URI._slash + path; } - // path must be absolute because we cannot format them - // otherwise: `file:./foo` -> file://./foo -> `{ authority: '.', path: 'foo' }` - // https://tools.ietf.org/html/rfc8089#section-2 - else if (path[0] !== URI._slash) { - throw new Error('[UriError]: relative paths are not supported.'); - } - return new URI('file', authority, path, URI._empty, URI._empty); } diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index df2d989d26c..3341b0bcb6a 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -38,11 +38,13 @@ suite('URI', () => { assert.equal(URI.file('c:/win/path/').fsPath, 'c:\\win\\path\\'); assert.equal(URI.file('C:/win/path').fsPath, 'c:\\win\\path'); assert.equal(URI.file('/c:/win/path').fsPath, 'c:\\win\\path'); + assert.equal(URI.file('./c/win/path').fsPath, '\\.\\c\\win\\path'); } else { assert.equal(URI.file('c:/win/path').fsPath, 'c:/win/path'); assert.equal(URI.file('c:/win/path/').fsPath, 'c:/win/path/'); assert.equal(URI.file('C:/win/path').fsPath, 'c:/win/path'); assert.equal(URI.file('/c:/win/path').fsPath, 'c:/win/path'); + assert.equal(URI.file('./c/win/path').fsPath, '/./c/win/path'); } }); @@ -316,12 +318,27 @@ suite('URI', () => { test('URI#file, no path-is-uri check', () => { // we don't complain here - let value = URI.file('/file://path/to/file'); + let value = URI.file('file://path/to/file'); assert.equal(value.scheme, 'file'); assert.equal(value.authority, ''); assert.equal(value.path, '/file://path/to/file'); }); + test('URI#file, always slash', () => { + + var value = URI.file('a.file'); + assert.equal(value.scheme, 'file'); + assert.equal(value.authority, ''); + assert.equal(value.path, '/a.file'); + assert.equal(value.toString(), 'file:///a.file'); + + value = URI.parse(value.toString()); + assert.equal(value.scheme, 'file'); + assert.equal(value.authority, ''); + assert.equal(value.path, '/a.file'); + assert.equal(value.toString(), 'file:///a.file'); + }); + test('URI.toString, only scheme and query', () => { var value = URI.parse('stuff:?qüery'); assert.equal(value.toString(), 'stuff:?q%C3%BCery'); @@ -410,36 +427,13 @@ suite('URI', () => { assert.equal(uri.toString(true), 'https://twitter.com/search?src=typd&q=%23tag'); }); - test('class URI cannot represent relative file paths, #34449', function () { - const uri = URI.parse('file:./relative/path'); - assert.equal(uri.scheme, 'file'); - assert.equal(uri.authority, ''); - assert.equal(uri.path, './relative/path'); - - assert.equal(uri.toString(), 'file://./relative/path'); - - // this is asymetric to be spec-compliant - const uri2 = URI.parse(uri.toString()); - assert.equal(uri2.authority, '.'); - assert.equal(uri2.path, '/relative/path'); - }); - - test('class URI cannot represent relative file paths, #34449', function () { - - const path = '/foo/bar'; - assert.equal(URI.file(path).path, path); - - // no relative paths - assert.throws(() => URI.file('foo/bar')); - assert.throws(() => URI.file('./foo/bar')); - }); test('URI - (de)serialize', function () { var values = [ URI.parse('http://localhost:8080/far'), URI.file('c:\\test with %25\\c#code'), - URI.file('//shäres/path/c#/plugin.json'), + URI.file('\\\\shäres\\path\\c#\\plugin.json'), URI.parse('http://api/files/test.me?t=1234'), URI.parse('http://api/files/test.me?t=1234#fff'), URI.parse('http://api/files/test.me#fff'), From 1be57ab371eddbdb8b6b9ad215bcf08fc305d595 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Fri, 15 Sep 2017 16:34:41 +0200 Subject: [PATCH 129/145] move lightbulb enablement logic into lightbulb, #27961 --- .../quickFix/browser/lightBulbWidget.ts | 13 ++- .../quickFix/browser/quickFixCommands.ts | 86 ++++++------------- 2 files changed, 35 insertions(+), 64 deletions(-) diff --git a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts index c25c621b809..2b76c9e2540 100644 --- a/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/quickFix/browser/lightBulbWidget.ts @@ -66,6 +66,12 @@ export class LightBulbWidget implements IDisposable, IContentWidget { dom.removeClass(this._domNode, 'hidden'); }); })); + this._disposables.push(this._editor.onDidChangeConfiguration(e => { + // hide when told to do so + if (e.contribInfo && !this._editor.getConfiguration().contribInfo.lightbulbEnabled) { + this.hide(); + } + })); } dispose(): void { @@ -124,11 +130,14 @@ export class LightBulbWidget implements IDisposable, IContentWidget { } private _show(): void { - const { fontInfo } = this._editor.getConfiguration(); + const config = this._editor.getConfiguration(); + if (!config.contribInfo.lightbulbEnabled) { + return; + } const { lineNumber } = this._model.position; const model = this._editor.getModel(); const indent = model.getIndentLevel(lineNumber); - const lineHasSpace = fontInfo.spaceWidth * indent > 22; + const lineHasSpace = config.fontInfo.spaceWidth * indent > 22; let effectiveLineNumber = lineNumber; if (!lineHasSpace) { diff --git a/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts b/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts index e6a1ef98e96..605591babeb 100644 --- a/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts +++ b/src/vs/editor/contrib/quickFix/browser/quickFixCommands.ts @@ -9,7 +9,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IMarkerService } from 'vs/platform/markers/common/markers'; import { ICommonCodeEditor, IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -32,28 +32,30 @@ export class QuickFixController implements IEditorContribution { private _editor: ICodeEditor; private _model: QuickFixModel; - private _quickFixContextMenu: QuickFixContextMenu | undefined; - private _lightBulbWidget: LightBulbWidget | undefined; + private _quickFixContextMenu: QuickFixContextMenu; + private _lightBulbWidget: LightBulbWidget; private _disposables: IDisposable[] = []; - private enabled: boolean = false; - - constructor( - editor: ICodeEditor, + constructor(editor: ICodeEditor, @IMarkerService markerService: IMarkerService, - @ICommandService private readonly _commandService: ICommandService, - @IContextMenuService private readonly _contextMenuService: IContextMenuService, - @IKeybindingService private readonly _keybindingService: IKeybindingService + @IContextKeyService contextKeyService: IContextKeyService, + @ICommandService commandService: ICommandService, + @IContextMenuService contextMenuService: IContextMenuService, + @IKeybindingService private _keybindingService: IKeybindingService ) { this._editor = editor; this._model = new QuickFixModel(this._editor, markerService); + this._quickFixContextMenu = new QuickFixContextMenu(editor, contextMenuService, commandService); + this._lightBulbWidget = new LightBulbWidget(editor); + + this._updateLightBulbTitle(); this._disposables.push( - this._editor.onDidChangeConfiguration(() => this.onEditorConfigurationChange()), - this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)) + this._quickFixContextMenu.onDidExecuteCodeAction(_ => this._model.trigger('auto')), + this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), + this._model.onDidChangeFixes(e => this._onQuickFixEvent(e)), + this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) ); - - this.onEditorConfigurationChange(); } public dispose(): void { @@ -61,46 +63,21 @@ export class QuickFixController implements IEditorContribution { dispose(this._disposables); } - private get lightBulbWidget(): LightBulbWidget { - if (!this._lightBulbWidget) { - this._lightBulbWidget = new LightBulbWidget(this._editor); - this._disposables.push( - this._lightBulbWidget.onClick(this._handleLightBulbSelect, this), - this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this) - ); - this._updateLightBulbTitle(); - } - return this._lightBulbWidget; - } - - private get quickFixContextMenu(): QuickFixContextMenu { - if (!this._quickFixContextMenu) { - this._quickFixContextMenu = new QuickFixContextMenu(this._editor, this._contextMenuService, this._commandService); - this._disposables.push(this._quickFixContextMenu.onDidExecuteCodeAction(_ => { - this._model.trigger('auto'); - })); - } - return this._quickFixContextMenu; - } - private _onQuickFixEvent(e: QuickFixComputeEvent): void { if (e && e.type === 'manual') { - this.quickFixContextMenu.show(e.fixes, e.position); + this._quickFixContextMenu.show(e.fixes, e.position); + } else if (e && e.fixes) { // auto magically triggered // * update an existing list of code actions // * manage light bulb - if (this.quickFixContextMenu.isVisible) { - this.quickFixContextMenu.show(e.fixes, e.position); + if (this._quickFixContextMenu.isVisible) { + this._quickFixContextMenu.show(e.fixes, e.position); } else { - if (this.enabled) { - this.lightBulbWidget.model = e; - } + this._lightBulbWidget.model = e; } } else { - if (this._lightBulbWidget) { - this._lightBulbWidget.hide(); - } + this._lightBulbWidget.hide(); } } @@ -109,7 +86,7 @@ export class QuickFixController implements IEditorContribution { } private _handleLightBulbSelect(coords: { x: number, y: number }): void { - this.quickFixContextMenu.show(this.lightBulbWidget.model.fixes, coords); + this._quickFixContextMenu.show(this._lightBulbWidget.model.fixes, coords); } public triggerFromEditorSelection(): void { @@ -117,10 +94,6 @@ export class QuickFixController implements IEditorContribution { } private _updateLightBulbTitle(): void { - if (!this._lightBulbWidget) { - return; - } - const kb = this._keybindingService.lookupKeybinding(QuickFixAction.Id); let title: string; if (kb) { @@ -128,18 +101,7 @@ export class QuickFixController implements IEditorContribution { } else { title = nls.localize('quickFix', "Show Fixes"); } - this.lightBulbWidget.title = title; - } - - private onEditorConfigurationChange(): void { - this.enabled = this._editor.getConfiguration().contribInfo.lightbulbEnabled; - - if (!this.enabled) { - if (this._lightBulbWidget) { - this._lightBulbWidget.dispose(); - this._lightBulbWidget = undefined; - } - } + this._lightBulbWidget.title = title; } } From bde20085c7fe57283f9d5535ea55e4a7a560726b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 15 Sep 2017 10:15:50 +0200 Subject: [PATCH 130/145] [html] use vscode-uri --- extensions/json/server/package.json | 3 +- extensions/json/server/src/jsonServerMain.ts | 2 +- extensions/json/server/src/utils/uri.ts | 351 ------------------- 3 files changed, 3 insertions(+), 353 deletions(-) delete mode 100644 extensions/json/server/src/utils/uri.ts diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json index 3b6e892cc42..d1ece9575d2 100644 --- a/extensions/json/server/package.json +++ b/extensions/json/server/package.json @@ -13,7 +13,8 @@ "vscode-json-languageservice": "^2.0.16", "vscode-languageserver": "3.4.0-next.6", "vscode-languageserver-protocol": "^3.1.1", - "vscode-nls": "^2.0.2" + "vscode-nls": "^2.0.2", + "vscode-uri": "^1.0.1" }, "devDependencies": { "@types/node": "^6.0.51" diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json/server/src/jsonServerMain.ts index 2fe428f717f..183d633ab7a 100644 --- a/extensions/json/server/src/jsonServerMain.ts +++ b/extensions/json/server/src/jsonServerMain.ts @@ -15,7 +15,7 @@ import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities } from import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light'; import path = require('path'); import fs = require('fs'); -import URI from './utils/uri'; +import URI from 'vscode-uri'; import * as URL from 'url'; import Strings = require('./utils/strings'); import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService } from 'vscode-json-languageservice'; diff --git a/extensions/json/server/src/utils/uri.ts b/extensions/json/server/src/utils/uri.ts deleted file mode 100644 index 5cce7590977..00000000000 --- a/extensions/json/server/src/utils/uri.ts +++ /dev/null @@ -1,351 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -function _encode(ch: string): string { - return '%' + ch.charCodeAt(0).toString(16).toUpperCase(); -} - -// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent -function encodeURIComponent2(str: string): string { - return encodeURIComponent(str).replace(/[!'()*]/g, _encode); -} - -function encodeNoop(str: string): string { - return str; -} - - -/** - * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986. - * This class is a simple parser which creates the basic component paths - * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation - * and encoding. - * - * foo://example.com:8042/over/there?name=ferret#nose - * \_/ \______________/\_________/ \_________/ \__/ - * | | | | | - * scheme authority path query fragment - * | _____________________|__ - * / \ / \ - * urn:example:animal:ferret:nose - * - * - */ -export default class URI { - - private static _empty = ''; - private static _slash = '/'; - private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; - private static _driveLetterPath = /^\/[a-zA-z]:/; - private static _upperCaseDrive = /^(\/)?([A-Z]:)/; - - private _scheme: string; - private _authority: string; - private _path: string; - private _query: string; - private _fragment: string; - private _formatted: string; - private _fsPath: string; - - constructor() { - this._scheme = URI._empty; - this._authority = URI._empty; - this._path = URI._empty; - this._query = URI._empty; - this._fragment = URI._empty; - - this._formatted = null; - this._fsPath = null; - } - - /** - * scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'. - * The part before the first colon. - */ - get scheme() { - return this._scheme; - } - - /** - * authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'. - * The part between the first double slashes and the next slash. - */ - get authority() { - return this._authority; - } - - /** - * path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'. - */ - get path() { - return this._path; - } - - /** - * query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'. - */ - get query() { - return this._query; - } - - /** - * fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'. - */ - get fragment() { - return this._fragment; - } - - // ---- filesystem path ----------------------- - - /** - * Returns a string representing the corresponding file system path of this URI. - * Will handle UNC paths and normalize windows drive letters to lower-case. Also - * uses the platform specific path separator. Will *not* validate the path for - * invalid characters and semantics. Will *not* look at the scheme of this URI. - */ - get fsPath() { - if (!this._fsPath) { - var value: string; - if (this._authority && this.scheme === 'file') { - // unc path: file://shares/c$/far/boo - value = `//${this._authority}${this._path}`; - } else if (URI._driveLetterPath.test(this._path)) { - // windows drive letter: file:///c:/far/boo - value = this._path[1].toLowerCase() + this._path.substr(2); - } else { - // other path - value = this._path; - } - if (process.platform === 'win32') { - value = value.replace(/\//g, '\\'); - } - this._fsPath = value; - } - return this._fsPath; - } - - // ---- modify to new ------------------------- - - public with(scheme: string, authority: string, path: string, query: string, fragment: string): URI { - var ret = new URI(); - ret._scheme = scheme || this.scheme; - ret._authority = authority || this.authority; - ret._path = path || this.path; - ret._query = query || this.query; - ret._fragment = fragment || this.fragment; - URI._validate(ret); - return ret; - } - - public withScheme(value: string): URI { - return this.with(value, undefined, undefined, undefined, undefined); - } - - public withAuthority(value: string): URI { - return this.with(undefined, value, undefined, undefined, undefined); - } - - public withPath(value: string): URI { - return this.with(undefined, undefined, value, undefined, undefined); - } - - public withQuery(value: string): URI { - return this.with(undefined, undefined, undefined, value, undefined); - } - - public withFragment(value: string): URI { - return this.with(undefined, undefined, undefined, undefined, value); - } - - // ---- parse & validate ------------------------ - - public static parse(value: string): URI { - const ret = new URI(); - const data = URI._parseComponents(value); - ret._scheme = data.scheme; - ret._authority = decodeURIComponent(data.authority); - ret._path = decodeURIComponent(data.path); - ret._query = decodeURIComponent(data.query); - ret._fragment = decodeURIComponent(data.fragment); - URI._validate(ret); - return ret; - } - - public static file(path: string): URI { - - const ret = new URI(); - ret._scheme = 'file'; - - // normalize to fwd-slashes - path = path.replace(/\\/g, URI._slash); - - // check for authority as used in UNC shares - // or use the path as given - if (path[0] === URI._slash && path[0] === path[1]) { - let idx = path.indexOf(URI._slash, 2); - if (idx === -1) { - ret._authority = path.substring(2); - } else { - ret._authority = path.substring(2, idx); - ret._path = path.substring(idx); - } - } else { - ret._path = path; - } - - // Ensure that path starts with a slash - // or that it is at least a slash - if (ret._path[0] !== URI._slash) { - ret._path = URI._slash + ret._path; - } - - URI._validate(ret); - - return ret; - } - - private static _parseComponents(value: string): UriComponents { - - const ret: UriComponents = { - scheme: URI._empty, - authority: URI._empty, - path: URI._empty, - query: URI._empty, - fragment: URI._empty, - }; - - const match = URI._regexp.exec(value); - if (match) { - ret.scheme = match[2] || ret.scheme; - ret.authority = match[4] || ret.authority; - ret.path = match[5] || ret.path; - ret.query = match[7] || ret.query; - ret.fragment = match[9] || ret.fragment; - } - return ret; - } - - public static create(scheme?: string, authority?: string, path?: string, query?: string, fragment?: string): URI { - return new URI().with(scheme, authority, path, query, fragment); - } - - private static _validate(ret: URI): void { - - // validation - // path, http://tools.ietf.org/html/rfc3986#section-3.3 - // If a URI contains an authority component, then the path component - // must either be empty or begin with a slash ("/") character. If a URI - // does not contain an authority component, then the path cannot begin - // with two slash characters ("//"). - if (ret.authority && ret.path && ret.path[0] !== '/') { - throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character'); - } - if (!ret.authority && ret.path.indexOf('//') === 0) { - throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")'); - } - } - - // ---- printing/externalize --------------------------- - - /** - * - * @param skipEncoding Do not encode the result, default is `false` - */ - public toString(skipEncoding: boolean = false): string { - if (!skipEncoding) { - if (!this._formatted) { - this._formatted = URI._asFormatted(this, false); - } - return this._formatted; - } else { - // we don't cache that - return URI._asFormatted(this, true); - } - } - - private static _asFormatted(uri: URI, skipEncoding: boolean): string { - - const encoder = !skipEncoding - ? encodeURIComponent2 - : encodeNoop; - - const parts: string[] = []; - - let { scheme, authority, path, query, fragment } = uri; - if (scheme) { - parts.push(scheme, ':'); - } - if (authority || scheme === 'file') { - parts.push('//'); - } - if (authority) { - authority = authority.toLowerCase(); - let idx = authority.indexOf(':'); - if (idx === -1) { - parts.push(encoder(authority)); - } else { - parts.push(encoder(authority.substr(0, idx)), authority.substr(idx)); - } - } - if (path) { - // lower-case windown drive letters in /C:/fff - const m = URI._upperCaseDrive.exec(path); - if (m) { - path = m[1] + m[2].toLowerCase() + path.substr(m[1].length + m[2].length); - } - - // encode every segement but not slashes - // make sure that # and ? are always encoded - // when occurring in paths - otherwise the result - // cannot be parsed back again - let lastIdx = 0; - while (true) { - let idx = path.indexOf(URI._slash, lastIdx); - if (idx === -1) { - parts.push(encoder(path.substring(lastIdx)).replace(/[#?]/, _encode)); - break; - } - parts.push(encoder(path.substring(lastIdx, idx)).replace(/[#?]/, _encode), URI._slash); - lastIdx = idx + 1; - }; - } - if (query) { - parts.push('?', encoder(query)); - } - if (fragment) { - parts.push('#', encoder(fragment)); - } - - return parts.join(URI._empty); - } - - public toJSON(): any { - return { - scheme: this.scheme, - authority: this.authority, - path: this.path, - fsPath: this.fsPath, - query: this.query, - fragment: this.fragment, - external: this.toString(), - $mid: 1 - }; - } -} - -interface UriComponents { - scheme: string; - authority: string; - path: string; - query: string; - fragment: string; -} - -interface UriState extends UriComponents { - $mid: number; - fsPath: string; - external: string; -} From baed6fa95b3dc28be11ccb25de4102ad58c8e34c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 15 Sep 2017 16:39:44 +0200 Subject: [PATCH 131/145] [html] multi folder settings optimizations --- extensions/json/client/src/jsonMain.ts | 78 +++++++++++++------- extensions/json/client/src/utils/hash.ts | 59 +++++++++++++++ extensions/json/server/npm-shrinkwrap.json | 4 +- extensions/json/server/package.json | 2 +- extensions/json/server/src/jsonServerMain.ts | 14 +--- 5 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 extensions/json/client/src/utils/hash.ts diff --git a/extensions/json/client/src/jsonMain.ts b/extensions/json/client/src/jsonMain.ts index 026beb78a74..bb933b6a929 100644 --- a/extensions/json/client/src/jsonMain.ts +++ b/extensions/json/client/src/jsonMain.ts @@ -10,11 +10,11 @@ import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient'; import TelemetryReporter from 'vscode-extension-telemetry'; import { ConfigurationFeature } from 'vscode-languageclient/lib/proposed'; - import { DocumentColorRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; import * as nls from 'vscode-nls'; +import { hash } from './utils/hash'; let localize = nls.loadMessageBundle(); namespace VSCodeContentRequest { @@ -192,8 +192,6 @@ function getSettings(): Settings { let httpSettings = workspace.getConfiguration('http'); let jsonSettings = workspace.getConfiguration('json'); - let schemas = []; - let settings: Settings = { http: { proxy: httpSettings.get('proxy'), @@ -201,41 +199,69 @@ function getSettings(): Settings { }, json: { format: jsonSettings.get('format'), - schemas: schemas, + schemas: [], + } + }; + let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null); + let collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], rootPath?: string, fileMatchPrefix?: string) => { + for (let setting of schemaSettings) { + let url = getSchemaId(setting, rootPath); + if (!url) { + continue; + } + let schemaSetting = schemaSettingsById[url]; + if (!schemaSetting) { + schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] }; + settings.json.schemas.push(schemaSetting); + } + let fileMatches = setting.fileMatch; + if (Array.isArray(fileMatches)) { + if (fileMatchPrefix) { + fileMatches = fileMatches.map(m => fileMatchPrefix + m); + } + schemaSetting.fileMatch.push(...fileMatches); + } + if (setting.schema) { + schemaSetting.schema = setting.schema; + } } }; - let settingsSchemas = jsonSettings.get('schemas'); - if (Array.isArray(settingsSchemas)) { - schemas.push(...settingsSchemas); - } + // merge global and folder settings. Qualify all file matches with the folder path. + let globalSettings = jsonSettings.get('schemas'); + if (Array.isArray(globalSettings)) { + collectSchemaSettings(globalSettings, workspace.rootPath); + } let folders = workspace.workspaceFolders; if (folders) { - folders.forEach(folder => { - let jsonConfig = workspace.getConfiguration('json', folder.uri); - let schemaConfigInfo = jsonConfig.inspect('schemas'); + for (let folder of folders) { + let folderUri = folder.uri; + let schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect('schemas'); let folderSchemas = schemaConfigInfo.workspaceFolderValue; if (Array.isArray(folderSchemas)) { - folderSchemas.forEach(schema => { - let url = schema.url; - if (!url && schema.schema) { - url = schema.schema.id; - } - if (url && url[0] === '.') { - url = Uri.file(path.normalize(path.join(folder.uri.fsPath, url))).toString(); - } - let fileMatch = schema.fileMatch; - if (fileMatch) { - fileMatch = fileMatch.map(m => folder.uri.toString() + '*' + m); - } - schemas.push({ url, fileMatch, schema: schema.schema }); - }); + let folderPath = folderUri.toString(); + if (folderPath[folderPath.length - 1] !== '/') { + folderPath = folderPath + '/'; + } + collectSchemaSettings(folderSchemas, folderUri.fsPath, folderPath + '*'); }; - }); + }; } return settings; } +function getSchemaId(schema: JSONSchemaSettings, rootPath?: string) { + let url = schema.url; + if (!url) { + if (schema.schema) { + url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`; + } + } else if (rootPath && (url[0] === '.' || url[0] === '/')) { + url = Uri.file(path.normalize(path.join(rootPath, url))).toString(); + } + return url; +} + function getPackageInfo(context: ExtensionContext): IPackageInfo { let extensionPackage = require(context.asAbsolutePath('./package.json')); if (extensionPackage) { diff --git a/extensions/json/client/src/utils/hash.ts b/extensions/json/client/src/utils/hash.ts new file mode 100644 index 00000000000..e7149e43cd7 --- /dev/null +++ b/extensions/json/client/src/utils/hash.ts @@ -0,0 +1,59 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +/** + * Return a hash value for an object. + */ +export function hash(obj: any, hashVal = 0): number { + switch (typeof obj) { + case 'object': + if (obj === null) { + return numberHash(349, hashVal); + } else if (Array.isArray(obj)) { + return arrayHash(obj, hashVal); + } + return objectHash(obj, hashVal); + case 'string': + return stringHash(obj, hashVal); + case 'boolean': + return booleanHash(obj, hashVal); + case 'number': + return numberHash(obj, hashVal); + case 'undefined': + return numberHash(obj, 937); + default: + return numberHash(obj, 617); + } +} + +function numberHash(val: number, initialHashVal: number): number { + return (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32 +} + +function booleanHash(b: boolean, initialHashVal: number): number { + return numberHash(b ? 433 : 863, initialHashVal); +} + +function stringHash(s: string, hashVal: number) { + hashVal = numberHash(149417, hashVal); + for (let i = 0, length = s.length; i < length; i++) { + hashVal = numberHash(s.charCodeAt(i), hashVal); + } + return hashVal; +} + +function arrayHash(arr: any[], initialHashVal: number): number { + initialHashVal = numberHash(104579, initialHashVal); + return arr.reduce((hashVal, item) => hash(item, hashVal), initialHashVal); +} + +function objectHash(obj: any, initialHashVal: number): number { + initialHashVal = numberHash(181387, initialHashVal); + return Object.keys(obj).sort().reduce((hashVal, key) => { + hashVal = stringHash(key, hashVal); + return hash(obj[key], hashVal); + }, initialHashVal); +} diff --git a/extensions/json/server/npm-shrinkwrap.json b/extensions/json/server/npm-shrinkwrap.json index 517efec26a3..3bcdb83008a 100644 --- a/extensions/json/server/npm-shrinkwrap.json +++ b/extensions/json/server/npm-shrinkwrap.json @@ -43,9 +43,9 @@ "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz" }, "vscode-json-languageservice": { - "version": "2.0.16", + "version": "2.0.18", "from": "vscode-json-languageservice@next", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-2.0.16.tgz" + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-2.0.18.tgz" }, "vscode-jsonrpc": { "version": "3.3.1", diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json index d1ece9575d2..684e9c35d28 100644 --- a/extensions/json/server/package.json +++ b/extensions/json/server/package.json @@ -10,7 +10,7 @@ "dependencies": { "jsonc-parser": "^1.0.0", "request-light": "^0.2.1", - "vscode-json-languageservice": "^2.0.16", + "vscode-json-languageservice": "^2.0.18", "vscode-languageserver": "3.4.0-next.6", "vscode-languageserver-protocol": "^3.1.1", "vscode-nls": "^2.0.2", diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json/server/src/jsonServerMain.ts index 183d633ab7a..4d1c416c41c 100644 --- a/extensions/json/server/src/jsonServerMain.ts +++ b/extensions/json/server/src/jsonServerMain.ts @@ -13,7 +13,6 @@ import { import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed'; import { xhr, XHRResponse, configure as configureHttpRequests, getErrorStatusDescription } from 'request-light'; -import path = require('path'); import fs = require('fs'); import URI from 'vscode-uri'; import * as URL from 'url'; @@ -54,9 +53,7 @@ let clientDynamicRegisterSupport = false; // After the server has started the client sends an initilize request. The server receives // in the passed params the rootPath of the workspace plus the client capabilities. -let workspaceRoot: URI; connection.onInitialize((params: InitializeParams): InitializeResult => { - workspaceRoot = URI.parse(params.rootPath); function hasClientCapability(...keys: string[]) { let c = params.capabilities; @@ -192,19 +189,12 @@ function updateConfiguration() { } } if (jsonConfigurationSettings) { - jsonConfigurationSettings.forEach(schema => { + jsonConfigurationSettings.forEach((schema, index) => { let uri = schema.url; if (!uri && schema.schema) { - uri = schema.schema.id; - } - if (!uri && schema.fileMatch) { - uri = 'vscode://schemas/custom/' + encodeURIComponent(schema.fileMatch.join('&')); + uri = schema.schema.id || `vscode://schemas/custom/${index}`; } if (uri) { - if (uri[0] === '.' && workspaceRoot) { - // workspace relative path - uri = URI.file(path.normalize(path.join(workspaceRoot.fsPath, uri))).toString(); - } languageSettings.schemas.push({ uri, fileMatch: schema.fileMatch, schema: schema.schema }); } }); From e5aea8641129b7c5cdbd1053ec3874aa3eb2a225 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 17:44:32 +0200 Subject: [PATCH 132/145] splitview: resizeView --- .../base/browser/ui/splitview/splitview2.ts | 38 +++++++-- .../browser/ui/splitview/splitview.test.ts | 77 ++++++++++++------- 2 files changed, 82 insertions(+), 33 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index bee93a2e7cb..7c151960b9a 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -49,7 +49,6 @@ interface ISashItem { interface ISashDragState { start: number; - sizes: number[]; up: number[]; down: number[]; maxUp: number; @@ -181,14 +180,12 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } private onSashStart({ sash, start }: ISashEvent): void { - const i = firstIndex(this.sashItems, item => item.sash === sash); - const sizes = this.viewItems.map(i => i.size); + const index = firstIndex(this.sashItems, item => item.sash === sash); const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - - const up = range(i, -1); - const down = range(i + 1, this.viewItems.length); + const up = range(index, -1); + const down = range(index + 1, this.viewItems.length); const collapsesUp = up.map(i => collapses[i]); const collapsesDown = down.map(i => collapses[i]); @@ -198,7 +195,7 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV const maxUp = Math.min(sum(collapsesUp), sum(expandsDown)); const maxDown = Math.min(sum(expandsUp), sum(collapsesDown)); - this.sashDragState = { start, sizes, up, down, maxUp, maxDown, collapses, expands }; + this.sashDragState = { start, up, down, maxUp, maxDown, collapses, expands }; } private onSashChange({ sash, start, current }: ISashEvent): void { @@ -213,6 +210,33 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV this.viewItems.forEach(viewItem => viewItem.explicitSize = viewItem.size); } + resizeView(index: number, size: number): void { + if (index < 0 || index >= this.viewItems.length) { + return; + } + + const viewItem = this.viewItems[index]; + size = clamp(size, viewItem.view.minimumSize, viewItem.view.maximumSize); + + const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); + const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); + const up = range(index, -1); + const down = range(index + 1, this.viewItems.length); + const collapsesUp = up.map(i => collapses[i]); + const collapsesDown = down.map(i => collapses[i]); + const expandsUp = up.map(i => expands[i]); + const expandsDown = down.map(i => expands[i]); + const maxUp = Math.min(sum(collapsesUp), sum(expandsDown)); + const maxDown = Math.min(sum(expandsUp), sum(collapsesDown)); + const diff = size - viewItem.size; + + if (diff < 0) { + this.expandCollapse(Math.min(-diff, maxUp), collapses, expands, up, down); + } else { + this.expandCollapse(Math.min(diff, maxDown), collapses, expands, down, up); + } + } + private onViewChange(item: IViewItem): void { const size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 8ae66da6710..661efa84f50 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -57,16 +57,14 @@ class TestView implements IView { } } -const TOTAL_SIZE = 200; - suite('Splitview', () => { let container: HTMLElement; setup(() => { container = document.createElement('div'); container.style.position = 'absolute'; - container.style.width = `${TOTAL_SIZE}px`; - container.style.height = `${TOTAL_SIZE}px`; + container.style.width = `${200}px`; + container.style.height = `${200}px`; }); teardown(() => { @@ -79,7 +77,7 @@ suite('Splitview', () => { splitview.dispose(); }); - test('splitview has views as sashes as children', () => { + test('has views as sashes as children', () => { const view1 = new TestView(20, 20); const view2 = new TestView(20, 20); const view3 = new TestView(20, 20); @@ -125,7 +123,7 @@ suite('Splitview', () => { view3.dispose(); }); - test('splitview calls view methods on addView and removeView', () => { + test('calls view methods on addView and removeView', () => { const view = new TestView(20, 20); const splitview = new SplitView(container); @@ -138,8 +136,8 @@ suite('Splitview', () => { splitview.addView(view, 20); assert.equal(view.size, 20, 'view has right size'); - assert(didLayout, 'layout was called'); - assert(didLayout, 'render was called'); + assert(didLayout, 'layout is called'); + assert(didLayout, 'render is called'); splitview.dispose(); layoutDisposable.dispose(); @@ -147,51 +145,78 @@ suite('Splitview', () => { view.dispose(); }); - test('splitview stretches view to viewport', () => { + test('stretches view to viewport', () => { const view = new TestView(20, Number.POSITIVE_INFINITY); const splitview = new SplitView(container); - splitview.layout(TOTAL_SIZE); + splitview.layout(200); splitview.addView(view, 20); - assert.equal(view.size, TOTAL_SIZE, 'view was stretched'); + assert.equal(view.size, 200, 'view is stretched'); - splitview.layout(TOTAL_SIZE); - assert.equal(view.size, TOTAL_SIZE, 'view stayed the same'); + splitview.layout(200); + assert.equal(view.size, 200, 'view stayed the same'); splitview.layout(100); - assert.equal(view.size, 100, 'view was collapsed'); + assert.equal(view.size, 100, 'view is collapsed'); splitview.layout(20); - assert.equal(view.size, 20, 'view was collapsed'); + assert.equal(view.size, 20, 'view is collapsed'); splitview.layout(10); - assert.equal(view.size, 20, 'view was clamped'); + assert.equal(view.size, 20, 'view is clamped'); - splitview.layout(TOTAL_SIZE); - assert.equal(view.size, TOTAL_SIZE, 'view was stretched'); + splitview.layout(200); + assert.equal(view.size, 200, 'view is stretched'); splitview.dispose(); view.dispose(); }); - test('splitview respects preferred sizes with structural changes', () => { + test('respects preferred sizes with structural changes', () => { const view1 = new TestView(20, Number.POSITIVE_INFINITY); const view2 = new TestView(20, Number.POSITIVE_INFINITY); const view3 = new TestView(20, Number.POSITIVE_INFINITY); const splitview = new SplitView(container); - splitview.layout(TOTAL_SIZE); + splitview.layout(200); splitview.addView(view1, 20); - assert.equal(view1.size, TOTAL_SIZE, 'view1 was stretched'); + assert.equal(view1.size, 200, 'view1 is stretched'); splitview.addView(view2, 20); - assert.equal(view1.size, 20, 'view1 size was restored'); - assert.equal(view2.size, TOTAL_SIZE - 20, 'view2 was stretched'); + assert.equal(view1.size, 20, 'view1 size is restored'); + assert.equal(view2.size, 200 - 20, 'view2 is stretched'); splitview.addView(view3, 20); - assert.equal(view1.size, 20, 'view1 size was restored'); - assert.equal(view2.size, 20, 'view2 size was restored'); - assert.equal(view3.size, TOTAL_SIZE - 20 * 2, 'view3 was stretched'); + assert.equal(view1.size, 20, 'view1 size is restored'); + assert.equal(view2.size, 20, 'view2 size is restored'); + assert.equal(view3.size, 160, 'view3 is stretched'); + + splitview.dispose(); + view3.dispose(); + view2.dispose(); + view1.dispose(); + }); + + test('can resize views', () => { + const view1 = new TestView(20, Number.POSITIVE_INFINITY); + const view2 = new TestView(20, Number.POSITIVE_INFINITY); + const view3 = new TestView(20, Number.POSITIVE_INFINITY); + const splitview = new SplitView(container); + splitview.layout(200); + + splitview.addView(view1, 20); + splitview.addView(view2, 20); + splitview.addView(view3, 20); + + assert.equal(view1.size, 20, 'view1 size is the default'); + assert.equal(view2.size, 20, 'view2 size the the default'); + assert.equal(view3.size, 160, 'view3 is stretched'); + + splitview.resizeView(1, 40); + + assert.equal(view1.size, 20, 'view1 is untouched'); + assert.equal(view2.size, 40, 'view2 is stretched'); + assert.equal(view3.size, 140, 'view3 is collapsed'); splitview.dispose(); view3.dispose(); From 806b6c7e88219f8d614ced8102f06ad8dba3f293 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 15 Sep 2017 17:51:58 +0200 Subject: [PATCH 133/145] splitview: more resizeView tests --- .../base/test/browser/ui/splitview/splitview.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 661efa84f50..0dd18c99bf7 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -218,6 +218,18 @@ suite('Splitview', () => { assert.equal(view2.size, 40, 'view2 is stretched'); assert.equal(view3.size, 140, 'view3 is collapsed'); + splitview.resizeView(0, 70); + + assert.equal(view1.size, 70, 'view1 is stretched'); + assert.equal(view2.size, 20, 'view2 is collapsed'); + assert.equal(view3.size, 110, 'view3 is collapsed'); + + splitview.resizeView(2, 20); + + assert.equal(view1.size, 70, 'view1 is stretched'); + assert.equal(view2.size, 110, 'view2 is stretched'); + assert.equal(view3.size, 20, 'view3 is collapsed only to minimum size'); + splitview.dispose(); view3.dispose(); view2.dispose(); From 56ee834f60bd179a89d029e7875da3a4f95d73f2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sat, 16 Sep 2017 15:43:58 +0200 Subject: [PATCH 134/145] splitview: cleaner main algorithm --- .../base/browser/ui/splitview/splitview2.ts | 165 +++++------------- .../browser/ui/splitview/splitview.test.ts | 8 +- 2 files changed, 51 insertions(+), 122 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index 7c151960b9a..854517269a1 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -48,17 +48,11 @@ interface ISashItem { } interface ISashDragState { + index: number; start: number; - up: number[]; - down: number[]; - maxUp: number; - maxDown: number; - collapses: number[]; - expands: number[]; + sizes: number[]; } -const sum = (a: number[]) => a.reduce((a, b) => a + b, 0); - function layoutViewItem(item: IViewItem, orientation: Orientation): void { if (orientation === Orientation.VERTICAL) { item.container.style.height = `${item.size}px`; @@ -160,116 +154,29 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } layout(size: number): void { - if (this.size === size) { - return; - } - - const indexes = range(this.viewItems.length - 1, -1); - const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); - const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - const totalViewsSize = this.viewItems.reduce((r, i) => r + i.size, 0); - const diff = Math.abs(totalViewsSize - size); - - if (size < totalViewsSize) { - this.expandCollapse(Math.min(diff, sum(collapses)), collapses, expands, indexes, []); - } else if (size > totalViewsSize) { - this.expandCollapse(Math.min(diff, sum(expands)), collapses, expands, [], indexes); - } - - this.size = size; + this.resize(this.viewItems.length - 1, size - this.size); + this.size = Math.max(size, this.viewItems.reduce((r, i) => r + i.size, 0)); } private onSashStart({ sash, start }: ISashEvent): void { const index = firstIndex(this.sashItems, item => item.sash === sash); - const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); - const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); + const sizes = this.viewItems.map(i => i.size); - const up = range(index, -1); - const down = range(index + 1, this.viewItems.length); - - const collapsesUp = up.map(i => collapses[i]); - const collapsesDown = down.map(i => collapses[i]); - const expandsUp = up.map(i => expands[i]); - const expandsDown = down.map(i => expands[i]); - - const maxUp = Math.min(sum(collapsesUp), sum(expandsDown)); - const maxDown = Math.min(sum(expandsUp), sum(collapsesDown)); - - this.sashDragState = { start, up, down, maxUp, maxDown, collapses, expands }; + this.sashDragState = { start, index, sizes }; } - private onSashChange({ sash, start, current }: ISashEvent): void { - const diff = current - this.sashDragState.start; - - if (diff < 0) { - this.expandCollapse(Math.min(-diff, this.sashDragState.maxUp), this.sashDragState.collapses, this.sashDragState.expands, this.sashDragState.up, this.sashDragState.down); - } else { - this.expandCollapse(Math.min(diff, this.sashDragState.maxDown), this.sashDragState.collapses, this.sashDragState.expands, this.sashDragState.down, this.sashDragState.up); - } + private onSashChange({ sash, current }: ISashEvent): void { + const { index, start, sizes } = this.sashDragState; + this.resize(index, current - start, sizes); this.viewItems.forEach(viewItem => viewItem.explicitSize = viewItem.size); } - resizeView(index: number, size: number): void { - if (index < 0 || index >= this.viewItems.length) { - return; - } - - const viewItem = this.viewItems[index]; - size = clamp(size, viewItem.view.minimumSize, viewItem.view.maximumSize); - - const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); - const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - const up = range(index, -1); - const down = range(index + 1, this.viewItems.length); - const collapsesUp = up.map(i => collapses[i]); - const collapsesDown = down.map(i => collapses[i]); - const expandsUp = up.map(i => expands[i]); - const expandsDown = down.map(i => expands[i]); - const maxUp = Math.min(sum(collapsesUp), sum(expandsDown)); - const maxDown = Math.min(sum(expandsUp), sum(collapsesDown)); - const diff = size - viewItem.size; - - if (diff < 0) { - this.expandCollapse(Math.min(-diff, maxUp), collapses, expands, up, down); - } else { - this.expandCollapse(Math.min(diff, maxDown), collapses, expands, down, up); - } - } - private onViewChange(item: IViewItem): void { + const index = this.viewItems.indexOf(item); const size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); - if (size === item.size) { - return; - } - - // this.setupAnimation(); - - const index = this.viewItems.indexOf(item); - const diff = Math.abs(size - item.size); - - const up = range(index - 1, -1); - const down = range(index + 1, this.viewItems.length); - const downUp = down.concat(up); - - const collapses = this.viewItems.map(i => Math.max(i.size - i.view.minimumSize, 0)); - const expands = this.viewItems.map(i => Math.max(i.view.maximumSize - i.size, 0)); - - let collapse: number, collapseIndexes: number[], expandIndexes: number[]; - - if (size < item.size) { - collapse = Math.min(downUp.reduce((t, i) => t + expands[i], 0), diff); - collapseIndexes = [index]; - expandIndexes = downUp; - - } else { - collapse = Math.min(downUp.reduce((t, i) => t + collapses[i], 0), diff); - collapseIndexes = downUp; - expandIndexes = [index]; - } - - this.expandCollapse(collapse, collapses, expands, collapseIndexes, expandIndexes); + this.resize(index, size - item.size); } // private setupAnimation(): void { @@ -286,22 +193,44 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // dom.removeClass(this.el, 'animated'); // } - // Main algorithm - private expandCollapse(collapse: number, collapses: number[], expands: number[], collapseIndexes: number[], expandIndexes: number[]): void { - let totalCollapse = collapse; - let totalExpand = totalCollapse; + resizeView(index: number, size: number): void { + if (index < 0 || index >= this.viewItems.length - 1) { + throw new Error('Cant resize view'); + } - collapseIndexes.forEach(i => { - let collapse = Math.min(collapses[i], totalCollapse); - totalCollapse -= collapse; - this.viewItems[i].size -= collapse; - }); + this.resize(index, size - this.viewItems[index].size); + } - expandIndexes.forEach(i => { - let expand = Math.min(expands[i], totalExpand); - totalExpand -= expand; - this.viewItems[i].size += expand; - }); + private resize(index: number, delta: number, sizes = this.viewItems.map(i => i.size)): void { + if (delta === 0 || index < 0 || index >= this.viewItems.length) { + return; + } + + const upIndexes = range(index, -1); + const up = upIndexes.map(i => this.viewItems[i]); + const upSizes = upIndexes.map(i => sizes[i]); + + const downIndexes = range(index + 1, this.viewItems.length); + const down = downIndexes.map(i => this.viewItems[i]); + const downSizes = downIndexes.map(i => sizes[i]); + + for (let i = 0, deltaUp = delta; deltaUp !== 0 && i < up.length; i++) { + const item = up[i]; + const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize); + const viewDelta = size - upSizes[i]; + + deltaUp -= viewDelta; + item.size = size; + } + + for (let i = 0, deltaDown = delta; deltaDown !== 0 && i < down.length; i++) { + const item = down[i]; + const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize); + const viewDelta = size - downSizes[i]; + + deltaDown += viewDelta; + item.size = size; + } this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); this.sashItems.forEach(item => item.sash.layout()); diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 0dd18c99bf7..eb324220b85 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -224,11 +224,11 @@ suite('Splitview', () => { assert.equal(view2.size, 20, 'view2 is collapsed'); assert.equal(view3.size, 110, 'view3 is collapsed'); - splitview.resizeView(2, 20); + assert.throws(() => splitview.resizeView(2, 20)); - assert.equal(view1.size, 70, 'view1 is stretched'); - assert.equal(view2.size, 110, 'view2 is stretched'); - assert.equal(view3.size, 20, 'view3 is collapsed only to minimum size'); + assert.equal(view1.size, 70, 'view1 stays the same'); + assert.equal(view2.size, 20, 'view2 stays the same'); + assert.equal(view3.size, 110, 'view3 stays the same'); splitview.dispose(); view3.dispose(); From 83aa0b1244366dcd82ae944c53edc618c84d081d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 09:18:40 +0200 Subject: [PATCH 135/145] splitview: more tests --- src/vs/base/browser/ui/sash/sash.ts | 4 + .../base/browser/ui/splitview/splitview2.ts | 75 ++++++------- .../browser/ui/splitview/splitview.test.ts | 100 ++++++++++++++++++ 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 338d07b4681..4fdafd509a4 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -268,6 +268,10 @@ export class Sash extends EventEmitter { this.isDisabled = true; } + get enabled(): boolean { + return !this.isDisabled; + } + public dispose(): void { if (this.$e) { this.$e.destroy(); diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index 854517269a1..ed91fe55aa4 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -123,7 +123,7 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } view.render(container, this.orientation); - this.relayout(); + this.relayoutPreferredSizes(); } removeView(index: number): void { @@ -142,15 +142,12 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV sashItem.disposable.dispose(); } - this.relayout(); + this.relayoutPreferredSizes(); } - private relayout(): void { + private relayoutPreferredSizes(): void { this.viewItems.forEach(i => i.size = clamp(i.explicitSize, i.view.minimumSize, i.view.maximumSize)); - - const previousSize = this.size; - this.size = this.viewItems.reduce((r, i) => r + i.size, 0); - this.layout(previousSize); + this.relayout(); } layout(size: number): void { @@ -158,6 +155,12 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV this.size = Math.max(size, this.viewItems.reduce((r, i) => r + i.size, 0)); } + private relayout(): void { + const previousSize = this.size; + this.size = this.viewItems.reduce((r, i) => r + i.size, 0); + this.layout(previousSize); + } + private onSashStart({ sash, start }: ISashEvent): void { const index = firstIndex(this.sashItems, item => item.sash === sash); const sizes = this.viewItems.map(i => i.size); @@ -173,10 +176,8 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } private onViewChange(item: IViewItem): void { - const index = this.viewItems.indexOf(item); - const size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); - - this.resize(index, size - item.size); + item.size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); + this.relayout(); } // private setupAnimation(): void { @@ -202,39 +203,41 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV } private resize(index: number, delta: number, sizes = this.viewItems.map(i => i.size)): void { - if (delta === 0 || index < 0 || index >= this.viewItems.length) { + if (index < 0 || index >= this.viewItems.length) { return; } - const upIndexes = range(index, -1); - const up = upIndexes.map(i => this.viewItems[i]); - const upSizes = upIndexes.map(i => sizes[i]); + if (delta !== 0) { + const upIndexes = range(index, -1); + const up = upIndexes.map(i => this.viewItems[i]); + const upSizes = upIndexes.map(i => sizes[i]); - const downIndexes = range(index + 1, this.viewItems.length); - const down = downIndexes.map(i => this.viewItems[i]); - const downSizes = downIndexes.map(i => sizes[i]); + const downIndexes = range(index + 1, this.viewItems.length); + const down = downIndexes.map(i => this.viewItems[i]); + const downSizes = downIndexes.map(i => sizes[i]); - for (let i = 0, deltaUp = delta; deltaUp !== 0 && i < up.length; i++) { - const item = up[i]; - const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize); - const viewDelta = size - upSizes[i]; + for (let i = 0, deltaUp = delta; deltaUp !== 0 && i < up.length; i++) { + const item = up[i]; + const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize); + const viewDelta = size - upSizes[i]; - deltaUp -= viewDelta; - item.size = size; + deltaUp -= viewDelta; + item.size = size; + } + + for (let i = 0, deltaDown = delta; deltaDown !== 0 && i < down.length; i++) { + const item = down[i]; + const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize); + const viewDelta = size - downSizes[i]; + + deltaDown += viewDelta; + item.size = size; + } + + this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); + this.sashItems.forEach(item => item.sash.layout()); } - for (let i = 0, deltaDown = delta; deltaDown !== 0 && i < down.length; i++) { - const item = down[i]; - const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize); - const viewDelta = size - downSizes[i]; - - deltaDown += viewDelta; - item.size = size; - } - - this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); - this.sashItems.forEach(item => item.sash.layout()); - // Update sashes enablement let previous = false; const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous); diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index eb324220b85..be73ee96d46 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -6,6 +6,7 @@ import * as assert from 'assert'; import { Emitter } from 'vs/base/common/event'; import { SplitView, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview2'; +import { Sash } from 'vs/base/browser/ui/sash/sash'; class TestView implements IView { @@ -57,6 +58,10 @@ class TestView implements IView { } } +function getSashes(splitview: SplitView): Sash[] { + return (splitview as any).sashItems.map(i => i.sash) as Sash[]; +} + suite('Splitview', () => { let container: HTMLElement; @@ -235,4 +240,99 @@ suite('Splitview', () => { view2.dispose(); view1.dispose(); }); + + test('reacts to view changes', () => { + const view1 = new TestView(20, Number.POSITIVE_INFINITY); + const view2 = new TestView(20, Number.POSITIVE_INFINITY); + const view3 = new TestView(20, Number.POSITIVE_INFINITY); + const splitview = new SplitView(container); + splitview.layout(200); + + splitview.addView(view1, 20); + splitview.addView(view2, 20); + splitview.addView(view3, 20); + + assert.equal(view1.size, 20, 'view1 size is restored'); + assert.equal(view2.size, 20, 'view2 size is restored'); + assert.equal(view3.size, 160, 'view3 is stretched'); + + view3.maximumSize = 20; + + assert.equal(view1.size, 20, 'view1 stays the same'); + assert.equal(view2.size, 160, 'view2 is stretched'); + assert.equal(view3.size, 20, 'view3 is collapsed'); + + view2.maximumSize = 40; + + assert.equal(view1.size, 140, 'view1 is stretched'); + assert.equal(view2.size, 40, 'view2 is collapsed'); + assert.equal(view3.size, 20, 'view3 is collapsed'); + + view3.maximumSize = 200; + + assert.equal(view1.size, 140, 'view1 stays the same'); + assert.equal(view2.size, 40, 'view2 stays the same'); + assert.equal(view3.size, 20, 'view3 stays the same'); + + view3.minimumSize = 100; + + assert.equal(view1.size, 80, 'view1 is collapsed'); + assert.equal(view2.size, 20, 'view2 stays the same'); + assert.equal(view3.size, 100, 'view3 is stretched'); + + splitview.dispose(); + view3.dispose(); + view2.dispose(); + view1.dispose(); + }); + + test('sashes are properly enabled/disabled', () => { + const view1 = new TestView(20, Number.POSITIVE_INFINITY); + const view2 = new TestView(20, Number.POSITIVE_INFINITY); + const view3 = new TestView(20, Number.POSITIVE_INFINITY); + const splitview = new SplitView(container); + splitview.layout(200); + + splitview.addView(view1, 20); + splitview.addView(view2, 20); + splitview.addView(view3, 20); + + let sashes = getSashes(splitview); + assert.equal(sashes.length, 2, 'there are two sashes'); + assert.equal(sashes[0].enabled, true, 'first sash is enabled'); + assert.equal(sashes[1].enabled, true, 'second sash is enabled'); + + splitview.layout(60); + assert.equal(sashes[0].enabled, false, 'first sash is disabled'); + assert.equal(sashes[1].enabled, false, 'second sash is disabled'); + + splitview.layout(20); + assert.equal(sashes[0].enabled, false, 'first sash is disabled'); + assert.equal(sashes[1].enabled, false, 'second sash is disabled'); + + splitview.layout(200); + assert.equal(sashes[0].enabled, true, 'first sash is enabled'); + assert.equal(sashes[1].enabled, true, 'second sash is enabled'); + + view1.maximumSize = 20; + assert.equal(sashes[0].enabled, false, 'first sash is disabled'); + assert.equal(sashes[1].enabled, true, 'second sash is enabled'); + + view2.maximumSize = 20; + assert.equal(sashes[0].enabled, false, 'first sash is disabled'); + assert.equal(sashes[1].enabled, false, 'second sash is disabled'); + + view1.maximumSize = 300; + assert.equal(sashes[0].enabled, true, 'first sash is enabled'); + assert.equal(sashes[1].enabled, true, 'second sash is enabled'); + + view2.maximumSize = 200; + assert.equal(sashes[0].enabled, true, 'first sash is enabled'); + assert.equal(sashes[1].enabled, true, 'second sash is enabled'); + + splitview.dispose(); + view3.dispose(); + view2.dispose(); + view1.dispose(); + }); }); \ No newline at end of file From c2cc2066afb4a3ad9109d65b7007b2803aa47f57 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 09:24:18 +0200 Subject: [PATCH 136/145] splitview: animation --- .../base/browser/ui/splitview/splitview2.ts | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index ed91fe55aa4..bfa0ef0eabb 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -71,6 +71,7 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV private viewItems: IViewItem[] = []; private sashItems: ISashItem[] = []; private sashDragState: ISashDragState; + private animationTimeout: number; get length(): number { return this.viewItems.length; @@ -150,17 +151,17 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV this.relayout(); } - layout(size: number): void { - this.resize(this.viewItems.length - 1, size - this.size); - this.size = Math.max(size, this.viewItems.reduce((r, i) => r + i.size, 0)); - } - private relayout(): void { const previousSize = this.size; this.size = this.viewItems.reduce((r, i) => r + i.size, 0); this.layout(previousSize); } + layout(size: number): void { + this.resize(this.viewItems.length - 1, size - this.size); + this.size = Math.max(size, this.viewItems.reduce((r, i) => r + i.size, 0)); + } + private onSashStart({ sash, start }: ISashEvent): void { const index = firstIndex(this.sashItems, item => item.sash === sash); const sizes = this.viewItems.map(i => i.size); @@ -177,22 +178,24 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV private onViewChange(item: IViewItem): void { item.size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); + this.setupAnimation(); this.relayout(); } - // private setupAnimation(): void { - // if (types.isNumber(this.animationTimeout)) { - // window.clearTimeout(this.animationTimeout); - // } + // TODO@Joao: move this to panelview + private setupAnimation(): void { + // Setup animation + if (types.isNumber(this.animationTimeout)) { + window.clearTimeout(this.animationTimeout); + } - // dom.addClass(this.el, 'animated'); - // this.animationTimeout = window.setTimeout(() => this.clearAnimation(), 200); - // } + dom.addClass(this.el, 'animated'); - // private clearAnimation(): void { - // this.animationTimeout = null; - // dom.removeClass(this.el, 'animated'); - // } + this.animationTimeout = window.setTimeout(() => { + this.animationTimeout = null; + dom.removeClass(this.el, 'animated'); + }, 200); + } resizeView(index: number, size: number): void { if (index < 0 || index >= this.viewItems.length - 1) { From ac47a3329140548935e74ebbfe1af8554bb53982 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 09:32:20 +0200 Subject: [PATCH 137/145] splitview: clean interface --- src/vs/base/browser/ui/splitview/splitview2.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index bfa0ef0eabb..053f144cf51 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -12,7 +12,7 @@ import types = require('vs/base/common/types'); import dom = require('vs/base/browser/dom'); import { clamp } from 'vs/base/common/numbers'; import { range, firstIndex } from 'vs/base/common/arrays'; -import { Sash, IVerticalSashLayoutProvider, IHorizontalSashLayoutProvider, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; +import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash'; export interface IOptions { @@ -63,7 +63,7 @@ function layoutViewItem(item: IViewItem, orientation: Orientation): void { item.view.layout(item.size, orientation); } -export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IVerticalSashLayoutProvider { +export class SplitView implements IDisposable { private orientation: Orientation; private el: HTMLElement; @@ -108,7 +108,8 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV // Add sash if (this.viewItems.length > 1) { const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; - const sash = new Sash(this.el, this, { orientation }); + const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) }; + const sash = new Sash(this.el, layoutProvider, { orientation }); const sashEventMapper = this.orientation === Orientation.VERTICAL ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); @@ -264,14 +265,6 @@ export class SplitView implements IDisposable, IHorizontalSashLayoutProvider, IV }); } - getVerticalSashLeft(sash: Sash): number { - return this.getSashPosition(sash); - } - - getHorizontalSashTop(sash: Sash): number { - return this.getSashPosition(sash); - } - private getSashPosition(sash: Sash): number { let position = 0; From 1bf3150b67c7b46240bf5991c4856630988cdf6f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 10:05:21 +0200 Subject: [PATCH 138/145] panelview: first steps --- src/vs/base/browser/ui/splitview/panelview.ts | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/vs/base/browser/ui/splitview/panelview.ts diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts new file mode 100644 index 00000000000..1603a64e3a9 --- /dev/null +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -0,0 +1,175 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import 'vs/css!./splitview'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import Event, { Emitter, chain } from 'vs/base/common/event'; +import { domEvent } from 'vs/base/browser/event'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode } from 'vs/base/common/keyCodes'; +import { $, append, toggleClass } from 'vs/base/browser/dom'; +import { IOptions, SplitView, IView } from './splitview2'; +export { IOptions } from './splitview2'; + +enum PanelState { + Expanded, + Collapsed +} + +export interface IPanelOptions { + ariaHeaderLabel?: string; + minimumBodySize?: number; + maximumBodySize?: number; + collapsed?: boolean; +} + +export abstract class Panel implements IView { + + private static HEADER_SIZE = 22; + + private state: PanelState = PanelState.Expanded; + private _onDidChange = new Emitter(); + private _minimumBodySize: number; + private _maximumBodySize: number; + private ariaHeaderLabel: string; + private header: HTMLElement; + private body: HTMLElement; + private disposables: IDisposable[] = []; + + get minimumBodySize(): number { + return this._minimumBodySize; + } + + set minimumBodySize(size: number) { + this._minimumBodySize = size; + this._onDidChange.fire(); + } + + get maximumBodySize(): number { + return this._maximumBodySize; + } + + set maximumBodySize(size: number) { + this._maximumBodySize = size; + this._onDidChange.fire(); + } + + get minimumSize(): number { + return Panel.HEADER_SIZE + (this.state === PanelState.Collapsed ? 0 : this._minimumBodySize); + } + + get maximumSize(): number { + return Panel.HEADER_SIZE + (this.state === PanelState.Collapsed ? 0 : this._maximumBodySize); + } + + readonly onDidChange: Event = this._onDidChange.event; + + constructor(options: IPanelOptions = {}) { + this.ariaHeaderLabel = options.ariaHeaderLabel || ''; + this._minimumBodySize = typeof options.minimumBodySize === 'number' ? options.minimumBodySize : 44; + this._maximumBodySize = typeof options.maximumBodySize === 'number' ? options.maximumBodySize : Number.POSITIVE_INFINITY; + this.state = options.collapsed ? PanelState.Collapsed : PanelState.Expanded; + } + + render(container: HTMLElement): void { + const panel = append(container, $('.panel')); + const header = append(panel, $('.panel-header')); + + header.setAttribute('tabindex', '0'); + header.setAttribute('role', 'toolbar'); + header.setAttribute('aria-label', this.ariaHeaderLabel); + this.renderHeader(); + + const onHeaderKeyDown = chain(domEvent(header, 'keydown')).map(e => new StandardKeyboardEvent(e)); + + onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) + .event(this.toggleExpansion, this, this.disposables); + + onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) + .event(this.collapse, this, this.disposables); + + onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) + .event(this.expand, this, this.disposables); + + // TODO@Joao move this down to panelview + // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.UpArrow) + // .event(focusPrevious, this, this.disposables); + + // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.DownArrow) + // .event(focusNext, this, this.disposables); + + this.body = append(panel, $('.panel-body')); + } + + private renderHeader(): void { + toggleClass(this.header, 'expanded', this.state === PanelState.Expanded); + this.header.setAttribute('aria-expanded', String(this.state === PanelState.Expanded)); + } + + layout(size: number): void { + this.layoutBody(size - Panel.HEADER_SIZE); + } + + focus(): void { + + } + + toggleExpansion(): void { + if (this.state === PanelState.Expanded) { + return this.collapse(); + } else { + return this.expand(); + } + } + + expand(): void { + if (this.state === PanelState.Expanded) { + return; + } + + this.renderHeader(); + } + + collapse(): void { + if (this.state === PanelState.Collapsed) { + return; + } + + this.renderHeader(); + } + + protected abstract renderBody(container: HTMLElement): void; + protected abstract layoutBody(size: number): void; + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + +export class PanelView implements IDisposable { + + private splitview: SplitView; + + constructor(private container: HTMLElement, options?: IOptions) { + this.splitview = new SplitView(container, options); + } + + addPanel(): void { + + } + + removePanel(): void { + + } + + layout(size: number): void { + + } + + dispose(): void { + } +} From 41dd25755f2c6d8b522cd69e5c8a3c87d9027fc2 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 16:15:12 +0200 Subject: [PATCH 139/145] panelview: animation, collapse states --- src/vs/base/browser/ui/splitview/panelview.ts | 77 +++++++++++++++---- .../base/browser/ui/splitview/splitview2.ts | 21 +---- 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 1603a64e3a9..157be8261dc 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -11,9 +11,9 @@ import Event, { Emitter, chain } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { $, append, toggleClass } from 'vs/base/browser/dom'; -import { IOptions, SplitView, IView } from './splitview2'; -export { IOptions } from './splitview2'; +import { $, append, addClass, removeClass, toggleClass } from 'vs/base/browser/dom'; +import { firstIndex } from 'vs/base/common/arrays'; +import { SplitView, IView } from './splitview2'; enum PanelState { Expanded, @@ -37,7 +37,6 @@ export abstract class Panel implements IView { private _maximumBodySize: number; private ariaHeaderLabel: string; private header: HTMLElement; - private body: HTMLElement; private disposables: IDisposable[] = []; get minimumBodySize(): number { @@ -84,7 +83,8 @@ export abstract class Panel implements IView { header.setAttribute('aria-label', this.ariaHeaderLabel); this.renderHeader(); - const onHeaderKeyDown = chain(domEvent(header, 'keydown')).map(e => new StandardKeyboardEvent(e)); + const onHeaderKeyDown = chain(domEvent(header, 'keydown')) + .map(e => new StandardKeyboardEvent(e)); onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) .event(this.toggleExpansion, this, this.disposables); @@ -95,6 +95,8 @@ export abstract class Panel implements IView { onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) .event(this.expand, this, this.disposables); + domEvent(header, 'click')(this.toggleExpansion, this, this.disposables); + // TODO@Joao move this down to panelview // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.UpArrow) // .event(focusPrevious, this, this.disposables); @@ -102,12 +104,8 @@ export abstract class Panel implements IView { // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.DownArrow) // .event(focusNext, this, this.disposables); - this.body = append(panel, $('.panel-body')); - } - - private renderHeader(): void { - toggleClass(this.header, 'expanded', this.state === PanelState.Expanded); - this.header.setAttribute('aria-expanded', String(this.state === PanelState.Expanded)); + const body = append(panel, $('.panel-body')); + this.renderBody(body); } layout(size: number): void { @@ -115,7 +113,7 @@ export abstract class Panel implements IView { } focus(): void { - + // TODO@joao what to do } toggleExpansion(): void { @@ -132,6 +130,7 @@ export abstract class Panel implements IView { } this.renderHeader(); + this._onDidChange.fire(); } collapse(): void { @@ -140,6 +139,12 @@ export abstract class Panel implements IView { } this.renderHeader(); + this._onDidChange.fire(); + } + + private renderHeader(): void { + toggleClass(this.header, 'expanded', this.state === PanelState.Expanded); + this.header.setAttribute('aria-expanded', String(this.state === PanelState.Expanded)); } protected abstract renderBody(container: HTMLElement): void; @@ -150,26 +155,66 @@ export abstract class Panel implements IView { } } +export class IPanelViewOptions { + dnd?: boolean; +} + +interface IPanelItem { + panel: Panel; + disposable: IDisposable; +} + export class PanelView implements IDisposable { + private el: HTMLElement; + private panelItems: IPanelItem[] = []; private splitview: SplitView; + private animationTimer: number | null = null; - constructor(private container: HTMLElement, options?: IOptions) { - this.splitview = new SplitView(container, options); + constructor(private container: HTMLElement, options?: IPanelViewOptions) { + this.el = append(container, $('.monaco-panel-view')); + this.splitview = new SplitView(container); } - addPanel(): void { + addPanel(panel: Panel, size: number, index = this.splitview.length): void { + const disposable = panel.onDidChange(this.setupAnimation, this); + const panelItem = { panel, disposable }; + this.panelItems.splice(index, 0, panelItem); + this.splitview.addView(panel, size, index); } - removePanel(): void { + removePanel(panel: Panel): void { + const index = firstIndex(this.panelItems, item => item.panel === panel); + if (index === -1) { + return; + } + + this.splitview.removeView(index); + const panelItem = this.panelItems.splice(index, 1)[0]; + panelItem.disposable.dispose(); } layout(size: number): void { + this.splitview.layout(size); + } + // TODO@Joao: move this to panelview + private setupAnimation(): void { + if (typeof this.animationTimer === 'number') { + window.clearTimeout(this.animationTimer); + } + + addClass(this.el, 'animated'); + + this.animationTimer = window.setTimeout(() => { + this.animationTimer = null; + removeClass(this.el, 'animated'); + }, 200); } dispose(): void { + } } diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index 053f144cf51..8385bc55cab 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -15,7 +15,7 @@ import { range, firstIndex } from 'vs/base/common/arrays'; import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash'; -export interface IOptions { +export interface ISplitViewOptions { orientation?: Orientation; // default Orientation.VERTICAL } @@ -71,13 +71,12 @@ export class SplitView implements IDisposable { private viewItems: IViewItem[] = []; private sashItems: ISashItem[] = []; private sashDragState: ISashDragState; - private animationTimeout: number; get length(): number { return this.viewItems.length; } - constructor(private container: HTMLElement, options?: IOptions) { + constructor(private container: HTMLElement, options?: ISplitViewOptions) { options = options || {}; this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation; @@ -179,25 +178,9 @@ export class SplitView implements IDisposable { private onViewChange(item: IViewItem): void { item.size = clamp(item.size, item.view.minimumSize, item.view.maximumSize); - this.setupAnimation(); this.relayout(); } - // TODO@Joao: move this to panelview - private setupAnimation(): void { - // Setup animation - if (types.isNumber(this.animationTimeout)) { - window.clearTimeout(this.animationTimeout); - } - - dom.addClass(this.el, 'animated'); - - this.animationTimeout = window.setTimeout(() => { - this.animationTimeout = null; - dom.removeClass(this.el, 'animated'); - }, 200); - } - resizeView(index: number, size: number): void { if (index < 0 || index >= this.viewItems.length - 1) { throw new Error('Cant resize view'); From 18715a07e379d18310d6464cda0ee80f58cff446 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 16:23:47 +0200 Subject: [PATCH 140/145] splitview: moveView --- .../base/browser/ui/splitview/splitview2.ts | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index 8385bc55cab..f7567f763a9 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -146,6 +146,24 @@ export class SplitView implements IDisposable { this.relayoutPreferredSizes(); } + moveView(from: number, to: number): void { + if (from < 0 || from >= this.viewItems.length) { + return; + } + + if (to < 0 || to >= this.viewItems.length) { + return; + } + + if (from === to) { + return; + } + + const viewItem = this.viewItems.splice(from, 1)[0]; + this.viewItems.splice(to, 0, viewItem); + this.render(); + } + private relayoutPreferredSizes(): void { this.viewItems.forEach(i => i.size = clamp(i.explicitSize, i.view.minimumSize, i.view.maximumSize)); this.relayout(); @@ -220,11 +238,15 @@ export class SplitView implements IDisposable { deltaDown += viewDelta; item.size = size; } - - this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); - this.sashItems.forEach(item => item.sash.layout()); } + this.render(); + } + + private render(): void { + this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); + this.sashItems.forEach(item => item.sash.layout()); + // Update sashes enablement let previous = false; const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous); From d522fb67cf7e3a3b28a9b657a46db738c260864e Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 16:59:11 +0200 Subject: [PATCH 141/145] panelview: dnd --- src/vs/base/browser/ui/splitview/panelview.ts | 120 +++++++++++++++++- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 157be8261dc..97c8e20274c 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -6,13 +6,14 @@ 'use strict'; import 'vs/css!./splitview'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import Event, { Emitter, chain } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { $, append, addClass, removeClass, toggleClass } from 'vs/base/browser/dom'; import { firstIndex } from 'vs/base/common/arrays'; +import { Color } from 'vs/base/common/color'; import { SplitView, IView } from './splitview2'; enum PanelState { @@ -36,7 +37,7 @@ export abstract class Panel implements IView { private _minimumBodySize: number; private _maximumBodySize: number; private ariaHeaderLabel: string; - private header: HTMLElement; + readonly header: HTMLElement; private disposables: IDisposable[] = []; get minimumBodySize(): number { @@ -155,6 +156,95 @@ export abstract class Panel implements IView { } } +interface IDndContext { + draggable: PanelDraggable | null; +} + +class PanelDraggable implements IDisposable { + + // see https://github.com/Microsoft/vscode/issues/14470 + private dragOverCounter = 0; + private dropBackground: Color | undefined; + private disposables: IDisposable[] = []; + + private _onDidDrop = new Emitter<{ from: Panel, to: Panel }>(); + readonly onDidDrop = this._onDidDrop.event; + + constructor(private panel: Panel, private context: IDndContext) { + domEvent(panel.header, 'dragstart')(this.onDragStart, this, this.disposables); + domEvent(panel.header, 'dragenter')(this.onDragEnter, this, this.disposables); + domEvent(panel.header, 'dragleave')(this.onDragLeave, this, this.disposables); + domEvent(panel.header, 'dragend')(this.onDragEnd, this, this.disposables); + domEvent(panel.header, 'drop')(this.onDrop, this, this.disposables); + } + + private onDragStart(e: DragEvent): void { + e.dataTransfer.effectAllowed = 'move'; + + const dragImage = append(document.body, $('.monaco-panel-drag-image', {}, this.panel.header.textContent)); + e.dataTransfer.setDragImage(dragImage, -10, -10); + setTimeout(() => document.body.removeChild(dragImage), 0); + + this.context.draggable = this; + } + + private onDragEnter(e: DragEvent): void { + if (!this.context.draggable || this.context.draggable === this) { + return; + } + + this.dragOverCounter++; + this.renderHeader(); + } + + private onDragLeave(e: DragEvent): void { + if (!this.context.draggable || this.context.draggable === this) { + return; + } + + this.dragOverCounter--; + + if (this.dragOverCounter === 0) { + this.renderHeader(); + } + } + + private onDragEnd(e: DragEvent): void { + if (!this.context.draggable) { + return; + } + + this.dragOverCounter = 0; + this.renderHeader(); + this.context.draggable = null; + } + + private onDrop(e: DragEvent): void { + if (!this.context.draggable) { + return; + } + + this.dragOverCounter = 0; + this.renderHeader(); + + if (this.context.draggable !== this) { + this._onDidDrop.fire({ from: this.context.draggable.panel, to: this.panel }); + } + + this.context.draggable = null; + } + + private renderHeader(): void { + this.panel.header.style.backgroundColor = this.dragOverCounter === 0 && this.dropBackground + ? this.dropBackground.toString() + : null; + } + + dispose(): void { + this.disposables = dispose(this.disposables); + } +} + export class IPanelViewOptions { dnd?: boolean; } @@ -166,19 +256,30 @@ interface IPanelItem { export class PanelView implements IDisposable { + private dnd: boolean; + private dndContext: IDndContext = { draggable: null }; private el: HTMLElement; private panelItems: IPanelItem[] = []; private splitview: SplitView; private animationTimer: number | null = null; constructor(private container: HTMLElement, options?: IPanelViewOptions) { + this.dnd = !!options.dnd; this.el = append(container, $('.monaco-panel-view')); this.splitview = new SplitView(container); } addPanel(panel: Panel, size: number, index = this.splitview.length): void { - const disposable = panel.onDidChange(this.setupAnimation, this); - const panelItem = { panel, disposable }; + const disposables: IDisposable[] = []; + panel.onDidChange(this.setupAnimation, this, disposables); + + if (this.dnd) { + const draggable = new PanelDraggable(panel, this.dndContext); + disposables.push(draggable); + draggable.onDidDrop(({ from, to }) => this.movePanel(from, to), null, disposables); + } + + const panelItem = { panel, disposable: combinedDisposable(disposables) }; this.panelItems.splice(index, 0, panelItem); this.splitview.addView(panel, size, index); @@ -196,6 +297,17 @@ export class PanelView implements IDisposable { panelItem.disposable.dispose(); } + movePanel(from: Panel, to: Panel): void { + const fromIndex = firstIndex(this.panelItems, item => item.panel === from); + const toIndex = firstIndex(this.panelItems, item => item.panel === to); + + if (fromIndex === -1 || toIndex === -1) { + return; + } + + this.splitview.moveView(fromIndex, toIndex); + } + layout(size: number): void { this.splitview.layout(size); } From 67a7154be69857cb5010cdcae150c81800df1958 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 17:05:44 +0200 Subject: [PATCH 142/145] panelview: dnd background color --- src/vs/base/browser/ui/splitview/panelview.ts | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 97c8e20274c..2715c1cc0b3 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -13,7 +13,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { $, append, addClass, removeClass, toggleClass } from 'vs/base/browser/dom'; import { firstIndex } from 'vs/base/common/arrays'; -import { Color } from 'vs/base/common/color'; +import { Color, RGBA } from 'vs/base/common/color'; import { SplitView, IView } from './splitview2'; enum PanelState { @@ -28,6 +28,10 @@ export interface IPanelOptions { collapsed?: boolean; } +export interface IPanelStyles { + dropBackground?: Color; +} + export abstract class Panel implements IView { private static HEADER_SIZE = 22; @@ -157,14 +161,16 @@ export abstract class Panel implements IView { } interface IDndContext { + dropBackground: Color | undefined; draggable: PanelDraggable | null; } class PanelDraggable implements IDisposable { + private static DefaultDragOverBackgroundColor = new Color(new RGBA(128, 128, 128, 0.5)); + // see https://github.com/Microsoft/vscode/issues/14470 private dragOverCounter = 0; - private dropBackground: Color | undefined; private disposables: IDisposable[] = []; private _onDidDrop = new Emitter<{ from: Panel, to: Panel }>(); @@ -235,9 +241,13 @@ class PanelDraggable implements IDisposable { } private renderHeader(): void { - this.panel.header.style.backgroundColor = this.dragOverCounter === 0 && this.dropBackground - ? this.dropBackground.toString() - : null; + let backgroundColor: string = null; + + if (this.dragOverCounter > 0) { + backgroundColor = (this.context.dropBackground || PanelDraggable.DefaultDragOverBackgroundColor).toString(); + } + + this.panel.header.style.backgroundColor = backgroundColor; } dispose(): void { @@ -257,7 +267,7 @@ interface IPanelItem { export class PanelView implements IDisposable { private dnd: boolean; - private dndContext: IDndContext = { draggable: null }; + private dndContext: IDndContext = { dropBackground: undefined, draggable: null }; private el: HTMLElement; private panelItems: IPanelItem[] = []; private splitview: SplitView; @@ -312,7 +322,10 @@ export class PanelView implements IDisposable { this.splitview.layout(size); } - // TODO@Joao: move this to panelview + style(styles: IPanelStyles): void { + this.dndContext.dropBackground = styles.dropBackground; + } + private setupAnimation(): void { if (typeof this.animationTimer === 'number') { window.clearTimeout(this.animationTimer); From 601f2c904899b95a091fbb63a1fffbbff692faae Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Sun, 17 Sep 2017 21:34:25 +0200 Subject: [PATCH 143/145] splitview: :lipstick: --- src/vs/base/browser/ui/splitview/splitview2.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/splitview2.ts b/src/vs/base/browser/ui/splitview/splitview2.ts index f7567f763a9..dceae97209f 100644 --- a/src/vs/base/browser/ui/splitview/splitview2.ts +++ b/src/vs/base/browser/ui/splitview/splitview2.ts @@ -76,8 +76,7 @@ export class SplitView implements IDisposable { return this.viewItems.length; } - constructor(private container: HTMLElement, options?: ISplitViewOptions) { - options = options || {}; + constructor(private container: HTMLElement, options: ISplitViewOptions = {}) { this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation; this.el = document.createElement('div'); @@ -161,7 +160,7 @@ export class SplitView implements IDisposable { const viewItem = this.viewItems.splice(from, 1)[0]; this.viewItems.splice(to, 0, viewItem); - this.render(); + this.layoutViews(); } private relayoutPreferredSizes(): void { @@ -240,10 +239,10 @@ export class SplitView implements IDisposable { } } - this.render(); + this.layoutViews(); } - private render(): void { + private layoutViews(): void { this.viewItems.forEach(item => layoutViewItem(item, this.orientation)); this.sashItems.forEach(item => item.sash.layout()); From 3233f1aae075c2c1f8fa61c3a7882753f5441ca0 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 18 Sep 2017 10:45:46 +0200 Subject: [PATCH 144/145] panelview: hide/show headers --- src/vs/base/browser/ui/splitview/panelview.ts | 105 ++++++++++-------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 2715c1cc0b3..7bd8c7af6aa 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -16,16 +16,11 @@ import { firstIndex } from 'vs/base/common/arrays'; import { Color, RGBA } from 'vs/base/common/color'; import { SplitView, IView } from './splitview2'; -enum PanelState { - Expanded, - Collapsed -} - export interface IPanelOptions { ariaHeaderLabel?: string; minimumBodySize?: number; maximumBodySize?: number; - collapsed?: boolean; + expanded?: boolean; } export interface IPanelStyles { @@ -36,7 +31,8 @@ export abstract class Panel implements IView { private static HEADER_SIZE = 22; - private state: PanelState = PanelState.Expanded; + private _expanded: boolean; + private _headerVisible: boolean; private _onDidChange = new Emitter(); private _minimumBodySize: number; private _maximumBodySize: number; @@ -63,20 +59,56 @@ export abstract class Panel implements IView { } get minimumSize(): number { - return Panel.HEADER_SIZE + (this.state === PanelState.Collapsed ? 0 : this._minimumBodySize); + const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; + const expanded = !this.headerVisible || this.expanded; + const minimumBodySize = expanded ? this._minimumBodySize : 0; + + return headerSize + minimumBodySize; } get maximumSize(): number { - return Panel.HEADER_SIZE + (this.state === PanelState.Collapsed ? 0 : this._maximumBodySize); + const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; + const expanded = !this.headerVisible || this.expanded; + const maximumBodySize = expanded ? this._maximumBodySize : 0; + + return headerSize + maximumBodySize; } readonly onDidChange: Event = this._onDidChange.event; constructor(options: IPanelOptions = {}) { + this._expanded = typeof options.expanded === 'undefined' ? true : !!options.expanded; this.ariaHeaderLabel = options.ariaHeaderLabel || ''; this._minimumBodySize = typeof options.minimumBodySize === 'number' ? options.minimumBodySize : 44; this._maximumBodySize = typeof options.maximumBodySize === 'number' ? options.maximumBodySize : Number.POSITIVE_INFINITY; - this.state = options.collapsed ? PanelState.Collapsed : PanelState.Expanded; + } + + get expanded(): boolean { + return this._expanded; + } + + set expanded(expanded: boolean) { + if (this._expanded === !!expanded) { + return; + } + + this._expanded = !!expanded; + this.renderHeader(); + this._onDidChange.fire(); + } + + get headerVisible(): boolean { + return this._headerVisible; + } + + set headerVisible(visible: boolean) { + if (this._headerVisible === !!visible) { + return; + } + + this._headerVisible = !!visible; + this.renderHeader(); + this._onDidChange.fire(); } render(container: HTMLElement): void { @@ -92,15 +124,16 @@ export abstract class Panel implements IView { .map(e => new StandardKeyboardEvent(e)); onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) - .event(this.toggleExpansion, this, this.disposables); + .event(() => this.expanded = !this.expanded, null, this.disposables); onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) - .event(this.collapse, this, this.disposables); + .event(() => this.expanded = false, null, this.disposables); onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) - .event(this.expand, this, this.disposables); + .event(() => this.expanded = true, null, this.disposables); - domEvent(header, 'click')(this.toggleExpansion, this, this.disposables); + domEvent(header, 'click') + (() => this.expanded = !this.expanded, null, this.disposables); // TODO@Joao move this down to panelview // onHeaderKeyDown.filter(e => e.keyCode === KeyCode.UpArrow) @@ -114,42 +147,20 @@ export abstract class Panel implements IView { } layout(size: number): void { - this.layoutBody(size - Panel.HEADER_SIZE); + const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; + this.layoutBody(size - headerSize); } focus(): void { // TODO@joao what to do } - toggleExpansion(): void { - if (this.state === PanelState.Expanded) { - return this.collapse(); - } else { - return this.expand(); - } - } - - expand(): void { - if (this.state === PanelState.Expanded) { - return; - } - - this.renderHeader(); - this._onDidChange.fire(); - } - - collapse(): void { - if (this.state === PanelState.Collapsed) { - return; - } - - this.renderHeader(); - this._onDidChange.fire(); - } - private renderHeader(): void { - toggleClass(this.header, 'expanded', this.state === PanelState.Expanded); - this.header.setAttribute('aria-expanded', String(this.state === PanelState.Expanded)); + const expanded = !this.headerVisible || this.expanded; + + toggleClass(this.header, 'hidden', !this.headerVisible); + toggleClass(this.header, 'expanded', expanded); + this.header.setAttribute('aria-expanded', String(expanded)); } protected abstract renderBody(container: HTMLElement): void; @@ -273,6 +284,9 @@ export class PanelView implements IDisposable { private splitview: SplitView; private animationTimer: number | null = null; + private _onDidDrop = new Emitter<{ from: Panel, to: Panel }>(); + readonly onDidDrop: Event<{ from: Panel, to: Panel }> = this._onDidDrop.event; + constructor(private container: HTMLElement, options?: IPanelViewOptions) { this.dnd = !!options.dnd; this.el = append(container, $('.monaco-panel-view')); @@ -286,7 +300,7 @@ export class PanelView implements IDisposable { if (this.dnd) { const draggable = new PanelDraggable(panel, this.dndContext); disposables.push(draggable); - draggable.onDidDrop(({ from, to }) => this.movePanel(from, to), null, disposables); + draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop, disposables); } const panelItem = { panel, disposable: combinedDisposable(disposables) }; @@ -340,6 +354,7 @@ export class PanelView implements IDisposable { } dispose(): void { - + this.panelItems.forEach(i => i.disposable.dispose()); + this.splitview.dispose(); } } From 07cd08c7e522899de4a27e3a4f18a9e5e2fa38d9 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 18 Sep 2017 11:28:49 +0200 Subject: [PATCH 145/145] introduce PanelViewlet --- src/vs/base/browser/ui/splitview/panelview.ts | 3 +- .../workbench/browser/parts/views/views2.ts | 238 ++++++++++++++++++ 2 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 src/vs/workbench/browser/parts/views/views2.ts diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 7bd8c7af6aa..94ed8a2e53e 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -37,8 +37,9 @@ export abstract class Panel implements IView { private _minimumBodySize: number; private _maximumBodySize: number; private ariaHeaderLabel: string; + readonly header: HTMLElement; - private disposables: IDisposable[] = []; + protected disposables: IDisposable[] = []; get minimumBodySize(): number { return this._minimumBodySize; diff --git a/src/vs/workbench/browser/parts/views/views2.ts b/src/vs/workbench/browser/parts/views/views2.ts new file mode 100644 index 00000000000..e6592e5a305 --- /dev/null +++ b/src/vs/workbench/browser/parts/views/views2.ts @@ -0,0 +1,238 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { TPromise } from 'vs/base/common/winjs.base'; +import Event, { Emitter } from 'vs/base/common/event'; +import { attachStyler } from 'vs/platform/theme/common/styler'; +import { Dimension, Builder } from 'vs/base/browser/builder'; +import { append, $ } from 'vs/base/browser/dom'; +import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; +import { firstIndex } from 'vs/base/common/arrays'; +import { IAction, IActionRunner } from 'vs/base/common/actions'; +import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { prepareActions } from 'vs/workbench/browser/actions'; +import { Viewlet, ViewletRegistry, Extensions } from 'vs/workbench/browser/viewlet'; +import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { PanelView, IPanelOptions, Panel } from 'vs/base/browser/ui/splitview/panelview'; + +export interface IViewletPanelOptions extends IPanelOptions { + actionRunner?: IActionRunner; +} + +export abstract class ViewletPanel extends Panel { + + private _onDidFocus = new Emitter(); + readonly onDidFocus: Event = this._onDidFocus.event; + + private actionRunner: IActionRunner; + private toolbar: ToolBar; + + constructor( + readonly name: string, + initialSize: number, + options: IViewletPanelOptions, + protected keybindingService: IKeybindingService, + protected contextMenuService: IContextMenuService + ) { + super(options); + + this.actionRunner = options.actionRunner; + } + + render(container: HTMLElement): void { + super.render(container); + + const title = append(this.header, $('div.title')); + title.textContent = this.name; + + const actions = append(this.header, $('div.actions')); + this.toolbar = new ToolBar(actions, this.contextMenuService, { + orientation: ActionsOrientation.HORIZONTAL, + actionItemProvider: action => this.getActionItem(action), + ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.name), + getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id), + actionRunner: this.actionRunner + }); + + this.disposables.push(this.toolbar); + this.updateActions(); + } + + focus(): void { + super.focus(); + this._onDidFocus.fire(); + } + + protected updateActions(): void { + this.toolbar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions()))(); + this.toolbar.context = this.getActionsContext(); + } + + getActions(): IAction[] { + return []; + } + + getSecondaryActions(): IAction[] { + return []; + } + + getActionItem(action: IAction): IActionItem { + return null; + } + + getActionsContext(): any { + return undefined; + } + + getOptimalWidth(): number { + return 0; + } +} + +export interface IViewsViewletOptions { + showHeaderInTitleWhenSingleView: boolean; +} + +const SplitViewThemeMapping = { + dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND +}; + +interface IViewletPanelItem { + panel: ViewletPanel; + disposable: IDisposable; +} + +export class PanelViewlet extends Viewlet { + + protected lastFocusedPanel: ViewletPanel | undefined; + private panelItems: IViewletPanelItem[] = []; + private panelview: PanelView; + + protected get isSingleView(): boolean { + return this.options.showHeaderInTitleWhenSingleView && this.panelItems.length === 1; + } + + protected get length(): number { + return this.panelItems.length; + } + + constructor( + id: string, + private options: Partial, + @ITelemetryService telemetryService: ITelemetryService, + @IThemeService themeService: IThemeService + ) { + super(id, telemetryService, themeService); + } + + async create(parent: Builder): TPromise { + super.create(parent); + + const container = parent.getHTMLElement(); + this.panelview = this._register(new PanelView(container)); + this._register(attachStyler(this.themeService, SplitViewThemeMapping, this.panelview)); + // this._register(this.panelview.onFocus(view => this.lastFocusedView = view)); + } + + getTitle(): string { + let title = Registry.as(Extensions.Viewlets).getViewlet(this.getId()).name; + + if (this.isSingleView) { + title += ': ' + this.panelItems[0].panel.name; + } + + return title; + } + + getActions(): IAction[] { + if (this.isSingleView) { + return this.panelItems[0].panel.getActions(); + } + + return []; + } + + getSecondaryActions(): IAction[] { + if (this.isSingleView) { + return this.panelItems[0].panel.getSecondaryActions(); + } + + return []; + } + + focus(): void { + super.focus(); + + if (this.lastFocusedPanel) { + this.lastFocusedPanel.focus(); + } else if (this.panelItems.length > 0) { + this.panelItems[0].panel.focus(); + } + } + + layout(dimension: Dimension): void { + this.panelview.layout(dimension.height); + } + + getOptimalWidth(): number { + const sizes = this.panelItems + .map(panelItem => panelItem.panel.getOptimalWidth() || 0); + + return Math.max(...sizes); + } + + addView(panel: ViewletPanel, index = this.panelItems.length - 1): void { + const disposables: IDisposable[] = []; + const onDidFocus = panel.onDidFocus(() => this.lastFocusedPanel = panel, null, disposables); + const disposable = combinedDisposable([onDidFocus]); + const panelItem: IViewletPanelItem = { panel, disposable }; + + this.panelItems.splice(index, 0, panelItem); + this.panelview.addPanel(panel, 200, index); + + this.updateViewHeaders(); + this.updateTitleArea(); + } + + removeView(panel: ViewletPanel): void { + const index = firstIndex(this.panelItems, i => i.panel === panel); + + if (index === -1) { + return; + } + + if (this.lastFocusedPanel === panel) { + this.lastFocusedPanel = undefined; + } + + this.panelview.removePanel(panel); + const [panelItem] = this.panelItems.splice(index, 1); + panelItem.disposable.dispose(); + + this.updateViewHeaders(); + this.updateTitleArea(); + } + + private updateViewHeaders(): void { + if (this.isSingleView) { + this.panelItems[0].panel.headerVisible = false; + } else { + this.panelItems.forEach(i => i.panel.headerVisible = true); + } + } + + dispose(): void { + super.dispose(); + this.panelItems.forEach(i => i.disposable.dispose()); + this.panelview.dispose(); + } +} \ No newline at end of file