(node: any, prefix: string)
| 174 | * travels with the thing it decorates. |
| 175 | */ |
| 176 | const collect = (node: any, prefix: string) => { |
| 177 | for (let i = 0; i < node.childCount; i++) { |
| 178 | const child = node.child(i); |
| 179 | if (!child) continue; |
| 180 | if (!boundary.has(child.type)) { |
| 181 | // Not a boundary itself, but might contain boundaries (e.g. an |
| 182 | // export_statement wrapping a class, or a decorated_definition). |
| 183 | if (CONTAINER_RE.test(child.type) || /export_statement|decorated_definition/.test(child.type)) { |
| 184 | collect(child, prefix); |
| 185 | } |
| 186 | continue; |
| 187 | } |
| 188 | |
| 189 | const startLine = child.startPosition.row; |
| 190 | const endLine = child.endPosition.row + 1; |
| 191 | const span = endLine - startLine; |
| 192 | const rawName = extractSymbolName(child, content); |
| 193 | const qualified = rawName ? (prefix ? `${prefix}.${rawName}` : rawName) : undefined; |
| 194 | const isContainer = CONTAINER_RE.test(child.type); |
| 195 | |
| 196 | if (isContainer && span > maxLines) { |
| 197 | // Too big to embed as one unit → emit a lightweight "header" chunk for the |
| 198 | // container signature (so the class/interface itself is searchable), then |
| 199 | // descend and chunk each member. |
| 200 | const headerEnd = Math.min(startLine + 3, endLine); // signature + a couple lines |
| 201 | boundaries.push({ startLine, endLine: headerEnd, symbol: qualified }); |
| 202 | let descended = false; |
| 203 | for (let j = 0; j < child.childCount; j++) { |
| 204 | const body = child.child(j); |
| 205 | if (body && BODY_RE.test(body.type)) { |
| 206 | collect(body, qualified ?? prefix); |
| 207 | descended = true; |
| 208 | } |
| 209 | } |
| 210 | // If we somehow found no body, fall back to emitting the whole thing. |
| 211 | if (!descended) { |
| 212 | boundaries.pop(); |
| 213 | boundaries.push({ startLine, endLine, symbol: qualified }); |
| 214 | } |
| 215 | } else { |
| 216 | // Fits, or isn't a container → one chunk. Decorators are included because |
| 217 | // we chunk on the outer node (decorated_definition / the node whose span |
| 218 | // covers leading decorators). |
| 219 | boundaries.push({ startLine, endLine, symbol: qualified }); |
| 220 | } |
| 221 | } |
| 222 | }; |
| 223 | collect(root, ''); |
| 224 | |
| 225 | if (boundaries.length === 0) return lineChunk(rel, content); |
no test coverage detected