From 1c6bf3557b83a18db8a13b47ee411d3137b10c71 Mon Sep 17 00:00:00 2001 From: Jacques Bouthillier Date: Thu, 4 Apr 2019 07:20:03 -0400 Subject: [PATCH] GH-4814 Looking at Gulp/Jake/Grunt plugins extensions. It is possible to have tasks with the same type, so we need to differentiate them. Using the handle available with the task to create a unique provider. This allow to have following plugins within the same workspace: - grunt - gulp - jake Signed-off-by: Jacques Bouthillier --- .../plugin-ext/src/main/browser/tasks-main.ts | 2 +- packages/plugin-ext/src/plugin/types-impl.ts | 49 +++++++++++++++++-- packages/plugin/src/theia.d.ts | 47 ++++++++++++------ .../browser/provided-task-configurations.ts | 9 ++-- .../task/src/browser/task-contribution.ts | 17 +++++-- 5 files changed, 96 insertions(+), 28 deletions(-) diff --git a/packages/plugin-ext/src/main/browser/tasks-main.ts b/packages/plugin-ext/src/main/browser/tasks-main.ts index c1b4d7999cc6e..ac1c3a79e5246 100644 --- a/packages/plugin-ext/src/main/browser/tasks-main.ts +++ b/packages/plugin-ext/src/main/browser/tasks-main.ts @@ -75,7 +75,7 @@ export class TasksMainImpl implements TasksMain { const taskResolver = this.createTaskResolver(handle); const disposable = new DisposableCollection(); - disposable.push(this.taskProviderRegistry.register(type, taskProvider)); + disposable.push(this.taskProviderRegistry.register(type, taskProvider, handle)); disposable.push(this.taskResolverRegistry.register(type, taskResolver)); this.disposables.set(handle, disposable); } diff --git a/packages/plugin-ext/src/plugin/types-impl.ts b/packages/plugin-ext/src/plugin/types-impl.ts index 2191a1d3fecfd..a558a3598a145 100644 --- a/packages/plugin-ext/src/plugin/types-impl.ts +++ b/packages/plugin-ext/src/plugin/types-impl.ts @@ -1541,7 +1541,7 @@ export enum TaskScope { export class Task { private taskDefinition: theia.TaskDefinition | undefined; - private taskScope: theia.TaskScope.Global | theia.TaskScope.Workspace | theia.WorkspaceFolder | undefined; + private taskScope?: theia.TaskScope.Global | theia.TaskScope.Workspace | theia.WorkspaceFolder | undefined; private taskName: string; private taskExecution: ProcessExecution | ShellExecution | undefined; private taskProblemMatchers: string[]; @@ -1550,13 +1550,51 @@ export class Task { private taskSource: string; private taskGroup: TaskGroup | undefined; private taskPresentationOptions: theia.TaskPresentationOptions | undefined; - - constructor(taskDefinition: theia.TaskDefinition, + constructor( + taskDefinition: theia.TaskDefinition, scope: theia.WorkspaceFolder | theia.TaskScope.Global | theia.TaskScope.Workspace, name: string, source: string, execution?: ProcessExecution | ShellExecution, - problemMatchers?: string | string[]) { + problemMatchers?: string | string[] + ); + + // Deprecated constructor used by Jake vscode built-in + constructor( + taskDefinition: theia.TaskDefinition, + name: string, + source: string, + execution?: ProcessExecution | ShellExecution, + problemMatchers?: string | string[], + ); + + // tslint:disable-next-line:no-any + constructor(...args: any[]) { + let taskDefinition: theia.TaskDefinition; + let scope: theia.WorkspaceFolder | theia.TaskScope.Global | theia.TaskScope.Workspace | undefined; + let name: string; + let source: string; + let execution: ProcessExecution | ShellExecution | undefined; + let problemMatchers: string | string[] | undefined; + + if (typeof args[1] === 'string') { + [ + taskDefinition, + name, + source, + execution, + problemMatchers, + ] = args; + } else { + [ + taskDefinition, + scope, + name, + source, + execution, + problemMatchers, + ] = args; + } this.definition = taskDefinition; this.scope = scope; @@ -1593,6 +1631,9 @@ export class Task { } set scope(value: theia.TaskScope.Global | theia.TaskScope.Workspace | theia.WorkspaceFolder | undefined) { + if (value === null) { + value = undefined; + } this.taskScope = value; } diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 7820b12c13c42..76ff581ae27f2 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -157,7 +157,6 @@ declare module '@theia/plugin' { export let all: Plugin[]; } - /** * A command is a unique identifier of a function * which can be executed by a user via a keyboard shortcut, @@ -3672,7 +3671,7 @@ declare module '@theia/plugin' { size: number; } - /** + /** * A type that filesystem providers should use to signal errors. * * This class has factory methods for common error-cases, like `EntryNotFound` when @@ -3680,45 +3679,45 @@ declare module '@theia/plugin' { */ export class FileSystemError extends Error { - /** + /** * Create an error to signal that a file or folder wasn't found. * @param messageOrUri Message or uri. */ static FileNotFound(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Create an error to signal that a file or folder already exists, e.g. when * creating but not overwriting a file. * @param messageOrUri Message or uri. */ static FileExists(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Create an error to signal that a file is not a folder. * @param messageOrUri Message or uri. */ static FileNotADirectory(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Create an error to signal that a file is a folder. * @param messageOrUri Message or uri. */ static FileIsADirectory(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Create an error to signal that an operation lacks required permissions. * @param messageOrUri Message or uri. */ static NoPermissions(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Create an error to signal that the file system is unavailable or too busy to * complete a request. * @param messageOrUri Message or uri. */ static Unavailable(messageOrUri?: string | Uri): FileSystemError; - /** + /** * Creates a new filesystem error. * * @param messageOrUri Message or uri. @@ -4121,7 +4120,6 @@ declare module '@theia/plugin' { */ export function applyEdit(edit: WorkspaceEdit): PromiseLike; - /** * Register a filesystem provider for a given scheme, e.g. `ftp`. * @@ -5060,7 +5058,6 @@ declare module '@theia/plugin' { constructor(range: Range, newText: string); } - /** * Completion item kinds. */ @@ -5773,9 +5770,9 @@ declare module '@theia/plugin' { /** * Check if this code action kind intersects `other`. - * The kind "refactor.extract" for example intersects refactor, "refactor.extract" and + * The kind "refactor.extract" for example intersects refactor, "refactor.extract" and * `"refactor.extract.function", but not "unicorn.refactor.extract", or "refactor.extractAll". - * + * * @param other Kind to check. */ intersects(other: CodeActionKind): boolean; @@ -6050,7 +6047,6 @@ declare module '@theia/plugin' { resolveDocumentLink?(link: DocumentLink, token: CancellationToken | undefined): ProviderResult; } - /** * The rename provider interface defines the contract between extensions and * the [rename](https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol)-feature. @@ -7160,13 +7156,34 @@ declare module '@theia/plugin' { * or '$eslint'. Problem matchers can be contributed by an extension using * the `problemMatchers` extension point. */ - constructor(taskDefinition: TaskDefinition, + constructor( + taskDefinition: TaskDefinition, scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, name: string, source?: string, execution?: ProcessExecution | ShellExecution, problemMatchers?: string | string[]); + /** + * ~~Creates a new task.~~ + * + * @deprecated Use the new constructors that allow specifying a scope 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 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, + name: string, + source: string, + execution?: ProcessExecution | ShellExecution, + problemMatchers?: string | string[]); + /** The task's name */ name: string; diff --git a/packages/task/src/browser/provided-task-configurations.ts b/packages/task/src/browser/provided-task-configurations.ts index d904e595f0175..8f8df2ec1cba0 100644 --- a/packages/task/src/browser/provided-task-configurations.ts +++ b/packages/task/src/browser/provided-task-configurations.ts @@ -47,9 +47,12 @@ export class ProvidedTaskConfigurations { if (task) { return task; } else { - const provider = this.taskProviderRegistry.getProvider(source); - if (provider) { - const tasks = await provider.provideTasks(); + const providers = this.taskProviderRegistry.getProvider(source); + if (providers.length > 0) { + const tasks: TaskConfiguration[] = []; + for (const provider of providers) { + tasks.push(...await provider.provideTasks()); + } this.cacheTasks(tasks); return this.getCachedTask(source, taskLabel); } diff --git a/packages/task/src/browser/task-contribution.ts b/packages/task/src/browser/task-contribution.ts index 9abcc457ae8f0..16cb4765f456a 100644 --- a/packages/task/src/browser/task-contribution.ts +++ b/packages/task/src/browser/task-contribution.ts @@ -70,15 +70,22 @@ export class TaskProviderRegistry { } /** Registers the given Task Provider to return Task Configurations of the specified type. */ - register(type: string, provider: TaskProvider): Disposable { - this.providers.set(type, provider); + register(type: string, provider: TaskProvider, handle?: number): Disposable { + const key = handle === undefined ? type : `${type}::${handle}`; + this.providers.set(key, provider); return { - dispose: () => this.providers.delete(type) + dispose: () => this.providers.delete(key) }; } - getProvider(type: string): TaskProvider | undefined { - return this.providers.get(type); + getProvider(type: string): TaskProvider[] { + const providerArray: TaskProvider[] = []; + this.providers.forEach((provider, key) => { + if (key.startsWith(type)) { + providerArray.push(provider); + } + }); + return providerArray; } /** Returns all registered Task Providers. */