Skip to content

Support overlapping mapping ranges #203

@piotrtomiak

Description

@piotrtomiak

I am continuing my work on Angular support and a lot of stuff is working correctly in version 2.3.0, however there is one problem with transpilation of ?., which for historical reasons works differently then TypeScript version of ?.. Let me describe the problem.

Problem

WebStorm is using TypeScript server to provide types of expressions. For instance, if we have foo.bar.fooBar expression, to get the type of fooBar property, WebStorm will check expression type of the whole range foo.bar.fooBar. This fails to work with transpiled ?. though. Currently, the ranges would be incorrectly mapped from the source file to generated file, e.g. data?.icon would be mapped to data)!.icon.

Visualization of Angular Template Transpilation 2024-06-17 11-36-46

The problem is that ?. is expanded to a whole expression, so we need to add more mappings and they will start overlapping:

Visualization of Angular Template Transpilation 2024-06-17 11-38-39

So, if we map source range data?.icon we should get (null as any ? (this.data)!.icon : undefined) generated range, but if we want to map an error from generated range that icon property does not exist on data, we should get a different mapping:

Visualization of Angular Template Transpilation 2024-06-17 11-39-51

Solution

I want to store source mappings in an interval tree (e.g. https://www.npmjs.com/package/@flatten-js/interval-tree). This will allow for a given text range to find all mappings containing a start point and an end point in O(ln(n)) time (where n is number of mappings) and then find among them the best match:

  1. If there are mappings containing both start and end point - find the smallest range among them. If start and end match perfectly use the target range as is.
    This also solves issues with mapping of e.g. _t1 to fooBar (when lengths of source and generated code are different). Currently you get _t1 mapped to foo instead of fooBar.
  2. Otherwise find the smallest mapping containing start and the smallest mapping containing end point and use them for mapping start and end separately.

@johnsoncodehk - I can implement the solution and provide a PR with it. Let me know what you think about this!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions