@@ -73,7 +73,6 @@ function symbolBoundaryRegex(symbol: string): RegExp {
7373 const escaped = symbol . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
7474 return new RegExp (
7575 `(?:^|[^A-Za-z0-9_$])(${ escaped } )(?:$|[^A-Za-z0-9_$])` ,
76- "g" ,
7776 ) ;
7877}
7978
@@ -265,6 +264,7 @@ async function readFileContainsSymbol(
265264 headSha : string ,
266265 token : string ,
267266 fetchImpl : typeof fetch ,
267+ skipLineNumbers : ReadonlySet < number > = new Set ( ) ,
268268 options : ScanOptions = { } ,
269269) : Promise < boolean > {
270270 const encodedPath = encodePath ( path ) ;
@@ -297,7 +297,15 @@ async function readFileContainsSymbol(
297297 } ) ;
298298 if ( ! response . ok ) return false ;
299299 const text = response . data ;
300- return symbolBoundaryRegex ( symbol ) . test ( text ) ;
300+ const lineRegex = symbolBoundaryRegex ( symbol ) ;
301+ for ( const [ index , line ] of text . split ( "\n" ) . entries ( ) ) {
302+ const lineNumber = index + 1 ;
303+ if ( skipLineNumbers . has ( lineNumber ) ) continue ;
304+ if ( lineRegex . test ( line ) ) {
305+ return true ;
306+ }
307+ }
308+ return false ;
301309 } catch {
302310 return false ;
303311 }
@@ -310,6 +318,8 @@ async function resolveCallers(
310318 headSha : string ,
311319 token : string ,
312320 skipPaths : Set < string > | null ,
321+ additionalPaths : Iterable < string > = [ ] ,
322+ skipLineNumbersByPath : ReadonlyMap < string , ReadonlySet < number > > = new Map ( ) ,
313323 fetchImpl : typeof fetch ,
314324 options : ScanOptions = { } ,
315325) : Promise < string [ ] > {
@@ -321,8 +331,10 @@ async function resolveCallers(
321331 fetchImpl ,
322332 options ,
323333 ) ;
334+ const candidatePaths = new Set ( hitPaths ) ;
335+ for ( const path of additionalPaths ) candidatePaths . add ( path ) ;
324336 const callers : string [ ] = [ ] ;
325- for ( const path of hitPaths ) {
337+ for ( const path of candidatePaths ) {
326338 if ( skipPaths ?. has ( path ) ) continue ;
327339 if ( callers . length >= MAX_CALLERS_PER_SYMBOL ) break ;
328340 if (
@@ -334,6 +346,7 @@ async function resolveCallers(
334346 headSha ,
335347 token ,
336348 fetchImpl ,
349+ skipLineNumbersByPath . get ( path ) ?? new Set ( ) ,
337350 options ,
338351 )
339352 ) {
@@ -471,13 +484,24 @@ export async function scanCallerImpact(
471484 const findings : CallerImpactFinding [ ] = [ ] ;
472485 for ( const candidate of candidates ) {
473486 if ( options . signal ?. aborted ) throw new Error ( "analyzer_aborted" ) ;
487+ const skipLineNumbersByPath =
488+ candidate . kind === "dead"
489+ ? new Map ( [ [ candidate . file , new Set ( [ candidate . line ] ) ] ] )
490+ : new Map < string , Set < number > > ( ) ;
491+ const isDead = candidate . kind === "dead" ;
492+ const skipPaths = isDead ? new Set ( [ candidate . file ] ) : changedPaths ;
493+ const additionalPaths = isDead
494+ ? Array . from ( changedPaths ) . filter ( ( path ) => path !== candidate . file )
495+ : [ ] ;
474496 const callers = await resolveCallers (
475497 repo . owner ,
476498 repo . repo ,
477499 candidate . searchSymbol ,
478500 req . headSha ,
479501 req . githubToken ,
480- candidate . kind === "dead" ? null : changedPaths ,
502+ skipPaths ,
503+ additionalPaths ,
504+ skipLineNumbersByPath ,
481505 fetchImpl ,
482506 options ,
483507 ) ;
0 commit comments