* A function nested inside another FUNCTION is only callable from within its * container — Python, JS/TS, and every closure language scope it lexically. * Resolving a bare name from elsewhere to a nested local fabricates an edge * scope already rules out: `join(...)` in one function must never bi
( candidate: Node, ref: UnresolvedRef, context: ResolutionContext )
| 364 | * symbols and C++ namespace-prefixed names (the prefix has no node). |
| 365 | */ |
| 366 | function isLexicallyReachable( |
| 367 | candidate: Node, |
| 368 | ref: UnresolvedRef, |
| 369 | context: ResolutionContext |
| 370 | ): boolean { |
| 371 | if (candidate.kind !== 'function') return true; |
| 372 | const qn = candidate.qualifiedName; |
| 373 | if (!qn || !qn.includes('::')) return true; |
| 374 | const parentQn = qn.slice(0, qn.lastIndexOf('::')); |
| 375 | const containers = context |
| 376 | .getNodesByQualifiedName(parentQn) |
| 377 | .filter( |
| 378 | (p) => |
| 379 | p.filePath === candidate.filePath && |
| 380 | (p.kind === 'function' || p.kind === 'method') && |
| 381 | p.startLine <= candidate.startLine && |
| 382 | p.endLine >= candidate.endLine |
| 383 | ); |
| 384 | if (containers.length === 0) return true; |
| 385 | return ( |
| 386 | ref.filePath === candidate.filePath && |
| 387 | containers.some((p) => ref.line >= p.startLine && ref.line <= p.endLine) |
| 388 | ); |
| 389 | } |
| 390 | |
| 391 | /** |
| 392 | * Try to resolve a reference by exact name match |
no test coverage detected