Skip to content

Commit 2434bf5

Browse files
authored
Merge pull request #39936 from doudou/problem_patterns_without_a_line
allow for problem patterns without a line
2 parents 3a8d09e + 8652645 commit 2434bf5

File tree

2 files changed

+335
-8
lines changed

2 files changed

+335
-8
lines changed

src/vs/platform/markers/common/problemMatcher.ts

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,30 @@ export module FileLocationKind {
4242
}
4343
}
4444

45+
46+
export enum ProblemLocationKind {
47+
File,
48+
Location
49+
}
50+
51+
export module ProblemLocationKind {
52+
export function fromString(value: string): ProblemLocationKind {
53+
value = value.toLowerCase();
54+
if (value === 'file') {
55+
return ProblemLocationKind.File;
56+
} else if (value === 'location') {
57+
return ProblemLocationKind.Location;
58+
} else {
59+
return undefined;
60+
}
61+
}
62+
}
63+
4564
export interface ProblemPattern {
4665
regexp: RegExp;
4766

67+
kind?: ProblemLocationKind;
68+
4869
file?: number;
4970

5071
message?: number;
@@ -138,6 +159,7 @@ interface Location {
138159
}
139160

140161
interface ProblemData {
162+
kind?: ProblemLocationKind;
141163
file?: string;
142164
location?: string;
143165
line?: string;
@@ -357,6 +379,9 @@ class SingleLineMatcher extends AbstractLineMatcher {
357379
public handle(lines: string[], start: number = 0): HandleResult {
358380
Assert.ok(lines.length - start === 1);
359381
let data: ProblemData = Object.create(null);
382+
if (this.pattern.kind) {
383+
data.kind = this.pattern.kind;
384+
}
360385
let matches = this.pattern.regexp.exec(lines[start]);
361386
if (matches) {
362387
this.fillProblemData(data, this.pattern, matches);
@@ -391,6 +416,7 @@ class MultiLineMatcher extends AbstractLineMatcher {
391416
Assert.ok(lines.length - start === this.patterns.length);
392417
this.data = Object.create(null);
393418
let data = this.data;
419+
data.kind = this.patterns[0].kind;
394420
for (let i = 0; i < this.patterns.length; i++) {
395421
let pattern = this.patterns[i];
396422
let matches = pattern.regexp.exec(lines[i + start]);
@@ -435,6 +461,14 @@ export namespace Config {
435461
*/
436462
regexp?: string;
437463

464+
/**
465+
* Whether the pattern matches a whole file, or a location (file/line)
466+
*
467+
* The default is to match for a location. Only valid on the
468+
* first problem pattern in a multi line problem matcher.
469+
*/
470+
kind?: string;
471+
438472
/**
439473
* The match group index of the filename.
440474
* If omitted 1 is used.
@@ -700,7 +734,7 @@ export namespace Config {
700734
}
701735
}
702736

703-
class ProblemPatternParser extends Parser {
737+
export class ProblemPatternParser extends Parser {
704738

705739
constructor(logger: IProblemReporter) {
706740
super(logger);
@@ -728,6 +762,9 @@ class ProblemPatternParser extends Parser {
728762

729763
private createSingleProblemPattern(value: Config.ProblemPattern): ProblemPattern {
730764
let result = this.doCreateSingleProblemPattern(value, true);
765+
if (result.kind === undefined) {
766+
result.kind = ProblemLocationKind.Location;
767+
}
731768
return this.validateProblemPattern([result]) ? result : null;
732769
}
733770

@@ -752,13 +789,19 @@ class ProblemPatternParser extends Parser {
752789
}
753790
result.push(pattern);
754791
}
792+
if (result[0].kind === undefined) {
793+
result[0].kind = ProblemLocationKind.Location;
794+
}
755795
return this.validateProblemPattern(result) ? result : null;
756796
}
757797

758798
private doCreateSingleProblemPattern(value: Config.ProblemPattern, setDefaults: boolean): ProblemPattern {
759799
let result: ProblemPattern = {
760-
regexp: this.createRegularExpression(value.regexp)
800+
regexp: this.createRegularExpression(value.regexp),
761801
};
802+
if (value.kind) {
803+
result.kind = ProblemLocationKind.fromString(value.kind);
804+
}
762805

763806
function copyProperty(result: ProblemPattern, source: Config.ProblemPattern, resultKey: keyof ProblemPattern, sourceKey: keyof Config.ProblemPattern) {
764807
let value = source[sourceKey];
@@ -779,7 +822,7 @@ class ProblemPatternParser extends Parser {
779822
result.loop = value.loop;
780823
}
781824
if (setDefaults) {
782-
if (result.location) {
825+
if (result.location || result.kind === ProblemLocationKind.File) {
783826
let defaultValue: Partial<ProblemPattern> = {
784827
file: 1,
785828
message: 0
@@ -801,7 +844,12 @@ class ProblemPatternParser extends Parser {
801844
private validateProblemPattern(values: ProblemPattern[]): boolean {
802845
let file: boolean, message: boolean, location: boolean, line: boolean;
803846
let regexp: number = 0;
804-
values.forEach(pattern => {
847+
let locationKind = (values[0].kind === undefined) ? ProblemLocationKind.Location : values[0].kind;
848+
849+
values.forEach((pattern, i) => {
850+
if (i !== 0 && pattern.kind) {
851+
this.error(localize('ProblemPatternParser.problemPattern.kindProperty.notFirst', 'The problem pattern is invalid. The kind property must be provided only in the first element'));
852+
}
805853
file = file || !Types.isUndefined(pattern.file);
806854
message = message || !Types.isUndefined(pattern.message);
807855
location = location || !Types.isUndefined(pattern.location);
@@ -814,8 +862,12 @@ class ProblemPatternParser extends Parser {
814862
this.error(localize('ProblemPatternParser.problemPattern.missingRegExp', 'The problem pattern is missing a regular expression.'));
815863
return false;
816864
}
817-
if (!(file && message && (location || line))) {
818-
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.'));
865+
if (!(file && message)) {
866+
this.error(localize('ProblemPatternParser.problemPattern.missingProperty', 'The problem pattern is invalid. It must have at least have a file and a message.'));
867+
return false;
868+
}
869+
if (locationKind === ProblemLocationKind.Location && !(location || line)) {
870+
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.'));
819871
return false;
820872
}
821873
return true;
@@ -880,6 +932,10 @@ export namespace Schemas {
880932
type: 'string',
881933
description: localize('ProblemPatternSchema.regexp', 'The regular expression to find an error, warning or info in the output.')
882934
},
935+
kind: {
936+
type: 'string',
937+
description: localize('ProblemPatternSchema.kind', 'whether the pattern matches a location (file and line) or only a file.')
938+
},
883939
file: {
884940
type: 'integer',
885941
description: localize('ProblemPatternSchema.file', 'The match group index of the filename. If omitted 1 is used.')
@@ -931,7 +987,7 @@ export namespace Schemas {
931987
};
932988

933989

934-
export const MultLileProblemPattern: IJSONSchema = {
990+
export const MultiLineProblemPattern: IJSONSchema = {
935991
type: 'array',
936992
items: ProblemPattern
937993
};
@@ -1030,6 +1086,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10301086
private fillDefaults(): void {
10311087
this.add('msCompile', {
10321088
regexp: /^(?:\s+\d+\>)?([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\)\s*:\s+(error|warning|info)\s+(\w{1,2}\d+)\s*:\s*(.*)$/,
1089+
kind: ProblemLocationKind.Location,
10331090
file: 1,
10341091
location: 2,
10351092
severity: 3,
@@ -1038,13 +1095,15 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10381095
});
10391096
this.add('gulp-tsc', {
10401097
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(\d+)\s+(.*)$/,
1098+
kind: ProblemLocationKind.Location,
10411099
file: 1,
10421100
location: 2,
10431101
code: 3,
10441102
message: 4
10451103
});
10461104
this.add('cpp', {
10471105
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(C\d+)\s*:\s*(.*)$/,
1106+
kind: ProblemLocationKind.Location,
10481107
file: 1,
10491108
location: 2,
10501109
severity: 3,
@@ -1053,6 +1112,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10531112
});
10541113
this.add('csc', {
10551114
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(CS\d+)\s*:\s*(.*)$/,
1115+
kind: ProblemLocationKind.Location,
10561116
file: 1,
10571117
location: 2,
10581118
severity: 3,
@@ -1061,6 +1121,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10611121
});
10621122
this.add('vb', {
10631123
regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(BC\d+)\s*:\s*(.*)$/,
1124+
kind: ProblemLocationKind.Location,
10641125
file: 1,
10651126
location: 2,
10661127
severity: 3,
@@ -1069,12 +1130,14 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10691130
});
10701131
this.add('lessCompile', {
10711132
regexp: /^\s*(.*) in file (.*) line no. (\d+)$/,
1133+
kind: ProblemLocationKind.Location,
10721134
message: 1,
10731135
file: 2,
10741136
line: 3
10751137
});
10761138
this.add('jshint', {
10771139
regexp: /^(.*):\s+line\s+(\d+),\s+col\s+(\d+),\s(.+?)(?:\s+\((\w)(\d+)\))?$/,
1140+
kind: ProblemLocationKind.Location,
10781141
file: 1,
10791142
line: 2,
10801143
character: 3,
@@ -1085,6 +1148,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10851148
this.add('jshint-stylish', [
10861149
{
10871150
regexp: /^(.+)$/,
1151+
kind: ProblemLocationKind.Location,
10881152
file: 1
10891153
},
10901154
{
@@ -1100,6 +1164,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
11001164
this.add('eslint-compact', {
11011165
regexp: /^(.+):\sline\s(\d+),\scol\s(\d+),\s(Error|Warning|Info)\s-\s(.+)\s\((.+)\)$/,
11021166
file: 1,
1167+
kind: ProblemLocationKind.Location,
11031168
line: 2,
11041169
character: 3,
11051170
severity: 4,
@@ -1109,6 +1174,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
11091174
this.add('eslint-stylish', [
11101175
{
11111176
regexp: /^([^\s].*)$/,
1177+
kind: ProblemLocationKind.Location,
11121178
file: 1
11131179
},
11141180
{
@@ -1123,6 +1189,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
11231189
]);
11241190
this.add('go', {
11251191
regexp: /^([^:]*: )?((.:)?[^:]*):(\d+)(:(\d+))?: (.*)$/,
1192+
kind: ProblemLocationKind.Location,
11261193
file: 2,
11271194
line: 4,
11281195
character: 6,
@@ -1373,7 +1440,7 @@ export namespace Schemas {
13731440
description: localize('PatternTypeSchema.name', 'The name of a contributed or predefined pattern')
13741441
},
13751442
Schemas.ProblemPattern,
1376-
Schemas.MultLileProblemPattern
1443+
Schemas.MultiLineProblemPattern
13771444
],
13781445
description: localize('PatternTypeSchema.description', 'A problem pattern or the name of a contributed or predefined problem pattern. Can be omitted if base is specified.')
13791446
};

0 commit comments

Comments
 (0)