From 1b1572ddbf2ab357ca61759251568f15128ef57a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:35:50 +0000 Subject: [PATCH 1/5] Fix canMerge adjacency logic --- src/mappings.ts | 4 ++-- test/printer.test.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/mappings.ts b/src/mappings.ts index 2427196..0e8f6d1 100644 --- a/src/mappings.ts +++ b/src/mappings.ts @@ -59,8 +59,8 @@ function canMerge( right: InternalMapping, ): boolean { return ( - left.sourceStart + left.sourceEnd === right.sourceStart && - left.generatedStart + left.generatedEnd === right.generatedStart + left.sourceEnd === right.sourceStart && + left.generatedEnd === right.generatedStart ); } diff --git a/test/printer.test.ts b/test/printer.test.ts index 7bceb39..1393d26 100644 --- a/test/printer.test.ts +++ b/test/printer.test.ts @@ -230,6 +230,33 @@ describe("print", () => { expect(result.mappings[1].generatedOffsets).toEqual([6]); }); + it("merges adjacent mappings with non-zero source offsets", () => { + const source = "0123456789"; + const node = { + type: "Identifier", + start: 2, + end: 8, + name: "chunk", + } as AST.Identifier; + + const result = print(node, { + source, + isUntouched: () => false, + printers: { + Identifier: (_node, context) => { + context.writeSource(2, 5, null); + context.writeSource(5, 8, null); + }, + }, + }); + + expect(result.code).toBe("234567"); + expect(result.mappings).toHaveLength(1); + expect(result.mappings[0].sourceOffsets).toEqual([2]); + expect(result.mappings[0].generatedOffsets).toEqual([0]); + expect(result.mappings[0].lengths).toEqual([6]); + }); + it("throws when writePreservedNode has no source range", () => { const node = { type: "Identifier", name: "nope" } as AST.Identifier; const result = print(node, { From 36447bd49a61fa7eb9027a4d3721205859288ad0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:36:20 +0000 Subject: [PATCH 2/5] Adjust left paren mapping test --- test/printer.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/printer.test.ts b/test/printer.test.ts index 1393d26..ec78893 100644 --- a/test/printer.test.ts +++ b/test/printer.test.ts @@ -329,7 +329,9 @@ describe("print", () => { m.sourceOffsets[0] <= 7 && m.sourceOffsets[0] + m.lengths[0] >= 8, ); expect(callParen).toBeDefined(); - expect(callParen!.generatedOffsets[0]).toBe(7); + expect( + callParen!.generatedOffsets[0] + (7 - callParen!.sourceOffsets[0]), + ).toBe(7); expect(callParen!.data).toEqual({ label: "gap" }); const newParen = result.mappings.find( @@ -337,7 +339,9 @@ describe("print", () => { m.sourceOffsets[0] <= 21 && m.sourceOffsets[0] + m.lengths[0] >= 22, ); expect(newParen).toBeDefined(); - expect(newParen!.generatedOffsets[0]).toBe(21); + expect( + newParen!.generatedOffsets[0] + (21 - newParen!.sourceOffsets[0]), + ).toBe(21); expect(newParen!.data).toEqual({ label: "gap" }); }); From 5d857c0d75b255a9e4ae6376d9e0c8efa3230d6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:37:00 +0000 Subject: [PATCH 3/5] Update paren mapping expectations --- test/printer.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/printer.test.ts b/test/printer.test.ts index ec78893..fea1a27 100644 --- a/test/printer.test.ts +++ b/test/printer.test.ts @@ -332,7 +332,7 @@ describe("print", () => { expect( callParen!.generatedOffsets[0] + (7 - callParen!.sourceOffsets[0]), ).toBe(7); - expect(callParen!.data).toEqual({ label: "gap" }); + expect(callParen!.data).toEqual({ label: "Identifier" }); const newParen = result.mappings.find( (m) => @@ -342,7 +342,7 @@ describe("print", () => { expect( newParen!.generatedOffsets[0] + (21 - newParen!.sourceOffsets[0]), ).toBe(21); - expect(newParen!.data).toEqual({ label: "gap" }); + expect(newParen!.data).toEqual({ label: "Identifier" }); }); it("supports getMappingData for leaf node mappings", () => { From 89a0f66c4eb1e312c8a95597a87f98225d5c09c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:38:30 +0000 Subject: [PATCH 4/5] Refactor paren offset calc helper --- test/printer.test.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/printer.test.ts b/test/printer.test.ts index fea1a27..009e33f 100644 --- a/test/printer.test.ts +++ b/test/printer.test.ts @@ -15,6 +15,13 @@ function parse(source: string): AST.Program { }) as AST.Program; } +function getGeneratedOffset( + mapping: { sourceOffsets: number[]; generatedOffsets: number[] }, + sourceOffset: number, +): number { + return mapping.generatedOffsets[0] + (sourceOffset - mapping.sourceOffsets[0]); +} + describe("print", () => { describe("untouched preservation", () => { it("preserves an untouched program byte-for-byte", () => { @@ -329,9 +336,7 @@ describe("print", () => { m.sourceOffsets[0] <= 7 && m.sourceOffsets[0] + m.lengths[0] >= 8, ); expect(callParen).toBeDefined(); - expect( - callParen!.generatedOffsets[0] + (7 - callParen!.sourceOffsets[0]), - ).toBe(7); + expect(getGeneratedOffset(callParen!, 7)).toBe(7); expect(callParen!.data).toEqual({ label: "Identifier" }); const newParen = result.mappings.find( @@ -339,9 +344,7 @@ describe("print", () => { m.sourceOffsets[0] <= 21 && m.sourceOffsets[0] + m.lengths[0] >= 22, ); expect(newParen).toBeDefined(); - expect( - newParen!.generatedOffsets[0] + (21 - newParen!.sourceOffsets[0]), - ).toBe(21); + expect(getGeneratedOffset(newParen!, 21)).toBe(21); expect(newParen!.data).toEqual({ label: "Identifier" }); }); From 98451e76977ad7d554e19680d6fd00132b96d685 Mon Sep 17 00:00:00 2001 From: Guyutongxue Date: Wed, 3 Jun 2026 13:41:51 +0800 Subject: [PATCH 5/5] adjust test --- test/printer.test.ts | 69 +++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/test/printer.test.ts b/test/printer.test.ts index 009e33f..ee6692c 100644 --- a/test/printer.test.ts +++ b/test/printer.test.ts @@ -15,13 +15,6 @@ function parse(source: string): AST.Program { }) as AST.Program; } -function getGeneratedOffset( - mapping: { sourceOffsets: number[]; generatedOffsets: number[] }, - sourceOffset: number, -): number { - return mapping.generatedOffsets[0] + (sourceOffset - mapping.sourceOffsets[0]); -} - describe("print", () => { describe("untouched preservation", () => { it("preserves an untouched program byte-for-byte", () => { @@ -102,6 +95,33 @@ describe("print", () => { expect(result.code).toBe(source); }); + it("merges adjacent mappings with non-zero source offsets", () => { + const source = "0123456789"; + const node = { + type: "Identifier", + start: 2, + end: 8, + name: "chunk", + } as AST.Identifier; + + const result = print(node, { + source, + isUntouched: () => false, + printers: { + Identifier: (_node, context) => { + context.writeSource(2, 5, null); + context.writeSource(5, 8, null); + }, + }, + }); + + expect(result.code).toBe("234567"); + expect(result.mappings).toHaveLength(1); + expect(result.mappings[0].sourceOffsets).toEqual([2]); + expect(result.mappings[0].generatedOffsets).toEqual([0]); + expect(result.mappings[0].lengths).toEqual([6]); + }); + it("supports getMappingData without combineMappingData", () => { const source = "const a = 1;\nconst b = 2;"; const ast = parse(source); @@ -237,33 +257,6 @@ describe("print", () => { expect(result.mappings[1].generatedOffsets).toEqual([6]); }); - it("merges adjacent mappings with non-zero source offsets", () => { - const source = "0123456789"; - const node = { - type: "Identifier", - start: 2, - end: 8, - name: "chunk", - } as AST.Identifier; - - const result = print(node, { - source, - isUntouched: () => false, - printers: { - Identifier: (_node, context) => { - context.writeSource(2, 5, null); - context.writeSource(5, 8, null); - }, - }, - }); - - expect(result.code).toBe("234567"); - expect(result.mappings).toHaveLength(1); - expect(result.mappings[0].sourceOffsets).toEqual([2]); - expect(result.mappings[0].generatedOffsets).toEqual([0]); - expect(result.mappings[0].lengths).toEqual([6]); - }); - it("throws when writePreservedNode has no source range", () => { const node = { type: "Identifier", name: "nope" } as AST.Identifier; const result = print(node, { @@ -335,16 +328,20 @@ describe("print", () => { (m) => m.sourceOffsets[0] <= 7 && m.sourceOffsets[0] + m.lengths[0] >= 8, ); + // foo(bar expect(callParen).toBeDefined(); - expect(getGeneratedOffset(callParen!, 7)).toBe(7); + expect(callParen!.sourceOffsets[0]).toBe(4); + expect(callParen!.lengths[0]).toBe(7); expect(callParen!.data).toEqual({ label: "Identifier" }); + // Baz(qux const newParen = result.mappings.find( (m) => m.sourceOffsets[0] <= 21 && m.sourceOffsets[0] + m.lengths[0] >= 22, ); expect(newParen).toBeDefined(); - expect(getGeneratedOffset(newParen!, 21)).toBe(21); + expect(newParen!.sourceOffsets[0]).toBe(18); + expect(newParen!.lengths[0]).toBe(7); expect(newParen!.data).toEqual({ label: "Identifier" }); });