Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions packages/loopover-engine/src/miner/repo-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,22 @@ export async function buildRepoMap(
}
const languageName = resolveRepoMapLanguage(file.path);
const sourceBytes = Buffer.byteLength(file.sourceText, "utf8");
// A file exceeding the per-file cap is skipped without being parsed, so it must NOT consume the
// aggregate parsed-work budget. Counting it before this check let one oversized file (a vendored/
// minified asset or generated bundle) exhaust maxTotalSourceBytes and force every subsequent small,
// legitimate file to skip too — a silent, order-dependent near-empty map (#7247). Only files that pass
// the per-file cap accrue against the aggregate, exactly as before for in-cap files.
if (sourceBytes > maxSourceBytes) {
entries.push({
path: file.path,
language: languageName,
symbols: [],
skipped: "resource_limit",
});
continue;
}
totalSourceBytes += sourceBytes;
if (
sourceBytes > maxSourceBytes ||
totalSourceBytes > maxTotalSourceBytes
) {
if (totalSourceBytes > maxTotalSourceBytes) {
entries.push({
path: file.path,
language: languageName,
Expand Down
22 changes: 22 additions & 0 deletions test/unit/repo-map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,28 @@ describe("buildRepoMap + extractRepoMapSymbols (#4280)", () => {
});
});

it("does not charge a file skipped for the per-file cap against the aggregate budget (#7247)", async () => {
// "function reallyLongName() {}" (28 bytes) exceeds the per-file cap and is skipped WITHOUT being
// parsed; pre-#7247 its bytes were still charged to the aggregate budget, exhausting it and skipping
// the small, legitimate file after it. The aggregate must only account for files actually parsed.
const entries = await buildRepoMap(
[
{ path: "src/huge.ts", sourceText: "function reallyLongName() {}" },
{ path: "src/small.ts", sourceText: "function s() {}" },
],
{ maxSourceBytes: 20, maxTotalSourceBytes: 20 },
);
expect(entries[0]).toEqual({
path: "src/huge.ts",
language: "typescript",
symbols: [],
skipped: "resource_limit",
});
// The small file after the skipped-oversized one is still parsed, not starved of aggregate budget.
expect(entries[1]!.skipped).toBeUndefined();
expect(entries[1]!.symbols.map((symbol) => symbol.name)).toEqual(["s"]);
});

it("keeps one entry per input file but resource-limits files beyond the file-count budget", async () => {
const entries = await buildRepoMap(
[
Expand Down