fix(read_file): make indentation offset beyond EOF return empty page

This commit is contained in:
Hannes Rudolph 2025-12-21 19:08:35 -07:00
parent cd60bc4fd5
commit c903656abc
2 changed files with 68 additions and 17 deletions

View file

@ -122,14 +122,14 @@ describe("read-file-content", () => {
describe("readIndentationBlock", () => {
const pythonCode = `def outer():
x = 1
def inner():
y = 2
return y
return inner()
def another():
pass`
x = 1
def inner():
y = 2
return y
return inner()
def another():
pass`
it("should extract a function block with its contents", async () => {
await withTempFile("indent-function-test.py", pythonCode, async (filepath) => {
@ -180,6 +180,16 @@ def another():
})
})
it("should return empty content when offset exceeds file length (no explicit anchorLine)", async () => {
await withTempFile("indent-offset-past-end-test.py", pythonCode, async (filepath) => {
const result = await readIndentationBlock(filepath, 100, 10)
expect(result.content).toBe("")
expect(result.lineCount).toBe(0)
expect(result.totalLines).toBeGreaterThan(0)
expect(result.metadata.totalLinesInFile).toBe(result.totalLines)
})
})
it("should handle single line result", async () => {
const content = "single line"
await withTempFile("indent-single-test.txt", content, async (filepath) => {

View file

@ -356,13 +356,9 @@ export async function readIndentationBlock(
limit: number = FALLBACK_LIMIT,
config: IndentationConfig = {},
): Promise<ReadFileContentResult> {
const {
anchorLine = offset,
maxLevels = 0,
includeSiblings = false,
includeHeader = true,
maxLines = limit,
} = config
const hasExplicitAnchorLine = typeof config.anchorLine === "number"
const anchorLine = config.anchorLine ?? offset
const { maxLevels = 0, includeSiblings = false, includeHeader = true, maxLines = limit } = config
if (anchorLine === 0) {
throw new RangeError("anchorLine must be a 1-indexed line number")
@ -374,8 +370,53 @@ export async function readIndentationBlock(
// Load all lines
const records = await collectFileLines(filePath)
if (records.length === 0 || anchorLine > records.length) {
throw new RangeError("anchorLine exceeds file length")
// If the file is empty, match slice mode and return an empty page.
if (records.length === 0) {
return {
content: "",
lineCount: 0,
totalLines: 0,
metadata: {
filePath,
totalLinesInFile: 0,
linesReturned: 0,
startLine: anchorLine,
endLine: anchorLine,
hasMoreBefore: anchorLine > 1,
hasMoreAfter: false,
linesBeforeStart: 0,
linesAfterEnd: 0,
truncatedByLimit: false,
lineLengthTruncations: [],
},
}
}
// If offset is out-of-range and no explicit anchorLine was provided, match slice mode and return an empty page.
if (anchorLine > records.length) {
if (hasExplicitAnchorLine) {
throw new RangeError("anchorLine exceeds file length")
}
const totalLines = records.length
return {
content: "",
lineCount: 0,
totalLines,
metadata: {
filePath,
totalLinesInFile: totalLines,
linesReturned: 0,
startLine: anchorLine,
endLine: anchorLine,
hasMoreBefore: anchorLine > 1,
hasMoreAfter: false,
linesBeforeStart: Math.min(anchorLine - 1, totalLines),
linesAfterEnd: 0,
truncatedByLimit: false,
lineLengthTruncations: [],
},
}
}
const anchorIndex = anchorLine - 1