@@ -96,9 +96,10 @@ export interface Options {
96
96
rulesDirectory ?: string | string [ ] ;
97
97
98
98
/**
99
- * That TSLint produces the correct output for the specified directory.
99
+ * Run the tests in the given directories to ensure a (custom) TSLint rule's output matches the expected output.
100
+ * When this property is `true` the `files` property is used to specify the directories from which the tests should be executed.
100
101
*/
101
- test ?: string ;
102
+ test ?: boolean ;
102
103
103
104
/**
104
105
* Whether to enable type checking when linting a project.
@@ -122,7 +123,7 @@ export async function run(options: Options, logger: Logger): Promise<Status> {
122
123
return await runWorker ( options , logger ) ;
123
124
} catch ( error ) {
124
125
if ( error instanceof FatalError ) {
125
- logger . error ( error . message ) ;
126
+ logger . error ( ` ${ error . message } \n` ) ;
126
127
return Status . FatalError ;
127
128
}
128
129
throw error ;
@@ -142,7 +143,7 @@ async function runWorker(options: Options, logger: Logger): Promise<Status> {
142
143
if ( options . test ) {
143
144
const test = await import ( "./test" ) ;
144
145
const results = test . runTests ( ( options . files || [ ] ) . map ( trimSingleQuotes ) , options . rulesDirectory ) ;
145
- return test . consoleTestResultsHandler ( results ) ? Status . Ok : Status . FatalError ;
146
+ return test . consoleTestResultsHandler ( results , logger ) ? Status . Ok : Status . FatalError ;
146
147
}
147
148
148
149
if ( options . config && ! fs . existsSync ( options . config ) ) {
@@ -151,20 +152,20 @@ async function runWorker(options: Options, logger: Logger): Promise<Status> {
151
152
152
153
const { output, errorCount } = await runLinter ( options , logger ) ;
153
154
if ( output && output . trim ( ) ) {
154
- logger . log ( output ) ;
155
+ logger . log ( ` ${ output } \n` ) ;
155
156
}
156
157
return options . force || errorCount === 0 ? Status . Ok : Status . LintError ;
157
158
}
158
159
159
160
async function runLinter ( options : Options , logger : Logger ) : Promise < LintResult > {
160
- const { files, program } = resolveFilesAndProgram ( options ) ;
161
+ const { files, program } = resolveFilesAndProgram ( options , logger ) ;
161
162
// if type checking, run the type checker
162
163
if ( program && options . typeCheck ) {
163
164
const diagnostics = ts . getPreEmitDiagnostics ( program ) ;
164
165
if ( diagnostics . length !== 0 ) {
165
166
const message = diagnostics . map ( ( d ) => showDiagnostic ( d , program , options . outputAbsolutePaths ) ) . join ( "\n" ) ;
166
167
if ( options . force ) {
167
- logger . error ( message ) ;
168
+ logger . error ( ` ${ message } \n` ) ;
168
169
} else {
169
170
throw new FatalError ( message ) ;
170
171
}
@@ -173,12 +174,15 @@ async function runLinter(options: Options, logger: Logger): Promise<LintResult>
173
174
return doLinting ( options , files , program , logger ) ;
174
175
}
175
176
176
- function resolveFilesAndProgram ( { files, project, exclude, outputAbsolutePaths } : Options ) : { files : string [ ] ; program ?: ts . Program } {
177
+ function resolveFilesAndProgram (
178
+ { files, project, exclude, outputAbsolutePaths } : Options ,
179
+ logger : Logger ,
180
+ ) : { files : string [ ] ; program ?: ts . Program } {
177
181
// remove single quotes which break matching on Windows when glob is passed in single quotes
178
182
exclude = exclude . map ( trimSingleQuotes ) ;
179
183
180
184
if ( project === undefined ) {
181
- return { files : resolveGlobs ( files , exclude , outputAbsolutePaths ) } ;
185
+ return { files : resolveGlobs ( files , exclude , outputAbsolutePaths , logger ) } ;
182
186
}
183
187
184
188
const projectPath = findTsconfig ( project ) ;
@@ -202,7 +206,7 @@ function resolveFilesAndProgram({ files, project, exclude, outputAbsolutePaths }
202
206
if ( fs . existsSync ( file ) ) {
203
207
throw new FatalError ( `'${ file } ' is not included in project.` ) ;
204
208
}
205
- console . warn ( `'${ file } ' does not exist. This will be an error in TSLint 6.` ) ; // TODO make this an error in v6.0.0
209
+ logger . error ( `'${ file } ' does not exist. This will be an error in TSLint 6.\n ` ) ; // TODO make this an error in v6.0.0
206
210
}
207
211
}
208
212
}
@@ -217,15 +221,15 @@ function filterFiles(files: string[], patterns: string[], include: boolean): str
217
221
return files . filter ( ( file ) => include === matcher . some ( ( pattern ) => pattern . match ( file ) ) ) ;
218
222
}
219
223
220
- function resolveGlobs ( files : string [ ] , ignore : string [ ] , outputAbsolutePaths ? : boolean ) : string [ ] {
224
+ function resolveGlobs ( files : string [ ] , ignore : string [ ] , outputAbsolutePaths : boolean | undefined , logger : Logger ) : string [ ] {
221
225
const results = flatMap (
222
226
files ,
223
227
( file ) => glob . sync ( trimSingleQuotes ( file ) , { ignore, nodir : true } ) ,
224
228
) ;
225
229
// warn if `files` contains non-existent files, that are not patters and not excluded by any of the exclude patterns
226
230
for ( const file of filterFiles ( files , ignore , false ) ) {
227
- if ( ! glob . hasMagic ( file ) ) {
228
- console . warn ( `'${ file } ' does not exist. This will be an error in TSLint 6.` ) ; // TODO make this an error in v6.0.0
231
+ if ( ! glob . hasMagic ( file ) && ! results . some ( createMinimatchFilter ( file ) ) ) {
232
+ logger . error ( `'${ file } ' does not exist. This will be an error in TSLint 6.\n ` ) ; // TODO make this an error in v6.0.0
229
233
}
230
234
}
231
235
const cwd = process . cwd ( ) ;
@@ -248,17 +252,17 @@ async function doLinting(
248
252
let configFile : IConfigurationFile | undefined ;
249
253
250
254
for ( const file of files ) {
255
+ const folder = path . dirname ( file ) ;
256
+ if ( lastFolder !== folder ) {
257
+ configFile = findConfiguration ( possibleConfigAbsolutePath , folder ) . results ;
258
+ lastFolder = folder ;
259
+ }
251
260
if ( isFileExcluded ( file ) ) {
252
261
continue ;
253
262
}
254
263
255
264
const contents = program !== undefined ? program . getSourceFile ( file ) . text : await tryReadFile ( file , logger ) ;
256
265
if ( contents !== undefined ) {
257
- const folder = path . dirname ( file ) ;
258
- if ( lastFolder !== folder ) {
259
- configFile = findConfiguration ( possibleConfigAbsolutePath , folder ) . results ;
260
- lastFolder = folder ;
261
- }
262
266
linter . lint ( file , contents , configFile ) ;
263
267
}
264
268
}
@@ -287,7 +291,7 @@ async function tryReadFile(filename: string, logger: Logger): Promise<string | u
287
291
// MPEG transport streams use the '.ts' file extension. They use 0x47 as the frame
288
292
// separator, repeating every 188 bytes. It is unlikely to find that pattern in
289
293
// TypeScript source, so tslint ignores files with the specific pattern.
290
- logger . error ( `${ filename } : ignoring MPEG transport stream` ) ;
294
+ logger . error ( `${ filename } : ignoring MPEG transport stream\n ` ) ;
291
295
return undefined ;
292
296
}
293
297
} finally {
0 commit comments