* Print indexing results using clack log methods
(clack: typeof import('@clack/prompts'), result: IndexResult, projectPath?: string)
| 415 | * Print indexing results using clack log methods |
| 416 | */ |
| 417 | function printIndexResult(clack: typeof import('@clack/prompts'), result: IndexResult, projectPath?: string): void { |
| 418 | const hasErrors = result.filesErrored > 0; |
| 419 | const parseWarnings = result.errors.filter((e) => e.code === 'parse_error' && e.severity === 'warning'); |
| 420 | |
| 421 | // Surface non-file-level failures (e.g. lock-acquisition failure |
| 422 | // when another indexer is running) before the file-count branches. |
| 423 | // Without this the CLI falls through to "No files found to index", |
| 424 | // which is actively misleading — the index DID run, it just couldn't |
| 425 | // get the lock. |
| 426 | // |
| 427 | // If success is false but no severity:'error' entry exists in |
| 428 | // `result.errors` (degenerate case — shouldn't happen in practice |
| 429 | // but worth guarding because the result shape is plumbed through |
| 430 | // multiple call sites), fall back to a generic message rather than |
| 431 | // continuing to the misleading "No files found" branch or throwing. |
| 432 | if (!result.success && !hasErrors && result.filesIndexed === 0) { |
| 433 | const generic = result.errors.find((e) => e.severity === 'error'); |
| 434 | clack.log.error(generic?.message ?? `Indexing failed ${getGlyphs().dash} no further details available`); |
| 435 | return; |
| 436 | } |
| 437 | |
| 438 | if (result.filesIndexed > 0) { |
| 439 | if (hasErrors) { |
| 440 | clack.log.success(`Indexed ${formatNumber(result.filesIndexed)} files (${formatNumber(result.filesErrored)} could not be parsed)`); |
| 441 | } else { |
| 442 | clack.log.success(`Indexed ${formatNumber(result.filesIndexed)} files`); |
| 443 | } |
| 444 | clack.log.info(`${formatNumber(result.nodesCreated)} nodes, ${formatNumber(result.edgesCreated)} edges in ${formatDuration(result.durationMs)}`); |
| 445 | // Warning-only parse failures keep indexing successful, but must be visible. |
| 446 | for (const warning of parseWarnings) { |
| 447 | clack.log.warn(warning.message); |
| 448 | } |
| 449 | // A PARTIAL index (files silently dropped mid-pipeline) must not pass |
| 450 | // as a clean run — it's the difference between "indexed the repo" and |
| 451 | // "indexed most of the repo, quietly". Only the completeness |
| 452 | // reconciliation warning; per-file extractor warnings stay in the |
| 453 | // error-code summary below. |
| 454 | for (const w of result.errors.filter((e) => e.code === 'index_partial')) { |
| 455 | clack.log.warn(w.message); |
| 456 | } |
| 457 | // Files salvaged from comment-stripped source after repeated parser |
| 458 | // failures are indexed but possibly incomplete — say so here, or the run |
| 459 | // reads as fully clean and the index quietly disagrees with a later |
| 460 | // re-parse of the same bytes (#1565). |
| 461 | const salvaged = result.errors.filter((e) => e.code === 'salvaged_stripped'); |
| 462 | if (salvaged.length > 0) { |
| 463 | const sample = salvaged.slice(0, 3).map((e) => e.filePath).filter(Boolean).join(', '); |
| 464 | const more = salvaged.length > 3 ? ', ...' : ''; |
| 465 | clack.log.warn(`${formatNumber(salvaged.length)} file(s) indexed from comment-stripped source after repeated parse failures ${getGlyphs().dash} symbols may be incomplete (${sample}${more})`); |
| 466 | } |
| 467 | } else if (hasErrors) { |
| 468 | clack.log.error(`Indexing failed ${getGlyphs().dash} all ${formatNumber(result.filesErrored)} files had errors`); |
| 469 | } else if (result.filesSkippedUnsupported) { |
| 470 | // A project CodeGraph has no grammar for used to be indistinguishable from |
| 471 | // an empty one: same message, same `complete` state, same exit 0. Say which |
| 472 | // files were there and that the graph is empty on purpose, so nobody — and |
| 473 | // no agent trusting the graph — reads silence as "this code doesn't exist" |
| 474 | // (#1502). |
no test coverage detected