This commit elaborates diagnostics produced for invalid template
contexts by including the name of the embedded template type using the
template context, and in the common case that the implicity property is
being referenced (e.g. in a `for .. of ..` expression), suggesting to
refine the type of the context. This suggestion is provided because
users will sometimes use a base class as the type of the context in the
embedded view, and a more specific context later on (e.g. in an
`ngOnChanges` method).
Closes https://github.com/angular/vscode-ng-language-service/issues/251
PR Close#34751
This commit adds a regression test to check that the language service
recognizes inputs and outputs declared in a directive decorator.
See #34874.
PR Close#34875
In Angular, symbol can have multiple definitions (e.g. a two-way
binding). This commit adds support for for multiple definitions for a
queried location in a template.
PR Close#34782
This commit makes the Angular Language Service interface a strict subset
of TypeScript's Language Service by renaming all methods to be
consistent with TypeScript's.
The custom Angular `LanguageService` interface was needed before the
inception of TypeScript tsserver plugin, but is now obsolete since
Angular LS is a proper tsserver plugin.
This allows us to easily adapt to upstream TS changes in the future, and
also allows us to reuse all data types defined in TypeScript.
PR Close#34888
The Template AST that corresponds to a given HTML AST is not always
complete, and often has to be reconstructed. This commit refactors the
code to make it easier to adapt to multiple cases.
PR Close#34764
Adds a `typeArguments` method to the `Symbol` interface, cleaning up how
type parameters of a TypeScript type are currently found. This will be
necessary for providing completions for `$event` variables' properties
(#34570).
This commit also performs some fly-by cleanups seen while implementing
the `typeArguments` methods. There is more clean up to do in the
`typescript_symbols` file, but the scope of this commit didn't need to
get larger.
PR Close#34571
Currently the language service constructs an `AttrAst` anytime it is
missing from a `TemplateAst` path. However, this should only be done
when the path does not contain an "attribute-like" AST, which can
includes bound properties or bound events.
This commit also refactors `visitAttr` to parse bindings only for
microsyntax expressions and does some other minor cleanup to make
linters happy.
This is some cleanup to help the language service eventually use
`BoundDirectivePropertyAst`s for providing completions for template
bindings rather than performing the manual parsing currently done.
PR Close#34743
This commit removes some test scenarios from `parsing-cases.ts` and
colocate them with the test code instead. This makes the tests easier to
read and understand.
PR Close#34716
This commit renames `addAttributeValuesToCompletions`, which generates
expression completions and is not exclusive to processing attributes, to
`processExpressionCompletions`. Also removes the expression completion
logic in `visitBoundText` for a call to `processExpressionCompletions`.
The conditional branch in `visitBoundText` is also removed. This branch
was added in one of the first commits to the language service
(519a324454) and appears to be
unnecessary, as the expression AST is constructed from the template
position anyway.
PR Close#34518
The compiler's `I18NHtmlParser` may expand template nodes that have
internationalization metadata attached to them; for instance,
```html
<div i18n="@@i18n-el">{{}}</div>
```
gets expanded to an AST with the i18n metadata extracted and text filled
in as necessary; to the language service, the template above, as read in
the AST, now looks something like
```html
<div>{{$implicit}}</div>
```
This is undesirable for the language service because we want to preserve
the original form of the source template source code, and have
information about the original values of the template. The language
service also does not need to use an i18n parser -- we don't generate
any template output.
To fix this turns out to be as easy as moving to using a raw
`HtmlParser`.
---
A note on the testing strategy: as mentioned above, we don't need to use
an i18n parser, but we don't **not** need to use one if the parser
does not heavily modify the template AST. For this reason, the tests
target the functionality of not modifying a template with i18n metadata
rather than testing that the language service does not use an i18n parser.
---
Closes https://github.com/angular/vscode-ng-language-service/issues/272
PR Close#34531
Currently, the language service provides completions in a template node
attribute by first checking if the attribute contains template bindings
to provide completions for, and then providing completions for the
expression in the attribute.
In the latter case, the expression AST was being constructed
"synthetically" inside the language service, in particular declaring the
expression to be a `PropertyRead` with an implicit receiver.
Unfortunately, this AST can be incorrect if the expression is actually a
property read on a component property receiver (e.g. when reading
`key` in the expression `obj.key`, `obj` is the receiver).
The fix is pretty simple - rather than a synthetic construction of the
AST, ask the expression parser to parse the expression in the attribute.
Fixes https://github.com/angular/vscode-ng-language-service/issues/523
PR Close#34517
This commit fixes a bug in which we do testing for completions.
Subsequently, this exposes another bug in our implementation whereby
suggestions are not provided in "ngFor" where there should have been.
Currently, multiple test cases are grouped together in a single
template. This requires the template to be somewhat complete so that
test cases that depend on variables declared earlier would pass.
Consider the following example:
```
template: `
<div *ngFor="let ~{for-person}person of ~{for-people}people">
<span>Name: {{~{for-interp-person}person.~{for-interp-name}name}}</span>
<span>Age: {{person.~{for-interp-age}age}}</span>
</div>`,
```
In order to test `~{for-interp-person}`, `people` has to be included after
`~{for-people}`. This means the test case for `~{for-people}` is not
reflective of the actual use case because the variable is already there!
In real case, the expression would be incomplete, and our implementation
failed to take that into account.
This commit breaks such test into individual tests, and fix the bugs in
the underlying implementation.
PR Close#34473
When a HTML Ast containing an Attribute node is converted to a Template Ast,
the attribute node might get dropped from the Template Ast path.
This is because the AttrNode is not even in the Template Ast to begin with.
In this case, we manually fix the path by converting the Attribute node
to a AttrAst node and appending it to the path.
This allows the `ExpressionVisitor` to properly visit the leaf node in the
TemplateAst path. We no longer need to visit the `Element` and look for
attributes.
PR Close#34459
Given the following HTML and cursor position:
```
<div c|></div>
^ cursor is here
```
Note that the cursor is **after** the attribute `c`.
Under the current implementation, only `Element` is included in the
path. Instead, it should be `Element -> Attribute`.
This bug occurs only for cases where the cursor is right after the Node,
and it is because the `end` position of the span is excluded from the search.
Instead, the `end` position should be included.
PR Close#34440
`let` and `of` should be considered reserved keywords in template syntax
and thus should not be part of the autocomplete suggestions.
For reference, TypeScript does not provide such completions.
This commit removes these results and cleans up the code.
PR Close#34434
Due to a bug in the existing banner, `typescript` module was require-d
instead of reusing the module passed in from tsserver.
This bug is caused by some source files in language-service that imports
`typescript` instead of `typescript/lib/tsserverlibrary`.
This is not an unsupported use case, it's just that when typescript is
resolved in the banner we have to be very careful about which modules to
"require".
The convoluted logic in the banner makes it very hard to detect
anomalies. This commit cleans it up and removes a lot of unneeded code.
This commit also removes `ts` import in typescript_host.ts and use `tss`
instead to make it less confusing.
PR Close#34262
If a Component or Directive is not part of any NgModule, the language
service currently produces an error message. This should not be an
error. Instead, it should be a suggestion.
This PR removes `ng.DiagnosticKind`, and instead reuses
`ts.DiagnosticCategory`.
PR closes https://github.com/angular/vscode-ng-language-service/issues/458
PR Close#34115
The language service incorrectly reports an error if it fails to find
NgModule metadata for a particular Component / Directive. In many cases,
the use case is legit, particularly in test.
This commit removes such diagnostic message and cleans up the interface
for `TypeScriptHost.getTemplateAst()`.
PR closes https://github.com/angular/vscode-ng-language-service/issues/463
PR Close#34113
Currently, variables of an unknown type in an `*ngFor` expression are
refined to have the type of the iterable binding of the `*ngFor`
expression. Unfortunately, this is a bug for variables aliasing
[values exported by
`*ngFor`](https://angular.io/api/common/NgForOf#local-variables),
including `index` and `first`, because they are also given the type of
the binding expression, but they are not of the binding type. For
example, in
```typescript
@Component({
selector: 'test',
template: `
<div *ngFor="let hero of heroes; let i = index; let isFirst = first">
{{ hero }}
</div>
`
})
export class TestComponent {
heroes: Hero[];
}
```
The local variables `i` and `isFirst` are determined to have a type of
`Hero`, when actually their types are `number` and `boolean`,
respectively.
This commit fixes this bug by checking if the value of a variable in an
`*ngFor` expression is known to be an export and assigning the variable
the type of that export value. Only if the variable does not alias an
export is it typed with the binding value of the `*ngFor` expression.
Closes https://github.com/angular/vscode-ng-language-service/issues/460
PR Close#34089
Commit 53fc2ed8bf added support for
determining index types accessed using index signatures, but did not
include support for index types accessed using dot notation:
```typescript
const obj<T>: { [key: string]: T };
obj['stringKey']. // gets `T.` completions
obj.stringKey. // did not peviously get `T.` completions
```
This adds support for determining an index type accessed via dot
notation by rigging an object's symbol table to return the string index
signature type a property access refers to, if that property does not
explicitly exist on the object. This is very similar to @ivanwonder's
work in #29811.
`SymbolWrapper` now takes an additional parameter to explicitly set the
type of the symbol wrapped. This is done because
`SymbolTableWrapper#get` only has access to the symbol of the index
type, _not_ the index signature symbol itself. An attempt to get the
type of the index type will give an error.
Closes#29811
Closes https://github.com/angular/vscode-ng-language-service/issues/126
PR Close#33884
When performing diagnostic checks or completions, we should take into
account members and properties in the base class, if any. Otherwise, the
language service will produce a false error.
PR closes https://github.com/angular/vscode-ng-language-service/issues/93
PR Close#34041