1818/* eslint-disable @typescript-eslint/no-explicit-any */
1919/* eslint-disable no-console */
2020
21- import * as fs from "fs" ;
22- import { getRandomValues } from 'node:crypto' ;
23- import * as path from " path" ;
21+ import * as fs from 'fs' ;
22+ import { getRandomValues } from 'node:crypto' ;
23+ import * as path from ' path' ;
2424
25- import * as ts from " typescript" ;
26- import yargs from " yargs" ;
27- import { hideBin } from " yargs/helpers" ;
25+ import * as ts from ' typescript' ;
26+ import yargs from ' yargs' ;
27+ import { hideBin } from ' yargs/helpers' ;
2828
2929let isVerbose : boolean = false ;
3030
@@ -35,7 +35,7 @@ function log(message: any): void {
3535}
3636
3737// Define the names of the functions we are looking for
38- const targetFunctionNames : Set < string > = new Set ( [ " fail" , " hardAssert" ] ) ;
38+ const targetFunctionNames : Set < string > = new Set ( [ ' fail' , ' hardAssert' ] ) ;
3939
4040// Interface to store information about found call sites
4141interface CallSiteInfo {
@@ -68,9 +68,9 @@ function getTsFilesRecursive(dirPath: string): string[] {
6868 }
6969 // Recursively scan subdirectories
7070 tsFiles = tsFiles . concat ( getTsFilesRecursive ( fullPath ) ) ;
71- } else if ( entry . isFile ( ) && ( entry . name . endsWith ( " .ts" ) ) ) {
71+ } else if ( entry . isFile ( ) && entry . name . endsWith ( ' .ts' ) ) {
7272 // Exclude declaration files (.d.ts) as they usually don't contain implementation
73- if ( ! entry . name . endsWith ( " .d.ts" ) ) {
73+ if ( ! entry . name . endsWith ( ' .d.ts' ) ) {
7474 tsFiles . push ( fullPath ) ;
7575 }
7676 }
@@ -168,23 +168,36 @@ function findFunctionCalls(filePaths: string[]): CallSiteInfo[] {
168168
169169function handleList ( occurrences : CallSiteInfo [ ] ) : void {
170170 if ( occurrences . length === 0 ) {
171- log ( " No assertion ids found." ) ;
171+ log ( ' No assertion ids found.' ) ;
172172 return ;
173173 }
174174
175- occurrences . sort ( ( a , b ) => a . assertionId . localeCompare ( b . assertionId ) ) . forEach ( ( call ) => {
176- console . log (
177- `ID: ${ call . assertionId } ; MESSAGE: ${ call . errorMessage } ; SOURCE: '${ call . functionName } ' call at ${ path . relative ( process . cwd ( ) , call . fileName ) } :${ call . line } :${ call . character } `
178- ) ;
179- } ) ;
175+ occurrences
176+ . sort ( ( a , b ) => a . assertionId . localeCompare ( b . assertionId ) )
177+ . forEach ( call => {
178+ console . log (
179+ `ID: ${ call . assertionId } ; MESSAGE: ${ call . errorMessage } ; SOURCE: '${
180+ call . functionName
181+ } ' call at ${ path . relative ( process . cwd ( ) , call . fileName ) } :${
182+ call . line
183+ } :${ call . character } `
184+ ) ;
185+ } ) ;
180186}
181187
182- function find ( occurrences : CallSiteInfo [ ] , targetId : string | number ) : CallSiteInfo [ ] {
183- const target = typeof targetId === 'number' ? targetId . toString ( 16 ) : targetId ;
188+ function find (
189+ occurrences : CallSiteInfo [ ] ,
190+ targetId : string | number
191+ ) : CallSiteInfo [ ] {
192+ const target =
193+ typeof targetId === 'number' ? targetId . toString ( 16 ) : targetId ;
184194 return occurrences . filter ( o => String ( o . assertionId ) === String ( target ) ) ;
185195}
186196
187- function handleFind ( occurrences : CallSiteInfo [ ] , targetId : string | number ) : void {
197+ function handleFind (
198+ occurrences : CallSiteInfo [ ] ,
199+ targetId : string | number
200+ ) : void {
188201 const foundLocations = find ( occurrences , targetId ) ;
189202
190203 if ( foundLocations . length === 0 ) {
@@ -197,7 +210,7 @@ function handleFind(occurrences: CallSiteInfo[], targetId: string | number): voi
197210
198211function handleCheck ( occurrences : CallSiteInfo [ ] ) : void {
199212 if ( occurrences . length === 0 ) {
200- log ( " No assertion ids found to check for duplicates." ) ;
213+ log ( ' No assertion ids found to check for duplicates.' ) ;
201214 return ;
202215 }
203216 const idCounts : { [ id : string ] : CallSiteInfo [ ] } = { } ;
@@ -212,19 +225,23 @@ function handleCheck(occurrences: CallSiteInfo[]): void {
212225
213226 // validate formats
214227 if ( ! / ^ 0 x [ 0 - 9 a - f ] { 4 } $ / . test ( occ . assertionId ) ) {
215- console . error ( `Invalid assertion ID '${ occ . assertionId } '. Must match /^0x[0-9a-f]{4}$/` ) ;
228+ console . error (
229+ `Invalid assertion ID '${ occ . assertionId } '. Must match /^0x[0-9a-f]{4}$/`
230+ ) ;
216231
217232 const relativePath = path . relative ( process . cwd ( ) , occ . fileName ) ;
218233 console . error ( `- at '${ relativePath } :${ occ . line } :${ occ . character } ` ) ;
219234 }
220235 } ) ;
221236
222237 let duplicatesFound = false ;
223- log ( " Checking for duplicate assertion id usage:" ) ;
238+ log ( ' Checking for duplicate assertion id usage:' ) ;
224239 Object . entries ( idCounts ) . forEach ( ( [ code , locations ] ) => {
225240 if ( locations . length > 1 ) {
226241 duplicatesFound = true ;
227- console . error ( `\nDuplicate assertion id "${ code } " found at ${ locations . length } locations:` ) ;
242+ console . error (
243+ `\nDuplicate assertion id "${ code } " found at ${ locations . length } locations:`
244+ ) ;
228245 locations . forEach ( loc => {
229246 const relativePath = path . relative ( process . cwd ( ) , loc . fileName ) ;
230247 console . error ( `- ${ relativePath } :${ loc . line } :${ loc . character } ` ) ;
@@ -233,9 +250,8 @@ function handleCheck(occurrences: CallSiteInfo[]): void {
233250 } ) ;
234251
235252 if ( ! duplicatesFound ) {
236- log ( "No duplicate assertion ids found." ) ;
237- }
238- else {
253+ log ( 'No duplicate assertion ids found.' ) ;
254+ } else {
239255 process . exit ( 1 ) ;
240256 }
241257}
@@ -244,9 +260,12 @@ function randomId(): string {
244260 const randomBytes = new Uint8Array ( 2 ) ;
245261 getRandomValues ( randomBytes ) ;
246262
247- return '0x' + Array . from ( randomBytes )
248- . map ( byte => byte . toString ( 16 ) . padStart ( 2 , '0' ) )
249- . join ( '' ) ;
263+ return (
264+ '0x' +
265+ Array . from ( randomBytes )
266+ . map ( byte => byte . toString ( 16 ) . padStart ( 2 , '0' ) )
267+ . join ( '' )
268+ ) ;
250269}
251270
252271function handleNew ( occurrences : CallSiteInfo [ ] ) : void {
@@ -263,44 +282,44 @@ function handleNew(occurrences: CallSiteInfo[]): void {
263282// --- Main Execution ---
264283async function main ( ) : Promise < void > {
265284 const argv = yargs ( hideBin ( process . argv ) )
266- . usage ( " Usage: $0 [options]" )
267- . option ( " dir" , {
285+ . usage ( ' Usage: $0 [options]' )
286+ . option ( ' dir' , {
268287 alias : 'D' ,
269- describe : " Directory to scan recursively for TS files" ,
270- type : " string" ,
271- demandOption : true ,
288+ describe : ' Directory to scan recursively for TS files' ,
289+ type : ' string' ,
290+ demandOption : true
272291 } )
273- . option ( " verbose" , {
274- alias : "V" ,
275- describe : " verbose" ,
276- type : " boolean" ,
292+ . option ( ' verbose' , {
293+ alias : 'V' ,
294+ describe : ' verbose' ,
295+ type : ' boolean'
277296 } )
278- . option ( " find" , {
279- alias : "F" ,
280- describe : " Find locations of a specific {assertionId}" ,
281- type : " string" ,
282- nargs : 1 ,
297+ . option ( ' find' , {
298+ alias : 'F' ,
299+ describe : ' Find locations of a specific {assertionId}' ,
300+ type : ' string' ,
301+ nargs : 1
283302 } )
284- . option ( " list" , {
285- alias : "L" ,
286- describe : " List all unique assertion ids found (default action)" ,
287- type : " boolean" ,
303+ . option ( ' list' , {
304+ alias : 'L' ,
305+ describe : ' List all unique assertion ids found (default action)' ,
306+ type : ' boolean'
288307 } )
289- . option ( " new" , {
290- alias : "N" ,
291- describe : " Suggest a new assertion id based on existing ones" ,
292- type : " boolean" ,
308+ . option ( ' new' , {
309+ alias : 'N' ,
310+ describe : ' Suggest a new assertion id based on existing ones' ,
311+ type : ' boolean'
293312 } )
294- . option ( " check" , {
295- alias : "C" ,
296- describe : " Check for duplicate usage of assertion ids" ,
297- type : " boolean" ,
313+ . option ( ' check' , {
314+ alias : 'C' ,
315+ describe : ' Check for duplicate usage of assertion ids' ,
316+ type : ' boolean'
298317 } )
299- . check ( ( argv ) => {
318+ . check ( argv => {
300319 // Enforce mutual exclusivity among options *within* the scan command
301320 const options = [ argv . F , argv . L , argv . N , argv . C ] . filter ( Boolean ) . length ;
302321 if ( options > 1 ) {
303- throw new Error ( " Options -F, -L, -N, -C are mutually exclusive." ) ;
322+ throw new Error ( ' Options -F, -L, -N, -C are mutually exclusive.' ) ;
304323 }
305324 return true ;
306325 } )
@@ -319,25 +338,31 @@ async function main(): Promise<void> {
319338 try {
320339 const stats = fs . statSync ( targetDirectory ) ;
321340 if ( ! stats . isDirectory ( ) ) {
322- console . error ( `Error: Provided path is not a directory: ${ targetDirectory } ` ) ;
341+ console . error (
342+ `Error: Provided path is not a directory: ${ targetDirectory } `
343+ ) ;
323344 process . exit ( 1 ) ;
324345 }
325346 } catch ( error : any ) {
326- console . error ( `Error accessing directory ${ targetDirectory } : ${ error . message } ` ) ;
347+ console . error (
348+ `Error accessing directory ${ targetDirectory } : ${ error . message } `
349+ ) ;
327350 process . exit ( 1 ) ;
328351 }
329352
330353 log ( `Scanning directory: ${ targetDirectory } ` ) ;
331354 const filesToScan = getTsFilesRecursive ( targetDirectory ) ;
332355
333356 if ( filesToScan . length === 0 ) {
334- log ( " No relevant .ts or .tsx files found." ) ;
357+ log ( ' No relevant .ts or .tsx files found.' ) ;
335358 process . exit ( 0 ) ;
336359 }
337360 log ( `Found ${ filesToScan . length } files. Analyzing for assertion ids...` ) ;
338361
339362 const allOccurrences = findFunctionCalls ( filesToScan ) ;
340- log ( `Scan complete. Found ${ allOccurrences . length } potential assertion id occurrences.` ) ;
363+ log (
364+ `Scan complete. Found ${ allOccurrences . length } potential assertion id occurrences.`
365+ ) ;
341366
342367 // Determine action based on flags
343368 if ( argv [ 'find' ] ) {
0 commit comments