11import type { Chalk } from 'chalk' ;
22import * as fs from 'fs' ;
3- import micromatch from 'micromatch ' ;
3+ import picomatch from 'picomatch ' ;
44import * as path from 'path' ;
55import * as webpack from 'webpack' ;
66import type typescript from 'typescript' ;
@@ -38,6 +38,40 @@ function defaultErrorFormatter(error: ErrorInfo, colors: Chalk) {
3838 ) ;
3939}
4040
41+ /**
42+ * Build a file-matcher from a reportFiles pattern array that replicates
43+ * micromatch semantics: a file must match a positive pattern AND not match
44+ * any negative pattern. Returns null when reportFiles is empty (no filtering).
45+ */
46+ function makeReportFilesMatcher (
47+ reportFiles : string [ ] ,
48+ ) : ( ( fileName : string ) => boolean ) | null {
49+ if ( reportFiles . length === 0 ) {
50+ return null ;
51+ }
52+ const { positivePatterns, negativePatterns } = reportFiles . reduce < {
53+ positivePatterns : string [ ] ;
54+ negativePatterns : string [ ] ;
55+ } > (
56+ ( acc , p ) => {
57+ if ( p . startsWith ( '!' ) ) {
58+ acc . negativePatterns . push ( p . slice ( 1 ) ) ;
59+ } else {
60+ acc . positivePatterns . push ( p ) ;
61+ }
62+ return acc ;
63+ } ,
64+ { positivePatterns : [ ] , negativePatterns : [ ] } ,
65+ ) ;
66+ const matchPos = picomatch (
67+ positivePatterns . length > 0 ? positivePatterns : [ '**' ] ,
68+ ) ;
69+ const matchNeg =
70+ negativePatterns . length > 0 ? picomatch ( negativePatterns ) : null ;
71+ return ( fileName : string ) =>
72+ matchPos ( fileName ) && ! ( matchNeg && matchNeg ( fileName ) ) ;
73+ }
74+
4175/**
4276 * Take TypeScript errors, parse them and format to webpack errors
4377 * Optionally adds a file name
@@ -48,30 +82,21 @@ export function formatErrors(
4882 colors : Chalk ,
4983 compiler : typeof typescript ,
5084 merge : { file ?: string ; module ?: webpack . Module } ,
51- context : string
85+ context : string ,
5286) : webpack . WebpackError [ ] {
87+ const matchesReportFiles = makeReportFilesMatcher ( loaderOptions . reportFiles ) ;
88+
5389 return diagnostics === undefined
5490 ? [ ]
5591 : diagnostics
5692 . filter ( diagnostic => {
5793 if ( loaderOptions . ignoreDiagnostics . indexOf ( diagnostic . code ) !== - 1 ) {
5894 return false ;
5995 }
60- if (
61- loaderOptions . reportFiles . length > 0 &&
62- diagnostic . file !== undefined
63- ) {
64- const relativeFileName = path . relative (
65- context ,
66- diagnostic . file . fileName
67- ) ;
68- const matchResult = micromatch (
69- [ relativeFileName ] ,
70- loaderOptions . reportFiles
71- ) ;
72- if ( matchResult . length === 0 ) {
96+ if ( matchesReportFiles !== null &&
97+ diagnostic . file !== undefined &&
98+ ! matchesReportFiles ( path . relative ( context , diagnostic . file . fileName ) ) ) {
7399 return false ;
74- }
75100 }
76101 return true ;
77102 } )
@@ -88,7 +113,7 @@ export function formatErrors(
88113 ] . toLowerCase ( ) as Severity ,
89114 content : compiler . flattenDiagnosticMessageText (
90115 diagnostic . messageText ,
91- constants . EOL
116+ constants . EOL ,
92117 ) ,
93118 file : file === undefined ? '' : path . normalize ( file . fileName ) ,
94119 line : start === undefined ? 0 : start . line ,
@@ -106,7 +131,7 @@ export function formatErrors(
106131 message ,
107132 merge . file === undefined ? errorInfo . file : merge . file ,
108133 start ,
109- end
134+ end ,
110135 ) ;
111136
112137 return Object . assign ( error , merge ) ;
@@ -116,7 +141,7 @@ export function formatErrors(
116141function getFileLocations (
117142 file : typescript . SourceFile ,
118143 position : number ,
119- length = 0
144+ length = 0 ,
120145) {
121146 const startLC = file . getLineAndCharacterOfPosition ( position ) ;
122147 const start : FileLocation = {
@@ -136,7 +161,7 @@ function getFileLocations(
136161
137162export function fsReadFile (
138163 fileName : string ,
139- encoding : BufferEncoding | undefined = 'utf8'
164+ encoding : BufferEncoding | undefined = 'utf8' ,
140165) {
141166 fileName = path . normalize ( fileName ) ;
142167 try {
@@ -151,7 +176,7 @@ export function makeError(
151176 message : string ,
152177 file : string ,
153178 location ?: FileLocation ,
154- endLocation ?: FileLocation
179+ endLocation ?: FileLocation ,
155180) : webpack . WebpackError {
156181 if ( isWebpack5 ) {
157182 const error = new webpack . WebpackError ( message ) ;
@@ -163,7 +188,7 @@ export function makeError(
163188 error . details = tsLoaderSource ( loaderOptions ) ;
164189
165190 return error ;
166- }
191+ }
167192
168193 return {
169194 message,
@@ -185,7 +210,7 @@ interface WebpackSourcePosition {
185210
186211function makeWebpackLocation (
187212 location : FileLocation ,
188- endLocation ?: FileLocation
213+ endLocation ?: FileLocation ,
189214) {
190215 const start : WebpackSourcePosition = {
191216 line : location . line ,
@@ -205,7 +230,7 @@ export function tsLoaderSource(loaderOptions: LoaderOptions) {
205230export function appendSuffixIfMatch (
206231 patterns : ( RegExp | string ) [ ] ,
207232 filePath : string ,
208- suffix : string
233+ suffix : string ,
209234) : string {
210235 if ( patterns . length > 0 ) {
211236 for ( const regexp of patterns ) {
@@ -219,7 +244,7 @@ export function appendSuffixIfMatch(
219244
220245export function appendSuffixesIfMatch (
221246 suffixDict : { [ suffix : string ] : ( RegExp | string ) [ ] } ,
222- filePath : string
247+ filePath : string ,
223248) : string {
224249 let amendedPath = filePath ;
225250 for ( const suffix in suffixDict ) {
@@ -243,10 +268,10 @@ export function unorderedRemoveItem<T>(array: T[], item: T): boolean {
243268export function populateDependencyGraph (
244269 resolvedModules : ResolvedModule [ ] ,
245270 instance : TSInstance ,
246- containingFile : string
271+ containingFile : string ,
247272) {
248273 resolvedModules = resolvedModules . filter (
249- mod => mod !== null && mod !== undefined
274+ mod => mod !== null && mod !== undefined ,
250275 ) ;
251276 if ( resolvedModules . length ) {
252277 const containingFileKey = instance . filePathKeyMapper ( containingFile ) ;
@@ -268,7 +293,7 @@ export function populateReverseDependencyGraph(instance: TSInstance) {
268293 instance . solutionBuilderHost
269294 ? getInputFileNameFromOutput ( instance , resolvedFileName ) ||
270295 resolvedFileName
271- : resolvedFileName
296+ : resolvedFileName ,
272297 ) ;
273298 let map = reverseDependencyGraph . get ( key ) ;
274299 if ( ! map ) {
@@ -287,7 +312,7 @@ export function populateReverseDependencyGraph(instance: TSInstance) {
287312export function collectAllDependants (
288313 reverseDependencyGraph : ReverseDependencyGraph ,
289314 fileName : FilePathKey ,
290- result : Map < FilePathKey , true > = new Map ( )
315+ result : Map < FilePathKey , true > = new Map ( ) ,
291316) : Map < FilePathKey , true > {
292317 result . set ( fileName , true ) ;
293318 const dependants = reverseDependencyGraph . get ( fileName ) ;
@@ -316,7 +341,8 @@ export function ensureProgram(instance: TSInstance) {
316341 instance . watchHost . updateRootFileNames ( ) ;
317342 }
318343 if ( instance . watchOfFilesAndCompilerOptions ) {
319- instance . builderProgram = instance . watchOfFilesAndCompilerOptions . getProgram ( ) ;
344+ instance . builderProgram =
345+ instance . watchOfFilesAndCompilerOptions . getProgram ( ) ;
320346 instance . program = instance . builderProgram . getProgram ( ) ;
321347 }
322348 instance . hasUnaccountedModifiedFiles = false ;
@@ -342,14 +368,14 @@ export function isReferencedFile(instance: TSInstance, filePath: string) {
342368 return (
343369 ! ! instance . solutionBuilderHost &&
344370 ! ! instance . solutionBuilderHost . watchedFiles . get (
345- instance . filePathKeyMapper ( filePath )
371+ instance . filePathKeyMapper ( filePath ) ,
346372 )
347373 ) ;
348374}
349375
350376export function useCaseSensitiveFileNames (
351377 compiler : typeof typescript ,
352- loaderOptions : LoaderOptions
378+ loaderOptions : LoaderOptions ,
353379) {
354380 return loaderOptions . useCaseSensitiveFileNames !== undefined
355381 ? loaderOptions . useCaseSensitiveFileNames
0 commit comments