Currently render3's `parseTemplate` throws away the parsed AST and
returns an empty list of HTML nodes if HTML->R3 translation failed. This
is not preferrable in some contexts like that of a language service,
where we would like a well-formed AST even if it is has errors.
PR Close#39413
Fixed a boolean logic error that prevented hybrid visitor from returning
undefined when a variable does not have value and cursor is not in the
key span.
PR Close#39061
It used to be the case that all microsyntax bindings share the same source
span, so the second bound attribute would overwrite the first.
This has been fixed in #39036, this case is added to prevent regression.
PR Close#39062
For the following example, the cursor is between `keySpan` and `valueSpan`
of the `BoundAttribute`.
```html
<test-cmp [foo]¦="bar"></test-cmp>
```
Our hybrid visitor will return `Element`in this case, which is the parent
node of the `BoundAttribute`.
This is because we only look at the `keySpan` and `valueSpan`, and not
the source span. The last element in the AST path is `Element`, so it gets
returned.
In this PR, I propose fixing this by adding a sentinel value `undefined`
to the AST path to signal that we've found a source span but the cursor is
neither in the key span nor the value span.
PR Close#38995
The keySpan in bound attributes provides more fine-grained location information and can be used
to disambiguate multiple bound attributes in a single microsyntax binding. Previously,
this case could not distinguish between the two different attributes because
the sourceSpans were identical and valueSpans would not match if the cursor
was located in a key.
PR Close#38955
In a microsyntax expressions, some attributes are not bound after
desugaring. For example,
```html
<div *ngFor="let item of items">
</div>
```
gets desugared to
```html
<ng-template ngFor let-items [ngForOf]="items">
</ngtemplate>
```
In this case, `ngFor` should be a literal attribute with no RHS value.
Therefore, its source span should be just the `keySpan` and not the
source span of the original template node.
This allows language service to precisely pinpoint different spans in a
microsyntax to provide accurate information.
PR Close#38766
Previously this interface was mostly stored in compiler-cli, but it
contains some properties that would be useful for compiling the
"declare component" prelink code.
This commit moves some of the interface over to the compiler
package so that it can be referenced there without creating a
circular dependency between the compiler and compiler-cli.
PR Close#38594
This commit introduces two visitors, one for Template AST and the other
for Expression AST to allow us to easily find the node that most closely
corresponds to a given cursor position.
This is crucial because many language service APIs take in a `position`
parameter, and the information returned depends on how well we can find
a good candidate node.
In View Engine implementation of language service, the search for the node
and the processing of information to return the result are strongly coupled.
This makes the code hard to understand and hard to debug because the stack
trace is often littered with layers of visitor calls.
With this new feature, we could test the "searching" part separately and
colocate all the logic (aka hacks) that's required to retrieve an accurate
span for a given node.
Right now, only the most "narrow" node is returned by the main exported
function `findNodeAtPosition`. If needed, we could expose the entire AST
path, or expose other methods to provide more context for a node.
Note that due to limitations in the template AST interface, there are
a few known cases where microsyntax spans are not recorded properly.
This will be dealt with in a follow-up PR.
PR Close#38540