( cg: CodeGraph, projectRoot: string, requested: string )
| 140 | } |
| 141 | |
| 142 | export function buildFileCode( |
| 143 | cg: CodeGraph, |
| 144 | projectRoot: string, |
| 145 | requested: string |
| 146 | ): WireFileCodePayload { |
| 147 | const started = Date.now(); |
| 148 | if (requested === '') throw badRequest('No file path was given. Use /api/filecode/<path>.'); |
| 149 | |
| 150 | // Refusal first, index lookup second — see `resolveRequestedFile`. |
| 151 | const { record, storedPath } = resolveRequestedFile(cg, projectRoot, requested); |
| 152 | const posixPath = toPosixPath(storedPath); |
| 153 | |
| 154 | const nodes = cg.getNodesInFile(storedPath); |
| 155 | const fileNode = nodes.find((n) => n.kind === 'file') ?? null; |
| 156 | const { entries: outline, total: outlineTotal } = buildOutlineEntries(cg, nodes); |
| 157 | |
| 158 | const { calls, total: callTotal, intraFileCalls } = buildCalls(cg, nodes, posixPath); |
| 159 | const outside = buildOutsideRefs(cg, storedPath); |
| 160 | |
| 161 | // One read answers both the drift verdict and the document's height. |
| 162 | const shape = readFileShape(projectRoot, storedPath, record); |
| 163 | |
| 164 | return { |
| 165 | file: { |
| 166 | path: posixPath, |
| 167 | language: record.language, |
| 168 | size: record.size, |
| 169 | indexedAt: record.indexedAt, |
| 170 | contentHash: record.contentHash, |
| 171 | generated: record.generated === true, |
| 172 | test: isTestFile(posixPath), |
| 173 | // Messages, not the raw records: the screen prints a count and a line, |
| 174 | // and an extractor's file/line bookkeeping is not something a reader acts |
| 175 | // on. |
| 176 | errors: (record.errors ?? []).map((e) => e.message), |
| 177 | id: fileNode?.id ?? null, |
| 178 | totalLines: shape.totalLines, |
| 179 | }, |
| 180 | drift: shape.drift, |
| 181 | ...(shape.reason ? { reason: shape.reason } : {}), |
| 182 | outline: wireList(outline, outlineTotal), |
| 183 | calls: wireList(calls, callTotal), |
| 184 | outside: wireList(outside.items, outside.total), |
| 185 | intraFileCalls, |
| 186 | timing: { elapsedMs: Date.now() - started }, |
| 187 | }; |
| 188 | } |
| 189 | |
| 190 | /** |
| 191 | * Every outgoing edge from every symbol in the file, grouped twice over: by the |
no test coverage detected