[api] Add SourceFile line mapping methods#4420
Conversation
There was a problem hiding this comment.
Pull request overview
Adds line/character mapping helpers to the native-preview SourceFile API surface to close #4215, enabling consumers to convert between UTF-16 positions and { line, character } pairs.
Changes:
- Introduces
LineAndCharacterand addsgetLineStarts,getLineAndCharacterOfPosition, andgetPositionOfLineAndCharacterto theSourceFileinterface. - Implements these methods on
RemoteSourceFile, including a cached line-starts array and a binary search for position-to-line mapping. - Adds encoder round-trip tests covering line starts, UTF-16 semantics, and line/character ↔ position conversion.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| _packages/native-preview/test/encoder.test.ts | Adds tests validating line start computation, UTF-16 line/character mapping, caching, and round-tripping. |
| _packages/native-preview/src/ast/ast.ts | Extends the public AST types with LineAndCharacter and new SourceFile mapping APIs. |
| _packages/native-preview/src/api/node/node.ts | Implements the new mapping APIs on RemoteSourceFile using computeLineStarts + binary search. |
| getLineAndCharacterOfPosition(position: number): LineAndCharacter { | ||
| const lineStarts = this.getLineStarts(); | ||
| const line = computeLineOfPosition(lineStarts, position); | ||
| return { line, character: position - lineStarts[line] }; | ||
| } |
There was a problem hiding this comment.
The Strada implementation doesn't guard, so I think it's fine as-is
| getPositionOfLineAndCharacter(line: number, character: number): number { | ||
| const lineStarts = this.getLineStarts(); | ||
| if (line < 0 || line >= lineStarts.length) { | ||
| throw new Error(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length}`); | ||
| } | ||
| return lineStarts[line] + character; | ||
| } |
|
@andrewbranch Thanks for working on this. I bumped into another limitation and was thinking about a solution. The only place my app is using these is diagnostic formatting logic. This is handy when a diagnostic spans multiple lines. It works well with Strada API, because The problem is that errors of TSConfig files are also reported as Perhaps the line mapping could be implemented as a separate utility class rather than adding them directly to class TextFile {
constructor(text: string) {
// ...
}
getLineStarts(): readonly number[] {
// ...
}
getLineAndCharacterOfPosition(position: number): LineAndCharacter {
// ...
}
// ...
} |
|
Thanks for making me realize this PR never merged 😅 Actually, tsconfig files do have SourceFiles (Strada has APIs for parsing them but not fetching them), so I wonder if it would be enough to expose a way of getting at those? |
|
Yes, some way of getting In a way it is clear that |
Closes #4215