提交 f51220db 编写于 作者: D Dirk Baeumer

Fixes #22066: Allow extensions to contribute named problem matchers via package.json

上级 e1401591
......@@ -365,6 +365,42 @@
"fileMatch": "typings.json",
"url": "http://json.schemastore.org/typings"
}
],
"problemPatterns": [
{
"name": "tsc",
"regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
"file": 1,
"location": 2,
"severity": 3,
"code": 4,
"message": 5
}
],
"problemMatchers": [
{
"name": "tsc",
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": ["relative", "$cwd"],
"pattern": "$tsc"
},
{
"name": "tsc-watch",
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": ["relative", "$cwd"],
"pattern": "$tsc",
"watching": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "^\\s*(?:message TS6032:|\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? -) File change detected\\. Starting incremental compilation\\.\\.\\."
},
"endsPattern": {
"regexp": "^\\s*(?:message TS6042:|\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? -) Compilation complete\\. Watching for file changes\\."
}
}
}
]
}
}
}
\ No newline at end of file
......@@ -41,48 +41,62 @@ export class ValidationStatus {
}
}
export interface ILogger {
log(value: string): void;
export interface IProblemReporter {
info(message: string): void;
warn(message: string): void;
error(message: string): void;
fatal(message: string): void;
status: ValidationStatus;
}
export abstract class Parser {
private _logger: ILogger;
private validationStatus: ValidationStatus;
private _problemReporter: IProblemReporter;
constructor(logger: ILogger, validationStatus: ValidationStatus = new ValidationStatus()) {
this._logger = logger;
this.validationStatus = validationStatus;
constructor(problemReporter: IProblemReporter) {
this._problemReporter = problemReporter;
}
public get logger(): ILogger {
return this._logger;
public reset(): void {
this._problemReporter.status.state = ValidationState.OK;
}
public get status(): ValidationStatus {
return this.validationStatus;
public get problemReporter(): IProblemReporter {
return this._problemReporter;
}
protected log(message: string): void {
this._logger.log(message);
public info(message: string): void {
this._problemReporter.info(message);
}
public warn(message: string): void {
this._problemReporter.warn(message);
}
public error(message: string): void {
this._problemReporter.error(message);
}
public fatal(message: string): void {
this._problemReporter.fatal(message);
}
protected is(value: any, func: (value: any) => boolean, wrongTypeState?: ValidationState, wrongTypeMessage?: string, undefinedState?: ValidationState, undefinedMessage?: string): boolean {
if (Types.isUndefined(value)) {
if (undefinedState) {
this.validationStatus.state = undefinedState;
this._problemReporter.status.state = undefinedState;
}
if (undefinedMessage) {
this.log(undefinedMessage);
this._problemReporter.info(undefinedMessage);
}
return false;
}
if (!func(value)) {
if (wrongTypeState) {
this.validationStatus.state = wrongTypeState;
this._problemReporter.status.state = wrongTypeState;
}
if (wrongTypeMessage) {
this.log(wrongTypeMessage);
this.info(wrongTypeMessage);
}
return false;
}
......
......@@ -11,7 +11,7 @@ import * as Platform from 'vs/base/common/platform';
import { IStringDictionary } from 'vs/base/common/collections';
import * as Types from 'vs/base/common/types';
import { ValidationStatus, ValidationState, ILogger, Parser } from 'vs/base/common/parsers';
import { ValidationState, IProblemReporter, Parser } from 'vs/base/common/parsers';
/**
* Options to be passed to the external program or shell.
......@@ -172,13 +172,13 @@ export interface ParserOptions {
export class ExecutableParser extends Parser {
constructor(logger: ILogger, validationStatus: ValidationStatus = new ValidationStatus()) {
super(logger, validationStatus);
constructor(logger: IProblemReporter) {
super(logger);
}
public parse(json: Config.Executable, parserOptions: ParserOptions = { globals: null, emptyCommand: false, noDefaults: false }): Executable {
let result = this.parseExecutable(json, parserOptions.globals);
if (this.status.isFatal()) {
if (this.problemReporter.status.isFatal()) {
return result;
}
let osExecutable: Executable;
......@@ -193,8 +193,7 @@ export class ExecutableParser extends Parser {
result = ExecutableParser.mergeExecutable(result, osExecutable);
}
if ((!result || !result.command) && !parserOptions.emptyCommand) {
this.status.state = ValidationState.Fatal;
this.log(NLS.localize('ExecutableParser.commandMissing', 'Error: executable info must define a command of type string.'));
this.fatal(NLS.localize('ExecutableParser.commandMissing', 'Error: executable info must define a command of type string.'));
return null;
}
if (!parserOptions.noDefaults) {
......
......@@ -13,10 +13,10 @@ import * as Types from 'vs/base/common/types';
import * as UUID from 'vs/base/common/uuid';
import { Config as ProcessConfig } from 'vs/base/common/processes';
import { ValidationStatus, ValidationState } from 'vs/base/common/parsers';
import { ValidationStatus, IProblemReporter as IProblemReporterBase } from 'vs/base/common/parsers';
import {
NamedProblemMatcher, ProblemMatcher, ProblemMatcherParser, Config as ProblemMatcherConfig,
registry as ProblemMatcherRegistry, isNamedProblemMatcher
isNamedProblemMatcher, ProblemMatcherRegistry
} from 'vs/platform/markers/common/problemMatcher';
import * as TaskSystem from './taskSystem';
......@@ -311,8 +311,7 @@ function fillProperty<T, K extends keyof T>(target: T, source: T, key: K) {
}
interface ParseContext {
logger: ILogger;
validationStatus: ValidationStatus;
problemReporter: IProblemReporter;
namedProblemMatchers: IStringDictionary<NamedProblemMatcher>;
isTermnial: boolean;
}
......@@ -324,8 +323,7 @@ namespace CommandOptions {
if (Types.isString(options.cwd)) {
result.cwd = options.cwd;
} else {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize('ConfigurationParser.invalidCWD', 'Warning: options.cwd must be of type string. Ignoring value {0}\n', options.cwd));
context.problemReporter.warn(nls.localize('ConfigurationParser.invalidCWD', 'Warning: options.cwd must be of type string. Ignoring value {0}\n', options.cwd));
}
}
if (options.env !== void 0) {
......@@ -471,8 +469,7 @@ namespace CommandConfiguration {
} else if (ShellConfiguration.is(config.isShellCommand)) {
result.isShellCommand = ShellConfiguration.from(config.isShellCommand, context);
if (!context.isTermnial) {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize('ConfigurationParser.noShell', 'Warning: shell configuration is only supported when executing tasks in the terminal.'));
context.problemReporter.warn(nls.localize('ConfigurationParser.noShell', 'Warning: shell configuration is only supported when executing tasks in the terminal.'));
}
} else if (config.isShellCommand !== void 0) {
result.isShellCommand = !!config.isShellCommand;
......@@ -481,8 +478,7 @@ namespace CommandConfiguration {
if (Types.isStringArray(config.args)) {
result.args = config.args.slice(0);
} else {
context.validationStatus.state = ValidationState.Fatal;
context.logger.log(nls.localize('ConfigurationParser.noargs', 'Error: command arguments must be an array of strings. Provided value is:\n{0}', config.args ? JSON.stringify(config.args, undefined, 4) : 'undefined'));
context.problemReporter.fatal(nls.localize('ConfigurationParser.noargs', 'Error: command arguments must be an array of strings. Provided value is:\n{0}', config.args ? JSON.stringify(config.args, undefined, 4) : 'undefined'));
}
}
if (config.options !== void 0) {
......@@ -578,12 +574,11 @@ namespace ProblemMatcherConverter {
return result;
}
(<ProblemMatcherConfig.NamedProblemMatcher[]>declares).forEach((value) => {
let namedProblemMatcher = (new ProblemMatcherParser(ProblemMatcherRegistry, context.logger, context.validationStatus)).parse(value);
let namedProblemMatcher = (new ProblemMatcherParser(context.problemReporter)).parse(value);
if (isNamedProblemMatcher(namedProblemMatcher)) {
result[namedProblemMatcher.name] = namedProblemMatcher;
} else {
context.validationStatus.state = ValidationState.Error;
context.logger.log(nls.localize('ConfigurationParser.noName', 'Error: Problem Matcher in declare scope must have a name:\n{0}\n', JSON.stringify(value, undefined, 4)));
context.problemReporter.error(nls.localize('ConfigurationParser.noName', 'Error: Problem Matcher in declare scope must have a name:\n{0}\n', JSON.stringify(value, undefined, 4)));
}
});
return result;
......@@ -596,8 +591,7 @@ namespace ProblemMatcherConverter {
}
let kind = getProblemMatcherKind(config);
if (kind === ProblemMatcherKind.Unknown) {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize(
context.problemReporter.warn(nls.localize(
'ConfigurationParser.unknownMatcherKind',
'Warning: the defined problem matcher is unknown. Supported types are string | ProblemMatcher | (string | ProblemMatcher)[].\n{0}\n',
JSON.stringify(config, null, 4)));
......@@ -648,12 +642,11 @@ namespace ProblemMatcherConverter {
return localProblemMatcher;
}
}
context.validationStatus.state = ValidationState.Error;
context.logger.log(nls.localize('ConfigurationParser.invalidVaraibleReference', 'Error: Invalid problemMatcher reference: {0}\n', value));
context.problemReporter.error(nls.localize('ConfigurationParser.invalidVaraibleReference', 'Error: Invalid problemMatcher reference: {0}\n', value));
return undefined;
} else {
let json = <ProblemMatcherConfig.ProblemMatcher>value;
return new ProblemMatcherParser(ProblemMatcherRegistry, context.logger, context.validationStatus).parse(json);
return new ProblemMatcherParser(context.problemReporter).parse(json);
}
}
}
......@@ -669,8 +662,7 @@ namespace CommandBinding {
}
if (!Types.isString(binding.identifier)) {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize('noCommandId', 'Warning: a command binding must defined an identifier. Ignoring binding.'));
context.problemReporter.warn(nls.localize('noCommandId', 'Warning: a command binding must defined an identifier. Ignoring binding.'));
return undefined;
}
let result: TaskSystem.CommandBinding = {
......@@ -706,8 +698,7 @@ namespace TaskDescription {
tasks.forEach((externalTask) => {
let taskName = externalTask.taskName;
if (!taskName) {
context.validationStatus.state = ValidationState.Fatal;
context.logger.log(nls.localize('ConfigurationParser.noTaskName', 'Error: tasks must provide a taskName property. The task will be ignored.\n{0}\n', JSON.stringify(externalTask, null, 4)));
context.problemReporter.fatal(nls.localize('ConfigurationParser.noTaskName', 'Error: tasks must provide a taskName property. The task will be ignored.\n{0}\n', JSON.stringify(externalTask, null, 4)));
return;
}
let problemMatchers = ProblemMatcherConverter.from(externalTask.problemMatcher, context);
......@@ -759,14 +750,12 @@ namespace TaskDescription {
let addTask: boolean = true;
if (context.isTermnial && task.command && task.command.name && task.command.isShellCommand && task.command.args && task.command.args.length > 0) {
if (hasUnescapedSpaces(task.command.name) || task.command.args.some(hasUnescapedSpaces)) {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize('taskConfiguration.shellArgs', 'Warning: the task \'{0}\' is a shell command and either the command name or one of its arguments has unescaped spaces. To ensure correct command line quoting please merge args into the command.', task.name));
context.problemReporter.warn(nls.localize('taskConfiguration.shellArgs', 'Warning: the task \'{0}\' is a shell command and either the command name or one of its arguments has unescaped spaces. To ensure correct command line quoting please merge args into the command.', task.name));
}
}
if (context.isTermnial) {
if ((task.command === void 0 || task.command.name === void 0) && (task.dependsOn === void 0 || task.dependsOn.length === 0)) {
context.validationStatus.state = ValidationState.Error;
context.logger.log(nls.localize(
context.problemReporter.error(nls.localize(
'taskConfiguration.noCommandOrDependsOn', 'Error: the task \'{0}\' neither specifies a command or a dependsOn property. The task will be ignored. Its definition is:\n{1}',
task.name, JSON.stringify(externalTask, undefined, 4)
));
......@@ -774,8 +763,7 @@ namespace TaskDescription {
}
} else {
if (task.command === void 0 || task.command.name === void 0) {
context.validationStatus.state = ValidationState.Warning;
context.logger.log(nls.localize(
context.problemReporter.warn(nls.localize(
'taskConfiguration.noCommand', 'Error: the task \'{0}\' doesn\'t define a command. The task will be ignored. Its definition is:\n{1}',
task.name, JSON.stringify(externalTask, undefined, 4)
));
......@@ -1037,30 +1025,26 @@ export interface ParseResult {
engine: ExecutionEngine;
}
export interface ILogger {
log(value: string): void;
export interface IProblemReporter extends IProblemReporterBase {
clearOutput(): void;
}
class ConfigurationParser {
private validationStatus: ValidationStatus;
private logger: ILogger;
private problemReporter: IProblemReporter;
constructor(logger: ILogger) {
this.logger = logger;
this.validationStatus = new ValidationStatus();
constructor(problemReporter: IProblemReporter) {
this.problemReporter = problemReporter;
}
public run(fileConfig: ExternalTaskRunnerConfiguration): ParseResult {
let engine = ExecutionEngine.from(fileConfig);
if (engine === ExecutionEngine.Terminal) {
this.logger.clearOutput();
this.problemReporter.clearOutput();
}
let context: ParseContext = { logger: this.logger, validationStatus: this.validationStatus, namedProblemMatchers: undefined, isTermnial: engine === ExecutionEngine.Terminal };
let context: ParseContext = { problemReporter: this.problemReporter, namedProblemMatchers: undefined, isTermnial: engine === ExecutionEngine.Terminal };
return {
validationStatus: this.validationStatus,
validationStatus: this.problemReporter.status,
configuration: this.createTaskRunnerConfiguration(fileConfig, context),
engine
};
......@@ -1068,7 +1052,7 @@ class ConfigurationParser {
private createTaskRunnerConfiguration(fileConfig: ExternalTaskRunnerConfiguration, context: ParseContext): TaskSystem.TaskRunnerConfiguration {
let globals = Globals.from(fileConfig, context);
if (context.validationStatus.isFatal()) {
if (this.problemReporter.status.isFatal()) {
return undefined;
}
context.namedProblemMatchers = ProblemMatcherConverter.namedFrom(fileConfig.declares, context);
......@@ -1123,6 +1107,6 @@ class ConfigurationParser {
}
}
export function parse(configuration: ExternalTaskRunnerConfiguration, logger: ILogger): ParseResult {
export function parse(configuration: ExternalTaskRunnerConfiguration, logger: IProblemReporter): ParseResult {
return (new ConfigurationParser(logger)).run(configuration);
}
\ No newline at end of file
......@@ -10,10 +10,10 @@ import { IStringDictionary } from 'vs/base/common/collections';
import * as Types from 'vs/base/common/types';
import * as UUID from 'vs/base/common/uuid';
import { ValidationStatus, ValidationState, ILogger, Parser } from 'vs/base/common/parsers';
import { IProblemReporter, Parser } from 'vs/base/common/parsers';
import { Executable, ExecutableParser, Config as ProcessConfig } from 'vs/base/common/processes';
import { ProblemMatcher, Config as ProblemMatcherConfig, ProblemMatcherParser } from 'vs/platform/markers/common/problemMatcher';
import { ProblemMatcher, Config as ProblemMatcherConfig, ProblemMatcherParser, ProblemMatcherRegistry } from 'vs/platform/markers/common/problemMatcher';
export namespace Config {
......@@ -159,11 +159,8 @@ export interface ParserSettings {
export class TaskParser extends Parser {
private resolver: { get(name: string): ProblemMatcher; };
constructor(resolver: { get(name: string): ProblemMatcher; }, logger: ILogger, validationStatus: ValidationStatus = new ValidationStatus()) {
super(logger, validationStatus);
this.resolver = resolver;
constructor(problemReporter: IProblemReporter) {
super(problemReporter);
}
public parse(json: Config.Task, parserSettings: ParserSettings = { globals: null, emptyExecutable: false, emptyCommand: false }): Task {
......@@ -181,17 +178,15 @@ export class TaskParser extends Parser {
trigger = <string[]>json.trigger;
}
if (name === null && trigger === null) {
this.status.state = ValidationState.Error;
this.log(NLS.localize('TaskParser.nameOrTrigger', 'A task must either define a name or a trigger.'));
this.error(NLS.localize('TaskParser.nameOrTrigger', 'A task must either define a name or a trigger.'));
return null;
}
let executable: Executable = json.executable ? (new ExecutableParser(this.logger, this.status)).parse(json.executable, { emptyCommand: !!parserSettings.emptyCommand }) : null;
let executable: Executable = json.executable ? (new ExecutableParser(this.problemReporter)).parse(json.executable, { emptyCommand: !!parserSettings.emptyCommand }) : null;
if (!executable && parserSettings.globals) {
executable = parserSettings.globals;
}
if (executable === null && !parserSettings.emptyExecutable) {
this.status.state = ValidationState.Error;
this.log(NLS.localize('TaskParser.noExecutable', 'A task must must define a valid executable.'));
this.error(NLS.localize('TaskParser.noExecutable', 'A task must must define a valid executable.'));
return null;
}
let isWatching: boolean = false;
......@@ -235,9 +230,9 @@ export class TaskParser extends Parser {
private parseProblemMatcher(json: string | ProblemMatcherConfig.ProblemMatcher): ProblemMatcher {
if (Types.isString(json)) {
return json.length > 0 && json.charAt(0) === '$' ? this.resolver.get(json.substr(1)) : null;
return json.length > 0 && json.charAt(0) === '$' ? ProblemMatcherRegistry.get(json.substr(1)) : null;
} else if (Types.isObject(json)) {
return new ProblemMatcherParser(this.resolver, this.logger, this.status).parse(<ProblemMatcherConfig.ProblemMatcher>json);
return new ProblemMatcherParser(this.problemReporter).parse(<ProblemMatcherConfig.ProblemMatcher>json);
} else {
return null;
}
......
......@@ -25,6 +25,7 @@ import { match } from 'vs/base/common/glob';
import { setTimeout } from 'vs/base/common/platform';
import { TerminateResponse, TerminateResponseCode } from 'vs/base/common/processes';
import * as strings from 'vs/base/common/strings';
import { ValidationStatus, ValidationState } from 'vs/base/common/parsers';
import { Registry } from 'vs/platform/platform';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
......@@ -40,6 +41,7 @@ import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ProblemMatcherRegistry } from 'vs/platform/markers/common/problemMatcher';
import { IModeService } from 'vs/editor/common/services/modeService';
......@@ -448,6 +450,43 @@ class NullTaskSystem extends EventEmitter implements ITaskSystem {
}
}
class ProblemReporter implements TaskConfig.IProblemReporter {
private _validationStatus: ValidationStatus;
constructor(private _outputChannel: IOutputChannel) {
this._validationStatus = new ValidationStatus();
}
public info(message: string): void {
this._validationStatus.state = ValidationState.Info;
this._outputChannel.append(message + '\n');
}
public warn(message: string): void {
this._validationStatus.state = ValidationState.Warning;
this._outputChannel.append(message + '\n');
}
public error(message: string): void {
this._validationStatus.state = ValidationState.Error;
this._outputChannel.append(message + '\n');
}
public fatal(message: string): void {
this._validationStatus.state = ValidationState.Fatal;
this._outputChannel.append(message + '\n');
}
public get status(): ValidationStatus {
return this._validationStatus;
}
public clearOutput(): void {
this._outputChannel.clear();
}
}
class TaskService extends EventEmitter implements ITaskService {
private static autoDetectTelemetryName: string = 'taskServer.autoDetect';
......@@ -591,14 +630,6 @@ class TaskService extends EventEmitter implements ITaskService {
});
}
public log(value: string): void {
this.outputChannel.append(value + '\n');
}
public clearOutput(): void {
this.outputChannel.clear();
}
private showOutput(): void {
this.outputChannel.show(true);
}
......@@ -621,7 +652,8 @@ class TaskService extends EventEmitter implements ITaskService {
this._taskSystemPromise = TPromise.as(this._taskSystem);
} else {
let hasError = false;
this._taskSystemPromise = TPromise.as(this.configurationService.getConfiguration<TaskConfig.ExternalTaskRunnerConfiguration>('tasks')).then((config) => {
this._taskSystemPromise = ProblemMatcherRegistry.onReady().then(() => {
let config = this.configurationService.getConfiguration<TaskConfig.ExternalTaskRunnerConfiguration>('tasks');
let parseErrors: string[] = config ? (<any>config).$parseErrors : null;
if (parseErrors) {
let isAffected = false;
......@@ -690,7 +722,8 @@ class TaskService extends EventEmitter implements ITaskService {
throw new TaskError(Severity.Info, nls.localize('TaskSystem.noConfiguration', 'No task runner configured.'), TaskErrors.NotConfigured);
}
let result: ITaskSystem = null;
let parseResult = TaskConfig.parse(config, this);
let problemReporter = new ProblemReporter(this.outputChannel);
let parseResult = TaskConfig.parse(config, problemReporter);
if (!parseResult.validationStatus.isOK()) {
this.outputChannel.show(true);
hasError = true;
......@@ -741,7 +774,7 @@ class TaskService extends EventEmitter implements ITaskService {
}
}
if (isAffected) {
this.log(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n'));
this.outputChannel.append(nls.localize('TaskSystem.invalidTaskJson', 'Error: The content of the tasks.json file has syntax errors. Please correct them before executing a task.\n'));
this.showOutput();
return TPromise.wrapError(undefined);
}
......@@ -785,12 +818,13 @@ class TaskService extends EventEmitter implements ITaskService {
if (!config) {
return undefined;
}
let parseResult = TaskConfig.parse(config, this);
let problemReporter = new ProblemReporter(this.outputChannel);
let parseResult = TaskConfig.parse(config, problemReporter);
if (!parseResult.validationStatus.isOK()) {
this.showOutput();
}
if (parseResult.validationStatus.isFatal()) {
this.log(nls.localize('TaskSystem.configurationErrors', 'Error: the provided task configuration has validation errors and can\'t not be used. Please correct the errors first.'));
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 undefined;
}
return parseResult.configuration;
......
......@@ -9,16 +9,40 @@ import Severity from 'vs/base/common/severity';
import * as UUID from 'vs/base/common/uuid';
import * as Platform from 'vs/base/common/platform';
import { ValidationStatus } from 'vs/base/common/parsers';
import { ProblemMatcher, FileLocationKind, ProblemPattern, ApplyToKind } from 'vs/platform/markers/common/problemMatcher';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/taskSystem';
import { parse, ParseResult, ILogger, ExternalTaskRunnerConfiguration } from 'vs/workbench/parts/tasks/common/taskConfiguration';
import { parse, ParseResult, IProblemReporter, ExternalTaskRunnerConfiguration } from 'vs/workbench/parts/tasks/common/taskConfiguration';
class ProblemReporter implements IProblemReporter {
private _validationStatus: ValidationStatus = new ValidationStatus();
class Logger implements ILogger {
public receivedMessage: boolean = false;
public lastMessage: string = undefined;
public log(message: string): void {
public info(message: string): void {
this.log(message);
}
public warn(message: string): void {
this.log(message);
}
public error(message: string): void {
this.log(message);
}
public fatal(message: string): void {
this.log(message);
}
public get status(): ValidationStatus {
return this._validationStatus;
}
private log(message: string): void {
this.receivedMessage = true;
this.lastMessage = message;
}
......@@ -281,9 +305,9 @@ class PatternBuilder {
}
function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, resolved: number) {
let logger = new Logger();
let result = parse(external, logger);
assert.ok(!logger.receivedMessage);
let reporter = new ProblemReporter();
let result = parse(external, reporter);
assert.ok(!reporter.receivedMessage);
let config = result.configuration;
let keys = Object.keys(config.tasks);
assert.strictEqual(keys.length, 1);
......@@ -294,10 +318,10 @@ function testDefaultProblemMatcher(external: ExternalTaskRunnerConfiguration, re
}
function testConfiguration(external: ExternalTaskRunnerConfiguration, builder: ConfiguationBuilder): void {
let logger = new Logger();
let result = parse(external, logger);
if (logger.receivedMessage) {
assert.ok(false, logger.lastMessage);
let reporter = new ProblemReporter();
let result = parse(external, reporter);
if (reporter.receivedMessage) {
assert.ok(false, reporter.lastMessage);
}
assertConfiguration(result, builder.result);
}
......@@ -719,7 +743,7 @@ suite('Tasks Configuration parsing tests', () => {
let external: ExternalTaskRunnerConfiguration = {
version: '0.1.0',
command: 'tsc',
problemMatcher: '$tsc'
problemMatcher: '$msCompile'
};
testDefaultProblemMatcher(external, 1);
});
......@@ -728,7 +752,7 @@ suite('Tasks Configuration parsing tests', () => {
let external: ExternalTaskRunnerConfiguration = {
version: '0.1.0',
command: 'tsc',
problemMatcher: ['$tsc', '$msCompile']
problemMatcher: ['$eslint-compact', '$msCompile']
};
testDefaultProblemMatcher(external, 2);
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册