Skip to content

Commit

Permalink
Merge pull request #39936 from doudou/problem_patterns_without_a_line
Browse files Browse the repository at this point in the history
allow for problem patterns without a line
  • Loading branch information
dbaeumer authored Feb 9, 2018
2 parents 3a8d09e + 8652645 commit 2434bf5
Show file tree
Hide file tree
Showing 2 changed files with 335 additions and 8 deletions.
83 changes: 75 additions & 8 deletions src/vs/platform/markers/common/problemMatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,30 @@ export module FileLocationKind {
}
}


export enum ProblemLocationKind {
File,
Location
}

export module ProblemLocationKind {
export function fromString(value: string): ProblemLocationKind {
value = value.toLowerCase();
if (value === 'file') {
return ProblemLocationKind.File;
} else if (value === 'location') {
return ProblemLocationKind.Location;
} else {
return undefined;
}
}
}

export interface ProblemPattern {
regexp: RegExp;

kind?: ProblemLocationKind;

file?: number;

message?: number;
Expand Down Expand Up @@ -138,6 +159,7 @@ interface Location {
}

interface ProblemData {
kind?: ProblemLocationKind;
file?: string;
location?: string;
line?: string;
Expand Down Expand Up @@ -357,6 +379,9 @@ class SingleLineMatcher extends AbstractLineMatcher {
public handle(lines: string[], start: number = 0): HandleResult {
Assert.ok(lines.length - start === 1);
let data: ProblemData = Object.create(null);
if (this.pattern.kind) {
data.kind = this.pattern.kind;
}
let matches = this.pattern.regexp.exec(lines[start]);
if (matches) {
this.fillProblemData(data, this.pattern, matches);
Expand Down Expand Up @@ -391,6 +416,7 @@ class MultiLineMatcher extends AbstractLineMatcher {
Assert.ok(lines.length - start === this.patterns.length);
this.data = Object.create(null);
let data = this.data;
data.kind = this.patterns[0].kind;
for (let i = 0; i < this.patterns.length; i++) {
let pattern = this.patterns[i];
let matches = pattern.regexp.exec(lines[i + start]);
Expand Down Expand Up @@ -435,6 +461,14 @@ export namespace Config {
*/
regexp?: string;

/**
* Whether the pattern matches a whole file, or a location (file/line)
*
* The default is to match for a location. Only valid on the
* first problem pattern in a multi line problem matcher.
*/
kind?: string;

/**
* The match group index of the filename.
* If omitted 1 is used.
Expand Down Expand Up @@ -700,7 +734,7 @@ export namespace Config {
}
}

class ProblemPatternParser extends Parser {
export class ProblemPatternParser extends Parser {

constructor(logger: IProblemReporter) {
super(logger);
Expand Down Expand Up @@ -728,6 +762,9 @@ class ProblemPatternParser extends Parser {

private createSingleProblemPattern(value: Config.ProblemPattern): ProblemPattern {
let result = this.doCreateSingleProblemPattern(value, true);
if (result.kind === undefined) {
result.kind = ProblemLocationKind.Location;
}
return this.validateProblemPattern([result]) ? result : null;
}

Expand All @@ -752,13 +789,19 @@ class ProblemPatternParser extends Parser {
}
result.push(pattern);
}
if (result[0].kind === undefined) {
result[0].kind = ProblemLocationKind.Location;
}
return this.validateProblemPattern(result) ? result : null;
}

private doCreateSingleProblemPattern(value: Config.ProblemPattern, setDefaults: boolean): ProblemPattern {
let result: ProblemPattern = {
regexp: this.createRegularExpression(value.regexp)
regexp: this.createRegularExpression(value.regexp),
};
if (value.kind) {
result.kind = ProblemLocationKind.fromString(value.kind);
}

function copyProperty(result: ProblemPattern, source: Config.ProblemPattern, resultKey: keyof ProblemPattern, sourceKey: keyof Config.ProblemPattern) {
let value = source[sourceKey];
Expand All @@ -779,7 +822,7 @@ class ProblemPatternParser extends Parser {
result.loop = value.loop;
}
if (setDefaults) {
if (result.location) {
if (result.location || result.kind === ProblemLocationKind.File) {
let defaultValue: Partial<ProblemPattern> = {
file: 1,
message: 0
Expand All @@ -801,7 +844,12 @@ class ProblemPatternParser extends Parser {
private validateProblemPattern(values: ProblemPattern[]): boolean {
let file: boolean, message: boolean, location: boolean, line: boolean;
let regexp: number = 0;
values.forEach(pattern => {
let locationKind = (values[0].kind === undefined) ? ProblemLocationKind.Location : values[0].kind;

values.forEach((pattern, i) => {
if (i !== 0 && pattern.kind) {
this.error(localize('ProblemPatternParser.problemPattern.kindProperty.notFirst', 'The problem pattern is invalid. The kind property must be provided only in the first element'));
}
file = file || !Types.isUndefined(pattern.file);
message = message || !Types.isUndefined(pattern.message);
location = location || !Types.isUndefined(pattern.location);
Expand All @@ -814,8 +862,12 @@ class ProblemPatternParser extends Parser {
this.error(localize('ProblemPatternParser.problemPattern.missingRegExp', 'The problem pattern is missing a regular expression.'));
return false;
}
if (!(file && message && (location || line))) {
this.error(localize('ProblemPatternParser.problemPattern.missingProperty', 'The problem pattern is invalid. It must have at least a file, message and line or location match group.'));
if (!(file && message)) {
this.error(localize('ProblemPatternParser.problemPattern.missingProperty', 'The problem pattern is invalid. It must have at least have a file and a message.'));
return false;
}
if (locationKind === ProblemLocationKind.Location && !(location || line)) {
this.error(localize('ProblemPatternParser.problemPattern.missingLocation', 'The problem pattern is invalid. It must either have kind: "file" or have a line or location match group.'));
return false;
}
return true;
Expand Down Expand Up @@ -880,6 +932,10 @@ export namespace Schemas {
type: 'string',
description: localize('ProblemPatternSchema.regexp', 'The regular expression to find an error, warning or info in the output.')
},
kind: {
type: 'string',
description: localize('ProblemPatternSchema.kind', 'whether the pattern matches a location (file and line) or only a file.')
},
file: {
type: 'integer',
description: localize('ProblemPatternSchema.file', 'The match group index of the filename. If omitted 1 is used.')
Expand Down Expand Up @@ -931,7 +987,7 @@ export namespace Schemas {
};


export const MultLileProblemPattern: IJSONSchema = {
export const MultiLineProblemPattern: IJSONSchema = {
type: 'array',
items: ProblemPattern
};
Expand Down Expand Up @@ -1030,6 +1086,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
private fillDefaults(): void {
this.add('msCompile', {
regexp: /^(?:\s+\d+\>)?([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\)\s*:\s+(error|warning|info)\s+(\w{1,2}\d+)\s*:\s*(.*)$/,
kind: ProblemLocationKind.Location,
file: 1,
location: 2,
severity: 3,
Expand All @@ -1038,13 +1095,15 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
});
this.add('gulp-tsc', {
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(\d+)\s+(.*)$/,
kind: ProblemLocationKind.Location,
file: 1,
location: 2,
code: 3,
message: 4
});
this.add('cpp', {
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(C\d+)\s*:\s*(.*)$/,
kind: ProblemLocationKind.Location,
file: 1,
location: 2,
severity: 3,
Expand All @@ -1053,6 +1112,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
});
this.add('csc', {
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(CS\d+)\s*:\s*(.*)$/,
kind: ProblemLocationKind.Location,
file: 1,
location: 2,
severity: 3,
Expand All @@ -1061,6 +1121,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
});
this.add('vb', {
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(BC\d+)\s*:\s*(.*)$/,
kind: ProblemLocationKind.Location,
file: 1,
location: 2,
severity: 3,
Expand All @@ -1069,12 +1130,14 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
});
this.add('lessCompile', {
regexp: /^\s*(.*) in file (.*) line no. (\d+)$/,
kind: ProblemLocationKind.Location,
message: 1,
file: 2,
line: 3
});
this.add('jshint', {
regexp: /^(.*):\s+line\s+(\d+),\s+col\s+(\d+),\s(.+?)(?:\s+\((\w)(\d+)\))?$/,
kind: ProblemLocationKind.Location,
file: 1,
line: 2,
character: 3,
Expand All @@ -1085,6 +1148,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
this.add('jshint-stylish', [
{
regexp: /^(.+)$/,
kind: ProblemLocationKind.Location,
file: 1
},
{
Expand All @@ -1100,6 +1164,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
this.add('eslint-compact', {
regexp: /^(.+):\sline\s(\d+),\scol\s(\d+),\s(Error|Warning|Info)\s-\s(.+)\s\((.+)\)$/,
file: 1,
kind: ProblemLocationKind.Location,
line: 2,
character: 3,
severity: 4,
Expand All @@ -1109,6 +1174,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
this.add('eslint-stylish', [
{
regexp: /^([^\s].*)$/,
kind: ProblemLocationKind.Location,
file: 1
},
{
Expand All @@ -1123,6 +1189,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
]);
this.add('go', {
regexp: /^([^:]*: )?((.:)?[^:]*):(\d+)(:(\d+))?: (.*)$/,
kind: ProblemLocationKind.Location,
file: 2,
line: 4,
character: 6,
Expand Down Expand Up @@ -1373,7 +1440,7 @@ export namespace Schemas {
description: localize('PatternTypeSchema.name', 'The name of a contributed or predefined pattern')
},
Schemas.ProblemPattern,
Schemas.MultLileProblemPattern
Schemas.MultiLineProblemPattern
],
description: localize('PatternTypeSchema.description', 'A problem pattern or the name of a contributed or predefined problem pattern. Can be omitted if base is specified.')
};
Expand Down
Loading

0 comments on commit 2434bf5

Please sign in to comment.