@@ -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+
4564export 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
140161interface ProblemData {
162+ kind ?: ProblemLocationKind ;
141163 file ?: string ;
142164 location ?: string ;
143165 line ?: string ;
@@ -353,6 +375,9 @@ class SingleLineMatcher extends AbstractLineMatcher {
353375 public handle ( lines : string [ ] , start : number = 0 ) : HandleResult {
354376 Assert . ok ( lines . length - start === 1 ) ;
355377 let data : ProblemData = Object . create ( null ) ;
378+ if ( this . pattern . kind ) {
379+ data . kind = this . pattern . kind ;
380+ }
356381 let matches = this . pattern . regexp . exec ( lines [ start ] ) ;
357382 if ( matches ) {
358383 this . fillProblemData ( data , this . pattern , matches ) ;
@@ -387,6 +412,7 @@ class MultiLineMatcher extends AbstractLineMatcher {
387412 Assert . ok ( lines . length - start === this . patterns . length ) ;
388413 this . data = Object . create ( null ) ;
389414 let data = this . data ;
415+ data . kind = this . patterns [ 0 ] . kind ;
390416 for ( let i = 0 ; i < this . patterns . length ; i ++ ) {
391417 let pattern = this . patterns [ i ] ;
392418 let matches = pattern . regexp . exec ( lines [ i + start ] ) ;
@@ -431,6 +457,14 @@ export namespace Config {
431457 */
432458 regexp ?: string ;
433459
460+ /**
461+ * Whether the pattern matches a whole file, or a location (file/line)
462+ *
463+ * The default is to match for a location. Only valid on the
464+ * first problem pattern in a multi line problem matcher.
465+ */
466+ kind ?: string ;
467+
434468 /**
435469 * The match group index of the filename.
436470 * If omitted 1 is used.
@@ -696,7 +730,7 @@ export namespace Config {
696730 }
697731}
698732
699- class ProblemPatternParser extends Parser {
733+ export class ProblemPatternParser extends Parser {
700734
701735 constructor ( logger : IProblemReporter ) {
702736 super ( logger ) ;
@@ -724,6 +758,9 @@ class ProblemPatternParser extends Parser {
724758
725759 private createSingleProblemPattern ( value : Config . ProblemPattern ) : ProblemPattern {
726760 let result = this . doCreateSingleProblemPattern ( value , true ) ;
761+ if ( result . kind === undefined ) {
762+ result . kind = ProblemLocationKind . Location ;
763+ }
727764 return this . validateProblemPattern ( [ result ] ) ? result : null ;
728765 }
729766
@@ -748,13 +785,19 @@ class ProblemPatternParser extends Parser {
748785 }
749786 result . push ( pattern ) ;
750787 }
788+ if ( result [ 0 ] . kind === undefined ) {
789+ result [ 0 ] . kind = ProblemLocationKind . Location ;
790+ }
751791 return this . validateProblemPattern ( result ) ? result : null ;
752792 }
753793
754794 private doCreateSingleProblemPattern ( value : Config . ProblemPattern , setDefaults : boolean ) : ProblemPattern {
755795 let result : ProblemPattern = {
756- regexp : this . createRegularExpression ( value . regexp )
796+ regexp : this . createRegularExpression ( value . regexp ) ,
757797 } ;
798+ if ( value . kind ) {
799+ result . kind = ProblemLocationKind . fromString ( value . kind ) ;
800+ }
758801
759802 function copyProperty ( result : ProblemPattern , source : Config . ProblemPattern , resultKey : keyof ProblemPattern , sourceKey : keyof Config . ProblemPattern ) {
760803 let value = source [ sourceKey ] ;
@@ -775,7 +818,7 @@ class ProblemPatternParser extends Parser {
775818 result . loop = value . loop ;
776819 }
777820 if ( setDefaults ) {
778- if ( result . location ) {
821+ if ( result . location || result . kind === ProblemLocationKind . File ) {
779822 let defaultValue : Partial < ProblemPattern > = {
780823 file : 1 ,
781824 message : 0
@@ -797,7 +840,12 @@ class ProblemPatternParser extends Parser {
797840 private validateProblemPattern ( values : ProblemPattern [ ] ) : boolean {
798841 let file : boolean , message : boolean , location : boolean , line : boolean ;
799842 let regexp : number = 0 ;
800- values . forEach ( pattern => {
843+ let locationKind = ( values [ 0 ] . kind === undefined ) ? ProblemLocationKind . Location : values [ 0 ] . kind ;
844+
845+ values . forEach ( ( pattern , i ) => {
846+ if ( i !== 0 && pattern . kind ) {
847+ this . error ( localize ( 'ProblemPatternParser.problemPattern.kindProperty.notFirst' , 'The problem pattern is invalid. The kind property must be provided only in the first element' ) ) ;
848+ }
801849 file = file || ! Types . isUndefined ( pattern . file ) ;
802850 message = message || ! Types . isUndefined ( pattern . message ) ;
803851 location = location || ! Types . isUndefined ( pattern . location ) ;
@@ -810,8 +858,12 @@ class ProblemPatternParser extends Parser {
810858 this . error ( localize ( 'ProblemPatternParser.problemPattern.missingRegExp' , 'The problem pattern is missing a regular expression.' ) ) ;
811859 return false ;
812860 }
813- if ( ! ( file && message && ( location || line ) ) ) {
814- 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.' ) ) ;
861+ if ( ! ( file && message ) ) {
862+ this . error ( localize ( 'ProblemPatternParser.problemPattern.missingProperty' , 'The problem pattern is invalid. It must have at least have a file and a message.' ) ) ;
863+ return false ;
864+ }
865+ if ( locationKind === ProblemLocationKind . Location && ! ( location || line ) ) {
866+ 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.' ) ) ;
815867 return false ;
816868 }
817869 return true ;
@@ -876,6 +928,10 @@ export namespace Schemas {
876928 type : 'string' ,
877929 description : localize ( 'ProblemPatternSchema.regexp' , 'The regular expression to find an error, warning or info in the output.' )
878930 } ,
931+ kind : {
932+ type : 'string' ,
933+ description : localize ( 'ProblemPatternSchema.kind' , 'whether the pattern matches a location (file and line) or only a file.' )
934+ } ,
879935 file : {
880936 type : 'integer' ,
881937 description : localize ( 'ProblemPatternSchema.file' , 'The match group index of the filename. If omitted 1 is used.' )
@@ -1026,6 +1082,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10261082 private fillDefaults ( ) : void {
10271083 this . add ( 'msCompile' , {
10281084 regexp : / ^ (?: \s + \d + \> ) ? ( [ ^ \s ] .* ) \( ( \d + | \d + , \d + | \d + , \d + , \d + , \d + ) \) \s * : \s + ( e r r o r | w a r n i n g | i n f o ) \s + ( \w { 1 , 2 } \d + ) \s * : \s * ( .* ) $ / ,
1085+ kind : ProblemLocationKind . Location ,
10291086 file : 1 ,
10301087 location : 2 ,
10311088 severity : 3 ,
@@ -1034,13 +1091,15 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10341091 } ) ;
10351092 this . add ( 'gulp-tsc' , {
10361093 regexp : / ^ ( [ ^ \s ] .* ) \( ( \d + | \d + , \d + | \d + , \d + , \d + , \d + ) \) : \s + ( \d + ) \s + ( .* ) $ / ,
1094+ kind : ProblemLocationKind . Location ,
10371095 file : 1 ,
10381096 location : 2 ,
10391097 code : 3 ,
10401098 message : 4
10411099 } ) ;
10421100 this . add ( 'cpp' , {
10431101 regexp : / ^ ( [ ^ \s ] .* ) \( ( \d + | \d + , \d + | \d + , \d + , \d + , \d + ) \) : \s + ( e r r o r | w a r n i n g | i n f o ) \s + ( C \d + ) \s * : \s * ( .* ) $ / ,
1102+ kind : ProblemLocationKind . Location ,
10441103 file : 1 ,
10451104 location : 2 ,
10461105 severity : 3 ,
@@ -1049,6 +1108,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10491108 } ) ;
10501109 this . add ( 'csc' , {
10511110 regexp : / ^ ( [ ^ \s ] .* ) \( ( \d + | \d + , \d + | \d + , \d + , \d + , \d + ) \) : \s + ( e r r o r | w a r n i n g | i n f o ) \s + ( C S \d + ) \s * : \s * ( .* ) $ / ,
1111+ kind : ProblemLocationKind . Location ,
10521112 file : 1 ,
10531113 location : 2 ,
10541114 severity : 3 ,
@@ -1057,6 +1117,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10571117 } ) ;
10581118 this . add ( 'vb' , {
10591119 regexp : / ^ ( [ ^ \s ] .* ) \( ( \d + | \d + , \d + | \d + , \d + , \d + , \d + ) \) : \s + ( e r r o r | w a r n i n g | i n f o ) \s + ( B C \d + ) \s * : \s * ( .* ) $ / ,
1120+ kind : ProblemLocationKind . Location ,
10601121 file : 1 ,
10611122 location : 2 ,
10621123 severity : 3 ,
@@ -1065,12 +1126,14 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10651126 } ) ;
10661127 this . add ( 'lessCompile' , {
10671128 regexp : / ^ \s * ( .* ) i n f i l e ( .* ) l i n e n o . ( \d + ) $ / ,
1129+ kind : ProblemLocationKind . Location ,
10681130 message : 1 ,
10691131 file : 2 ,
10701132 line : 3
10711133 } ) ;
10721134 this . add ( 'jshint' , {
10731135 regexp : / ^ ( .* ) : \s + l i n e \s + ( \d + ) , \s + c o l \s + ( \d + ) , \s ( .+ ?) (?: \s + \( ( \w ) ( \d + ) \) ) ? $ / ,
1136+ kind : ProblemLocationKind . Location ,
10741137 file : 1 ,
10751138 line : 2 ,
10761139 character : 3 ,
@@ -1081,6 +1144,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10811144 this . add ( 'jshint-stylish' , [
10821145 {
10831146 regexp : / ^ ( .+ ) $ / ,
1147+ kind : ProblemLocationKind . Location ,
10841148 file : 1
10851149 } ,
10861150 {
@@ -1096,6 +1160,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
10961160 this . add ( 'eslint-compact' , {
10971161 regexp : / ^ ( .+ ) : \s l i n e \s ( \d + ) , \s c o l \s ( \d + ) , \s ( E r r o r | W a r n i n g | I n f o ) \s - \s ( .+ ) \s \( ( .+ ) \) $ / ,
10981162 file : 1 ,
1163+ kind : ProblemLocationKind . Location ,
10991164 line : 2 ,
11001165 character : 3 ,
11011166 severity : 4 ,
@@ -1105,6 +1170,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
11051170 this . add ( 'eslint-stylish' , [
11061171 {
11071172 regexp : / ^ ( [ ^ \s ] .* ) $ / ,
1173+ kind : ProblemLocationKind . Location ,
11081174 file : 1
11091175 } ,
11101176 {
@@ -1119,6 +1185,7 @@ class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
11191185 ] ) ;
11201186 this . add ( 'go' , {
11211187 regexp : / ^ ( [ ^ : ] * : ) ? ( ( .: ) ? [ ^ : ] * ) : ( \d + ) ( : ( \d + ) ) ? : ( .* ) $ / ,
1188+ kind : ProblemLocationKind . Location ,
11221189 file : 2 ,
11231190 line : 4 ,
11241191 character : 6 ,
@@ -1369,7 +1436,7 @@ export namespace Schemas {
13691436 description : localize ( 'PatternTypeSchema.name' , 'The name of a contributed or predefined pattern' )
13701437 } ,
13711438 Schemas . ProblemPattern ,
1372- Schemas . MultLileProblemPattern
1439+ Schemas . MultiLineProblemPattern
13731440 ] ,
13741441 description : localize ( 'PatternTypeSchema.description' , 'A problem pattern or the name of a contributed or predefined problem pattern. Can be omitted if base is specified.' )
13751442 } ;
0 commit comments