* Which of `filePaths` are AMBIENT DECLARATION files — they declare nothing * but types, and nothing in the index depends on them (CG-28). A hand-written * ambient `.d.ts` of global shims, a vendored typings file, module * augmentation: reachable only by name, structurally attached to nothi
(filePaths: Iterable<string>)
| 2072 | * candidate list, so this is a partial-index probe over a handful of paths. |
| 2073 | */ |
| 2074 | getAmbientDeclarationPathsAmong(filePaths: Iterable<string>): Set<string> { |
| 2075 | const unique = [...new Set(filePaths)]; |
| 2076 | const found = new Set<string>(); |
| 2077 | if (unique.length === 0) return found; |
| 2078 | |
| 2079 | for (let i = 0; i < unique.length; i += SQLITE_PARAM_CHUNK_SIZE) { |
| 2080 | const chunk = unique.slice(i, i + SQLITE_PARAM_CHUNK_SIZE); |
| 2081 | const placeholders = chunk.map(() => '?').join(','); |
| 2082 | // `file`/`import`/`export`/`parameter` are structural bookkeeping, not |
| 2083 | // things the file declares, so they neither qualify nor disqualify. |
| 2084 | const rows = this.db |
| 2085 | .prepare(` |
| 2086 | SELECT file_path, |
| 2087 | SUM(CASE WHEN kind NOT IN ('file','import','export','parameter') |
| 2088 | THEN 1 ELSE 0 END) AS declared, |
| 2089 | SUM(CASE WHEN kind IN ('interface','type_alias','enum','enum_member','namespace') |
| 2090 | THEN 1 ELSE 0 END) AS typeDeclared |
| 2091 | FROM nodes |
| 2092 | WHERE file_path IN (${placeholders}) |
| 2093 | GROUP BY file_path |
| 2094 | `) |
| 2095 | .all(...chunk) as Array<{ file_path: string; declared: number; typeDeclared: number }>; |
| 2096 | let candidates = rows |
| 2097 | .filter((r) => r.declared > 0 && r.declared === r.typeDeclared) |
| 2098 | .map((r) => r.file_path); |
| 2099 | if (candidates.length === 0) continue; |
| 2100 | |
| 2101 | const disqualify = (sql: string): void => { |
| 2102 | if (candidates.length === 0) return; |
| 2103 | const hit = new Set( |
| 2104 | (this.db |
| 2105 | .prepare(sql.replace('$IN$', candidates.map(() => '?').join(','))) |
| 2106 | .all(...candidates) as Array<{ file_path: string }>).map((r) => r.file_path), |
| 2107 | ); |
| 2108 | candidates = candidates.filter((p) => !hit.has(p)); |
| 2109 | }; |
| 2110 | // (3) originates behaviour |
| 2111 | disqualify(` |
| 2112 | SELECT DISTINCT n.file_path AS file_path |
| 2113 | FROM edges e JOIN nodes n ON n.id = e.source |
| 2114 | WHERE e.kind IN ('calls','instantiates') AND n.file_path IN ($IN$) |
| 2115 | `); |
| 2116 | // (4) something outside the file depends on it |
| 2117 | disqualify(` |
| 2118 | SELECT DISTINCT t.file_path AS file_path |
| 2119 | FROM edges e JOIN nodes t ON t.id = e.target JOIN nodes s ON s.id = e.source |
| 2120 | WHERE t.file_path IN ($IN$) AND s.file_path <> t.file_path |
| 2121 | `); |
| 2122 | for (const path of candidates) found.add(path); |
| 2123 | } |
| 2124 | return found; |
| 2125 | } |
| 2126 | |
| 2127 | /** |
| 2128 | * A reusable `(path) => boolean` ambient-declaration test over a bounded |
no test coverage detected