diff --git a/package.json b/package.json index de71817..8b155ed 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,9 @@ "pnpm": { "overrides": { "@vitest/coverage-v8>ast-v8-to-istanbul": "./" + }, + "patchedDependencies": { + "istanbul-lib-source-maps": "patches/istanbul-lib-source-maps.patch" } }, "prettier": {} diff --git a/patches/istanbul-lib-source-maps.patch b/patches/istanbul-lib-source-maps.patch new file mode 100644 index 0000000..b58795a --- /dev/null +++ b/patches/istanbul-lib-source-maps.patch @@ -0,0 +1,36 @@ +diff --git a/CHANGELOG.md b/CHANGELOG.md +deleted file mode 100644 +index dad8c06aac26cb8cfced31da5f35ac8e95915f15..0000000000000000000000000000000000000000 +diff --git a/lib/get-mapping.js b/lib/get-mapping.js +index 187a02ed65104d8e3a058d6bfe7dc8bd7c285369..10dbf17549a6a0795e868bbc2ea6d0df661da514 100644 +--- a/lib/get-mapping.js ++++ b/lib/get-mapping.js +@@ -36,13 +36,26 @@ function originalEndPositionFor(sourceMap, generatedEnd) { + // generated file end location. Note however that this position on its + // own is not useful because it is the position of the _start_ of the range + // on the original file, and we want the _end_ of the range. +- const beforeEndMapping = originalPositionTryBoth( ++ let beforeEndMapping = originalPositionTryBoth( + sourceMap, + generatedEnd.line, + generatedEnd.column - 1 + ); + if (beforeEndMapping.source === null) { +- return null; ++ for ( ++ let line = generatedEnd.line; ++ line > 0 && beforeEndMapping.source === null; ++ line-- ++ ) { ++ beforeEndMapping = originalPositionTryBoth( ++ sourceMap, ++ line, ++ Number.MAX_SAFE_INTEGER ++ ); ++ } ++ if (beforeEndMapping.source === null) { ++ return null; ++ } + } + + // Convert that original position back to a generated one, with a bump diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1194ce..3933acc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,11 @@ settings: overrides: '@vitest/coverage-v8>ast-v8-to-istanbul': ./ +patchedDependencies: + istanbul-lib-source-maps: + hash: b951f25236a1145ea237e903b9fd0292a37cca73260959fe7b6bbfe7e61a7fcc + path: patches/istanbul-lib-source-maps.patch + importers: .: @@ -98,7 +103,7 @@ importers: version: 3.0.1 istanbul-lib-source-maps: specifier: ^5.0.6 - version: 5.0.6 + version: 5.0.6(patch_hash=b951f25236a1145ea237e903b9fd0292a37cca73260959fe7b6bbfe7e61a7fcc) istanbul-reports: specifier: ^3.2.0 version: 3.2.0 @@ -2963,7 +2968,7 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 6.0.3 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 + istanbul-lib-source-maps: 5.0.6(patch_hash=b951f25236a1145ea237e903b9fd0292a37cca73260959fe7b6bbfe7e61a7fcc) istanbul-reports: 3.2.0 magicast: 0.5.1 obug: 2.1.1 @@ -2979,7 +2984,7 @@ snapshots: ast-v8-to-istanbul: 'link:' istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 + istanbul-lib-source-maps: 5.0.6(patch_hash=b951f25236a1145ea237e903b9fd0292a37cca73260959fe7b6bbfe7e61a7fcc) istanbul-reports: 3.2.0 magicast: 0.5.1 obug: 2.1.1 @@ -3623,7 +3628,7 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@5.0.6: + istanbul-lib-source-maps@5.0.6(patch_hash=b951f25236a1145ea237e903b9fd0292a37cca73260959fe7b6bbfe7e61a7fcc): dependencies: '@jridgewell/trace-mapping': 0.3.31 debug: 4.4.0 diff --git a/src/location.ts b/src/location.ts index 77dd8db..4072026 100644 --- a/src/location.ts +++ b/src/location.ts @@ -91,15 +91,18 @@ export class Locator { let end = getPosition(endNeedle, this.#map); - // e.g. tsc that doesnt include } in source maps - if (end === null) { - endNeedle.column++; - end = getPosition(endNeedle, this.#map); - } - if (end === null) { + // search the previous lines as the mapping was not found on the same line + // e.g. tsc that doesnt include } in source maps + for ( + let line = endNeedle.line; + line >= startNeedle.line && end === null; + line-- + ) { + end = getPosition({ line, column: Infinity }, this.#map); + } // Does not exist in source maps, e.g. generated code - return null; + if (end === null) return null; } const loc = { start, end }; diff --git a/test/location.test.ts b/test/location.test.ts index ab95516..c01891b 100644 --- a/test/location.test.ts +++ b/test/location.test.ts @@ -102,3 +102,39 @@ function sum(a, b) { expect(locator.offsetToNeedle(start)).toEqual({ line: 2, column: 9 }); expect(locator.offsetToNeedle(end)).toEqual({ line: 2, column: 12 }); }); + +test("getLoc returns mapped location for positions without end mapping", () => { + const code = `\ +export function isEven(a: number) { + return a % 2 === 0 +} + +export function isOdd(a: number) { + return !isEven(a) +} +`; + const map = { + version: 3 as const, + mappings: + "AAAA,OAAO,SAAS,OAAO,GAAW;AAChC,QAAO,IAAI,MAAM;;AAGnB,OAAO,SAAS,MAAM,GAAW;AAC/B,QAAO,CAAC,OAAO,EAAE", + sources: ["even.ts"], + names: [], + }; + + const locator = new Locator(code, new TraceMap(map), ""); + + expect(locator.getLoc({ start: 25, end: 50 })).toEqual({ + start: { + filename: "even.ts", + line: 1, + column: 23, + }, + end: { + source: "even.ts", + filename: "even.ts", + line: 2, + column: 19, + name: null, + }, + }); +}); diff --git a/test/svelte.test.ts b/test/svelte.test.ts index 389fa73..9b509e7 100644 --- a/test/svelte.test.ts +++ b/test/svelte.test.ts @@ -19,9 +19,9 @@ test("svelte for loop", async ({ actual, expected }) => { expect(actual).toMatchInlineSnapshot(` { "branches": "0/0 (100%)", - "functions": "0/3 (0%)", + "functions": "0/4 (0%)", "lines": "0/3 (0%)", - "statements": "0/5 (0%)", + "statements": "0/6 (0%)", } `); diff --git a/test/vue.test.ts b/test/vue.test.ts index af502ed..1af3c07 100644 --- a/test/vue.test.ts +++ b/test/vue.test.ts @@ -19,9 +19,9 @@ test("vue for loop", async ({ actual, expected }) => { expect(actual).toMatchInlineSnapshot(` { "branches": "0/0 (100%)", - "functions": "0/0 (100%)", - "lines": "0/2 (0%)", - "statements": "0/2 (0%)", + "functions": "0/1 (0%)", + "lines": "0/3 (0%)", + "statements": "0/3 (0%)", } `);