diff --git a/core/util/ranges.test.ts b/core/util/ranges.test.ts index 84d1c8d54a2..9466c003f61 100644 --- a/core/util/ranges.test.ts +++ b/core/util/ranges.test.ts @@ -353,6 +353,24 @@ describe("intersection", () => { }); }); + test("uses later start and earlier end when both ranges share the start and end lines", () => { + rangeA = { + start: { line: 0, character: 5 }, + end: { line: 3, character: 4 }, + }; + + rangeB = { + start: { line: 0, character: 10 }, + end: { line: 3, character: 2 }, + }; + + const result = intersection(rangeA, rangeB); + expect(result).toEqual({ + start: { line: 0, character: 10 }, + end: { line: 3, character: 2 }, + }); + }); + test("returns correct intersection when ranges touch at the edge", () => { rangeA = { start: { line: 1, character: 0 }, diff --git a/core/util/ranges.ts b/core/util/ranges.ts index a9bf5e97242..978fea58c2c 100644 --- a/core/util/ranges.ts +++ b/core/util/ranges.ts @@ -46,10 +46,21 @@ export function intersection(a: Range, b: Range): Range | null { }; } + // When both ranges begin on the shared start line, the intersection begins at + // the later of the two characters (and symmetrically ends at the earlier one). + // Picking whichever range's line matched first dropped that comparison. const startCharacter = - startLine === a.start.line ? a.start.character : b.start.character; + a.start.line === b.start.line + ? Math.max(a.start.character, b.start.character) + : startLine === a.start.line + ? a.start.character + : b.start.character; const endCharacter = - endLine === a.end.line ? a.end.character : b.end.character; + a.end.line === b.end.line + ? Math.min(a.end.character, b.end.character) + : endLine === a.end.line + ? a.end.character + : b.end.character; return { start: { line: startLine, character: startCharacter },