Skip to content

Commit

Permalink
create problem markers from task output
Browse files Browse the repository at this point in the history
What's included in this PR:
- support taskDefinition, problemMatcher, & problemPattern contributed by Theia plugins.
- support customizing tasks by adding named & anonymous problem matchers and patterns in .theia/tasks.json.
- support parsing output from both "start - finish" tasks and "watch" tasks.
- support both single line and multi line patterns.
- create problem markers on parsing task output with the plugin-defined or user-defined problem matchers and patterns.

What's not included:
- prompt users to provide problem matcher and / or patterns before starting tasks
- remove problem markers automatically when problems are fixed

CQ:
https://dev.eclipse.org/ipzilla/show_bug.cgi?id=19787. Approved on June 4 2019.
https://dev.eclipse.org/ipzilla/show_bug.cgi?id=20139. Approved on June 11 2019.

Signed-off-by: elaihau <[email protected]>
  • Loading branch information
elaihau committed Jul 3, 2019
1 parent 20d60b3 commit 0517bae
Show file tree
Hide file tree
Showing 33 changed files with 2,205 additions and 81 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Change Log

## v0.9.0
- [task] added support for VS Code task contribution points: `taskDefinitions`, `problemMatchers`, and `problemPatterns`

Breaking changes:

Expand Down
15 changes: 15 additions & 0 deletions packages/cpp/src/browser/cpp-build-configurations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
let disableJSDOM = enableJSDOM();

import { ContainerModule, Container } from 'inversify';
import { expect } from 'chai';
import { FileSystem } from '@theia/filesystem/lib/common';
Expand All @@ -25,6 +28,9 @@ import { FileSystemNode } from '@theia/filesystem/lib/node/node-filesystem';
import { bindCppPreferences } from './cpp-preferences';
import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
import { MockPreferenceService } from '@theia/core/lib/browser/preferences/test/mock-preference-service';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser';

disableJSDOM();

let container: Container;

Expand All @@ -33,6 +39,7 @@ beforeEach(function () {
bind(CppBuildConfigurationManager).to(CppBuildConfigurationManagerImpl).inSingletonScope();
bind(StorageService).to(MockStorageService).inSingletonScope();
bind(FileSystem).to(FileSystemNode).inSingletonScope();
bind(TaskDefinitionRegistry).toSelf().inSingletonScope();
bindCppPreferences(bind);
bind(PreferenceService).to(MockPreferenceService).inSingletonScope();
});
Expand Down Expand Up @@ -77,6 +84,14 @@ async function initializeTest(buildConfigurations: CppBuildConfiguration[] | und
}

describe('build-configurations', function () {
before(() => {
disableJSDOM = enableJSDOM();
});

after(() => {
disableJSDOM();
});

it('should work with no preferences', async function () {
const cppBuildConfigurations = await initializeTest(undefined, undefined);

Expand Down
2 changes: 2 additions & 0 deletions packages/cpp/src/browser/cpp-task-provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Event } from '@theia/core';
import { expect } from 'chai';
import { TaskConfiguration } from '@theia/task/src/common';
import { ProcessTaskConfiguration } from '@theia/task/lib/common/process/task-protocol';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser';

// The object under test.
let taskProvider: CppTaskProvider;
Expand Down Expand Up @@ -67,6 +68,7 @@ beforeEach(function () {
const container: Container = new Container();
container.bind(CppTaskProvider).toSelf().inSingletonScope();
container.bind(TaskResolverRegistry).toSelf().inSingletonScope();
container.bind(TaskDefinitionRegistry).toSelf().inSingletonScope();
container.bind(CppBuildConfigurationManager).to(MockCppBuildConfigurationManager);
taskProvider = container.get(CppTaskProvider);

Expand Down
21 changes: 19 additions & 2 deletions packages/cpp/src/browser/cpp-task-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
********************************************************************************/

import parseArgv = require('string-argv');
import { inject, injectable } from 'inversify';
import { inject, injectable, postConstruct } from 'inversify';
import { ProcessTaskConfiguration } from '@theia/task/lib/common/process/task-protocol';
import { TaskDefinitionRegistry } from '@theia/task/lib/browser';
import { TaskContribution, TaskProvider, TaskProviderRegistry, TaskResolver, TaskResolverRegistry } from '@theia/task/lib/browser/task-contribution';
import { CppBuildConfigurationManager, CppBuildConfiguration } from './cpp-build-configurations';
import { ContributedTaskConfiguration, TaskConfiguration } from '@theia/task/lib/common/task-protocol';
import { ContributedTaskConfiguration, TaskConfiguration, } from '@theia/task/lib/common/task-protocol';

/**
* Data required to define a C/C++ build task the user could run.
Expand All @@ -35,8 +36,14 @@ const CPP_BUILD_TASK_SOURCE: string = 'cpp';
export class CppTaskProvider implements TaskContribution, TaskProvider, TaskResolver {

@inject(TaskResolverRegistry) protected readonly taskResolverRegistry: TaskResolverRegistry;
@inject(TaskDefinitionRegistry) protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;
@inject(CppBuildConfigurationManager) protected readonly cppBuildConfigurationManager: CppBuildConfigurationManager;

@postConstruct()
protected init(): void {
this.registerTaskDefinition();
}

registerProviders(registry: TaskProviderRegistry) {
registry.register(CPP_BUILD_TASK_SOURCE, this);
}
Expand Down Expand Up @@ -108,4 +115,14 @@ export class CppTaskProvider implements TaskContribution, TaskProvider, TaskReso

return taskConfigs;
}

private registerTaskDefinition(): void {
this.taskDefinitionRegistry.register({
taskType: CPP_BUILD_TASK_TYPE_KEY,
properties: {
required: ['label'],
all: ['label']
}
});
}
}
28 changes: 28 additions & 0 deletions packages/plugin-ext/src/common/plugin-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ExtPluginApi } from './plugin-ext-api-contribution';
import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
import { RecursivePartial } from '@theia/core/lib/common/types';
import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema';
import { ProblemMatcherContribution, ProblemPatternContribution, TaskDefinition } from '@theia/task/lib/common';

export const hostedServicePath = '/services/hostedPlugin';

Expand Down Expand Up @@ -71,6 +72,9 @@ export interface PluginPackageContribution {
keybindings?: PluginPackageKeybinding[];
debuggers?: PluginPackageDebuggersContribution[];
snippets: PluginPackageSnippetsContribution[];
taskDefinitions?: PluginTaskDefinitionContribution[];
problemMatchers?: PluginProblemMatcherContribution[];
problemPatterns?: PluginProblemPatternContribution[];
}

export interface PluginPackageViewContainer {
Expand Down Expand Up @@ -174,6 +178,27 @@ export interface PluginPackageLanguageContributionConfiguration {
folding?: FoldingRules;
}

export interface PluginTaskDefinitionContribution {
type: string;
required: string[];
properties: {
[name: string]: {
type: string;
description?: string;
// tslint:disable-next-line:no-any
[additionalProperty: string]: any;
}
}
}

export interface PluginProblemMatcherContribution extends ProblemMatcherContribution {
name: string;
}

export interface PluginProblemPatternContribution extends ProblemPatternContribution {
name: string;
}

export const PluginScanner = Symbol('PluginScanner');
/**
* This scanner process package.json object and returns plugin metadata objects.
Expand Down Expand Up @@ -364,6 +389,9 @@ export interface PluginContribution {
keybindings?: Keybinding[];
debuggers?: DebuggerContribution[];
snippets?: SnippetContribution[];
taskDefinitions?: TaskDefinition[];
problemMatchers?: ProblemMatcherContribution[];
problemPatterns?: ProblemPatternContribution[];
}

export interface SnippetContribution {
Expand Down
24 changes: 24 additions & 0 deletions packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
LanguageContribution,
PluginPackageLanguageContributionConfiguration,
LanguageConfiguration,
PluginTaskDefinitionContribution,
AutoClosingPairConditional,
AutoClosingPair,
ViewContainer,
Expand Down Expand Up @@ -55,6 +56,7 @@ import { deepClone } from '@theia/core/lib/common/objects';
import { FileUri } from '@theia/core/lib/node/file-uri';
import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/common/preferences/preference-schema';
import { RecursivePartial } from '@theia/core/lib/common/types';
import { ProblemMatcherContribution, ProblemPatternContribution, TaskDefinition } from '@theia/task/lib/common/task-protocol';

namespace nls {
export function localize(key: string, _default: string) {
Expand Down Expand Up @@ -183,6 +185,18 @@ export class TheiaPluginScanner implements PluginScanner {
contributions.debuggers = debuggers;
}

if (rawPlugin.contributes!.taskDefinitions) {
contributions.taskDefinitions = rawPlugin.contributes!.taskDefinitions!.map(definitionContribution => this.readTaskDefinition(definitionContribution));
}

if (rawPlugin.contributes!.problemMatchers) {
contributions.problemMatchers = rawPlugin.contributes!.problemMatchers as ProblemMatcherContribution[];
}

if (rawPlugin.contributes!.problemPatterns) {
contributions.problemPatterns = rawPlugin.contributes!.problemPatterns as ProblemPatternContribution[];
}

contributions.snippets = this.readSnippets(rawPlugin);
return contributions;
}
Expand Down Expand Up @@ -354,6 +368,16 @@ export class TheiaPluginScanner implements PluginScanner {
return result;
}

private readTaskDefinition(definitionContribution: PluginTaskDefinitionContribution): TaskDefinition {
return {
taskType: definitionContribution.type,
properties: {
required: definitionContribution.required,
all: Object.keys(definitionContribution.properties)
}
};
}

protected resolveSchemaAttributes(type: string, configurationAttributes: { [request: string]: IJSONSchema }): IJSONSchema[] {
const taskSchema = {};
return Object.keys(configurationAttributes).map(request => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { KeybindingsContributionPointHandler } from './keybindings/keybindings-c
import { MonacoSnippetSuggestProvider } from '@theia/monaco/lib/browser/monaco-snippet-suggest-provider';
import { PluginSharedStyle } from './plugin-shared-style';
import { CommandRegistry } from '@theia/core';
import { TaskDefinitionRegistry, ProblemMatcherRegistry, ProblemPatternRegistry } from '@theia/task/lib/browser';

@injectable()
export class PluginContributionHandler {
Expand Down Expand Up @@ -59,6 +60,15 @@ export class PluginContributionHandler {
@inject(PluginSharedStyle)
protected readonly style: PluginSharedStyle;

@inject(TaskDefinitionRegistry)
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;

@inject(ProblemMatcherRegistry)
protected readonly problemMatcherRegistry: ProblemMatcherRegistry;

@inject(ProblemPatternRegistry)
protected readonly problemPatternRegistry: ProblemPatternRegistry;

handleContributions(contributions: PluginContribution): void {
if (contributions.configuration) {
this.updateConfigurationSchema(contributions.configuration);
Expand Down Expand Up @@ -149,6 +159,18 @@ export class PluginContributionHandler {
});
}
}

if (contributions.taskDefinitions) {
contributions.taskDefinitions.forEach(def => this.taskDefinitionRegistry.register(def));
}

if (contributions.problemPatterns) {
contributions.problemPatterns.forEach(pattern => this.problemPatternRegistry.register(pattern));
}

if (contributions.problemMatchers) {
contributions.problemMatchers.forEach(matcher => this.problemMatcherRegistry.register(matcher));
}
}

protected registerCommands(contribution: PluginContribution): void {
Expand Down
6 changes: 4 additions & 2 deletions packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1733,12 +1733,14 @@ export class Task {
if (this.taskExecution instanceof ProcessExecution) {
Object.assign(this.taskDefinition, {
type: 'process',
id: this.taskExecution.computeId()
id: this.taskExecution.computeId(),
taskType: this.taskDefinition!.type
});
} else if (this.taskExecution instanceof ShellExecution) {
Object.assign(this.taskDefinition, {
type: 'shell',
id: this.taskExecution.computeId()
id: this.taskExecution.computeId(),
taskType: this.taskDefinition!.type
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/task/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"@theia/terminal": "^0.8.0",
"@theia/variable-resolver": "^0.8.0",
"@theia/workspace": "^0.8.0",
"jsonc-parser": "^2.0.2"
"jsonc-parser": "^2.0.2",
"vscode-uri": "^1.0.8"
},
"publishConfig": {
"access": "public"
Expand Down
3 changes: 3 additions & 0 deletions packages/task/src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@

export * from './task-service';
export * from './task-contribution';
export * from './task-definition-registry';
export * from './task-problem-matcher-registry';
export * from './task-problem-pattern-registry';
Loading

0 comments on commit 0517bae

Please sign in to comment.