Clamp calculated sourcemap positions rather than throwing (#28583)
* Clamp calculated sourcemap positions rather than throwing, to allow the underlying file to drift out of date with the sourcemap without a crash * Clamp line as well
This commit is contained in:
parent
12f3d0d54c
commit
cd08a22ef5
3 changed files with 53 additions and 4 deletions
|
@ -342,12 +342,29 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string): number {
|
export function getPositionOfLineAndCharacterWithEdits(sourceFile: SourceFileLike, line: number, character: number): number {
|
||||||
|
return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, /*allowEdits*/ true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @internal */
|
||||||
|
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string, allowEdits?: true): number {
|
||||||
if (line < 0 || line >= lineStarts.length) {
|
if (line < 0 || line >= lineStarts.length) {
|
||||||
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
|
if (allowEdits) {
|
||||||
|
// Clamp line to nearest allowable value
|
||||||
|
line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = lineStarts[line] + character;
|
const res = lineStarts[line] + character;
|
||||||
|
if (allowEdits) {
|
||||||
|
// Clamp to nearest allowable values to allow the underlying to be edited without crashing (accuracy is lost, instead)
|
||||||
|
// TODO: Somehow track edits between file as it was during the creation of sourcemap we have and the current file and
|
||||||
|
// apply them to the computed position to improve accuracy
|
||||||
|
return res > lineStarts[line + 1] ? lineStarts[line + 1] : typeof debugText === "string" && res > debugText.length ? debugText.length : res;
|
||||||
|
}
|
||||||
if (line < lineStarts.length - 1) {
|
if (line < lineStarts.length - 1) {
|
||||||
Debug.assert(res < lineStarts[line + 1]);
|
Debug.assert(res < lineStarts[line + 1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,7 @@ namespace ts {
|
||||||
|
|
||||||
function processMapping(mapping: Mapping): MappedPosition {
|
function processMapping(mapping: Mapping): MappedPosition {
|
||||||
const generatedPosition = generatedFile !== undefined
|
const generatedPosition = generatedFile !== undefined
|
||||||
? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter)
|
? getPositionOfLineAndCharacterWithEdits(generatedFile, mapping.generatedLine, mapping.generatedCharacter)
|
||||||
: -1;
|
: -1;
|
||||||
let source: string | undefined;
|
let source: string | undefined;
|
||||||
let sourcePosition: number | undefined;
|
let sourcePosition: number | undefined;
|
||||||
|
@ -617,7 +617,7 @@ namespace ts {
|
||||||
const sourceFile = host.getSourceFileLike(sourceFilePath);
|
const sourceFile = host.getSourceFileLike(sourceFilePath);
|
||||||
source = map.sources[mapping.sourceIndex];
|
source = map.sources[mapping.sourceIndex];
|
||||||
sourcePosition = sourceFile !== undefined
|
sourcePosition = sourceFile !== undefined
|
||||||
? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter)
|
? getPositionOfLineAndCharacterWithEdits(sourceFile, mapping.sourceLine, mapping.sourceCharacter)
|
||||||
: -1;
|
: -1;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/// <reference path="../fourslash.ts" />
|
||||||
|
|
||||||
|
// @Filename: /node_modules/a/dist/index.d.ts
|
||||||
|
////export declare class Foo {
|
||||||
|
//// bar: any;
|
||||||
|
////}
|
||||||
|
//////# sourceMappingURL=index.d.ts.map
|
||||||
|
|
||||||
|
// @Filename: /node_modules/a/dist/index.d.ts.map
|
||||||
|
////{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,GAAG,MAAC;CACP"}
|
||||||
|
|
||||||
|
// @Filename: /node_modules/a/src/index.ts
|
||||||
|
////export class /*2*/Foo {
|
||||||
|
////}
|
||||||
|
////
|
||||||
|
|
||||||
|
// @Filename: /node_modules/a/package.json
|
||||||
|
////{
|
||||||
|
//// "name": "a",
|
||||||
|
//// "version": "0.0.0",
|
||||||
|
//// "private": true,
|
||||||
|
//// "main": "dist",
|
||||||
|
//// "types": "dist"
|
||||||
|
////}
|
||||||
|
|
||||||
|
// @Filename: /index.ts
|
||||||
|
////import { Foo/*1*/ } from "a";
|
||||||
|
|
||||||
|
goTo.file("/index.ts");
|
||||||
|
|
||||||
|
goTo.marker("1");
|
||||||
|
verify.goToDefinitionIs("2"); // getDefinitionAndBoundSpan
|
Loading…
Reference in a new issue