* Find an exported symbol in `filePath`, following `export { x } from * './other'` and `export * from './other'` chains until the original * declaration is reached. Cycle-safe via the `visited` set. * * Without this, every barrel-style import (`import { Foo } from * './index'` where `index.ts`
(
filePath: string,
want: {
isDefault: boolean;
isNamespace: boolean;
exportedName: string;
memberName: string | null;
},
language: Language,
context: ResolutionContext,
visited: Set<string>,
depth = 0
)
| 2077 | * resolved file, not declarations the file forwarded. |
| 2078 | */ |
| 2079 | function findExportedSymbol( |
| 2080 | filePath: string, |
| 2081 | want: { |
| 2082 | isDefault: boolean; |
| 2083 | isNamespace: boolean; |
| 2084 | exportedName: string; |
| 2085 | memberName: string | null; |
| 2086 | }, |
| 2087 | language: Language, |
| 2088 | context: ResolutionContext, |
| 2089 | visited: Set<string>, |
| 2090 | depth = 0 |
| 2091 | ): Node | undefined { |
| 2092 | // Memoize fresh (top-level) lookups only: recursive re-export steps carry a |
| 2093 | // populated `visited` set, whose contents change the reachable answer. |
| 2094 | // Every ref to the same imported symbol repeats this exact walk, so the |
| 2095 | // top-level memo removes the re-export chase + per-file linear scans from |
| 2096 | // all but the first occurrence. |
| 2097 | if (depth === 0 && visited.size === 0) { |
| 2098 | let memo = exportedSymbolMemos.get(context); |
| 2099 | if (!memo) { |
| 2100 | memo = new Map(); |
| 2101 | exportedSymbolMemos.set(context, memo); |
| 2102 | } |
| 2103 | const key = `${filePath}\0${want.isDefault ? 1 : 0}${want.isNamespace ? 1 : 0}\0${want.exportedName}\0${want.memberName ?? ''}\0${language}`; |
| 2104 | if (memo.has(key)) return memo.get(key); |
| 2105 | const result = findExportedSymbolWalk(filePath, want, language, context, visited, depth); |
| 2106 | memo.set(key, result); |
| 2107 | return result; |
| 2108 | } |
| 2109 | return findExportedSymbolWalk(filePath, want, language, context, visited, depth); |
| 2110 | } |
| 2111 | |
| 2112 | function findExportedSymbolWalk( |
| 2113 | filePath: string, |
no test coverage detected