Commit Graph

214 Commits

Author SHA1 Message Date
ayazhafiz df890d7629 fix(compiler): record correct end of expression (#34690)
This commit fixes a bug with the expression parser wherein the end index
of an expression node was recorded as the start index of the next token,
not the end index of the current token.

Closes #33477
Closes https://github.com/angular/vscode-ng-language-service/issues/433

PR Close #34690
2020-03-20 10:19:02 -07:00
ayazhafiz acc483e2eb feat(language-service): improve non-callable error message (#35271)
This commit improves the context of a non-callable function error
message by providing the affected call target and its non-callable type.

PR Close #35271
2020-03-17 09:28:59 -07:00
ayazhafiz 18b1bd4415 fix(language-service): infer $implicit value for ngIf template contexts (#35941)
Today, the language service infers the type of variables bound to the
"ngIf" template context member of an NgIf directive, but does not do the
same for the the "$implicit" context member. This commit adds support
for that.

Fixes https://github.com/angular/vscode-ng-language-service/issues/676

PR Close #35941
2020-03-11 14:52:27 -04:00
Keen Yee Liau 06779cfe24 feat(compiler): Add sourceSpan and keySpan to TemplateBinding (#35897)
This commit adds fine-grained text spans to TemplateBinding for microsyntax expressions.

1. Source span
   By convention, source span refers to the entire span of the binding,
   including its key and value.
2. Key span
   Span of the binding key, without any whitespace or keywords like `let`

The value span is captured by the value expression AST.

This is part of a series of PRs to fix source span mapping in microsyntax expression.
For more info, see the doc https://docs.google.com/document/d/1mEVF2pSSMSnOloqOPQTYNiAJO0XQxA1H0BZyESASOrE/edit?usp=sharing

PR Close #35897
2020-03-11 14:51:56 -04:00
ivanwonder 3d46a45fa8 fix(language-service): resolve the variable from the template context first (#35982)
PR Close #35982
2020-03-10 13:27:04 -04:00
ayazhafiz 406419bc0f fix(language-service): fix calculation of pipe spans (#35986)
This commit accomplishes two tasks:

- Fixes the span of queried pipes to only be applied on pipe names
- By consequence, fixes how pipes are located in arguments (previously,
  pipes with arguments could not be found because the span of a pipe
  uses a relative span, while the template position is absolute)

The screenshots attached to the PR for this commit demonstrate the
change.

Closes https://github.com/angular/vscode-ng-language-service/issues/677

PR Close #35986
2020-03-10 13:26:40 -04:00
Keen Yee Liau bef14cf424 refactor(compiler): rename _ParseAST.optionalCharacter TemplateBinding.expression (#35886)
This commit renames
1. _ParseAST.optionalCharacter -> consumeOptionalCharacter
2. TemplateBinding.expression -> value

PR Close #35886
2020-03-06 12:39:49 -05:00
ivanwonder 4e1d780554 fix(language-service): resolve the real path for symlink (#35895)
when AOT resolves the module name, it will preserve the path of the symlink, but the ts-server will return the real path for symlink.

PR Close #35895
2020-03-06 12:38:55 -05:00
ayazhafiz 47a1811e0b feat(language-service): modularize error messages (#35678)
This commit performs a modularization of the Language Service's existing
diagnostic messages. Such a modularization has two primary advantages:

- Centralization and decoupling of error messages from the code that
  generates them makes it easy to add/delete/edit diagnostic messages,
  and allows for independent iteration of diagnostic messages and
  diagnostic generation.
- Prepares for additional features like annotating the locations where a
  diagnostic is generated and enabling the configuration of which
  diagnostics should be reported by the language service.

Although it would be preferable to place the diagnostics registry in an
independent JSON file, for ease of typing diagnostic types as an enum
variant of 'ts.DiagnosticCategory', the registry is stored as an object.

Part of #32663.

PR Close #35678
2020-03-03 08:49:34 -08:00
Keen Yee Liau 208ef7bd62 refactor(compiler): Remove NullAstVisitor and visitAstChildren (#35619)
This commit removes the `NullAstVisitor` and `visitAstChildren` exported
from `packages/compiler/src/expression_parser/ast.ts` because they
contain duplicate and buggy implementation, and their use cases could be
sufficiently covered by `RecursiveAstVisitor` if the latter implements the
`visit` method. This use case is only needed in the language service.

With this change, any visitor that extends `RecursiveAstVisitor` could
just define their own `visit` function and the parent class will behave
correctly.

A bit of historical context:
In language service, we need a way to tranverse the expression AST in a
selective manner based on where the user's cursor is. This means we need a
"filtering" function to decide which node to visit and which node to not
visit. Instead of refactoring `RecursiveAstVisitor` to support this,
`visitAstChildren` was created. `visitAstChildren` duplicates the
implementation of `RecursiveAstVisitor`, but introduced some bugs along
the way. For example, in `visitKeyedWrite`, it visits
```
obj -> key -> obj
```
instead of
```
obj -> key -> value
```

Moreover, because of the following line
```
visitor.visit && visitor.visit(ast, context) || ast.visit(visitor, context);
```
`visitAstChildren` visits every node *twice*.

PR Close #35619
2020-02-28 07:13:17 -08:00
ivanwonder 8e354dae00 fix(language-service): get the right 'ElementAst' in the nested HTML tag (#35317)
For example, '<div><p string-model~{cursor}></p></div>', when provide the hover info for 'string-model', the 'path.head' is root tag 'div'. Use the parent of 'path.tail' instead.

PR Close #35317
2020-02-25 13:12:08 -08:00
ivanwonder 049f118c1b fix(language-service): provide hover for interpolation in attribute value (#35494)
I think the bug is introduced in my PR#34847. For example, 'model="{{title}}"', the attribute value cannot be parsed by 'parseTemplateBindings'.

PR Close #35494
2020-02-21 12:35:51 -08:00
Pusztai Tibor 54fd33fb80 fix(language-service): infer context type of structural directives (#35537) (#35561)
PR Close #35561
2020-02-21 09:11:54 -08:00
ivanwonder 66c06eb1ad fix(language-service): provide completions for the structural directive that only injects the 'ViewContainerRef' (#35466)
The completions list don't include the 'ngTemplateOutlet'. The directive is a structural directive when it has injected the 'TemplateRef' or 'ViewContainerRef'.

PR Close #35466
2020-02-20 15:12:50 -08:00
Keen Yee Liau 81241af7ac fix(language-service): Suggest ? and ! operator on nullable receiver (#35200)
Under strict mode, the language service fails to typecheck nullable
symbols that have already been verified to be non-null.

This generates incorrect (false positive) and confusing diagnostics
for users.

To work around this issue in the short term, this commit changes the
diagnostic message from an error to a suggestion, and prompts users to
use the safe navigation operator (?) or non-null assertion operator (!).

For example, instead of

```typescript
{{ optional && optional.toString() }}
```

the following is cleaner:

```typescript
{{ optional?.toString() }}
{{ optional!.toString() }}
```

Note that with this change, users who legitimately make a typo in their
code will no longer see an error. I think this is acceptable, since
false positive is worse than false negative. However, if users follow
the suggestion, add ? or ! to their code, then the error will be surfaced.
This seems a reasonable trade-off.

References:

1. Safe navigation operator (?)
   https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths
2. Non-null assertion operator (!)
   https://angular.io/guide/template-syntax#the-non-null-assertion-operator---

PR closes https://github.com/angular/angular/pull/35070
PR closes https://github.com/angular/vscode-ng-language-service/issues/589

PR Close #35200
2020-02-10 16:43:44 -08:00
Keen Yee Liau a8609ba0ad refactor(language-service): dedupe diagnostics using ts utility function (#35086)
This commit makes a minor refactoring that replaces `uniqueBySpan` with
`ts.sortAndDeduplicateDiagnostics()`.

PR Close #35086
2020-02-03 08:57:58 -08:00
Keen Yee Liau c8584e5d36 refactor(language-service): Replace TypeDiagnostic with ng.Diagnostic (#35085)
This commit cleans up `expression_type.ts` by

1. Removing the unnecessary `TypeDiagnostic` class. It's replaced by
`ng.Diagnostic`.
2. Consolidating `reportError()` and `reportWarning()` to
`reportDiagnostic()`.

This is prep work so that we could make some of the type diagnostics a
suggestion in later PRs.

PR Close #35085
2020-02-03 08:57:18 -08:00
Ayaz Hafiz b608fa55f0 fix(language-service): warn, not error, on missing context members (#35036)
The language service reports an error when a directive's template
context is missing a member that is being used in a template (e.g. if
`$implicit` is being used with a template context typed as `any`).
While this diagnostic message is valuable, typing template contexts
loosely as `any` or `object` is very widespread in community packages,
and often still compiles correctly, so reporting the diagnostic as an
error may be misleading to users.

This commit changes the diagnostic to be a warning, and adds additional
information about how the user can eliminate the warning entirely -- by
refining the template context type.

Closes https://github.com/angular/vscode-ng-language-service/issues/572

PR Close #35036
2020-01-29 12:22:09 -08:00
ayazhafiz b64ead5cb8 fix(language-service): prune duplicate returned definitions (#34995)
Sometimes, a request for definitions will return multiple of the same
definition. This can happen in at least the cases of

- two-way bindings (one of the same definition for the property and
  event binding)
- multiple template binding expressions in the same attribute
  - something like "*ngFor="let i of items; trackBy: test" has two
    template bindings, resulting in two template binding ASTs at the
    same location (the attribute span). The language service then parses
    both of these bindings individually, resulting in two independent
    but identical definitions. For more context, see https://github.com/angular/angular/pull/34847#discussion_r371006680.

This commit prunes duplicate definitions by signing definitions with
their location, and checking if that location signature has been seen in
a previous definition returned to the client.

PR Close #34995
2020-01-29 12:21:04 -08:00
ayazhafiz e7c74cbd69 feat(language-service): completions for output $event properties in (#34570)
This commit adds support for completions of properties on `$event`
variables in bound outputs.

This is the second major PR to support completions for `$event`
variables (https://github.com/angular/vscode-ng-language-service/issues/531).
The final completion support that must be provided is for `$event`
variables in bindings targeting DOM events, like `(click)`.

PR Close #34570
2020-01-28 09:07:43 -08:00
ayazhafiz 24864ee71e feat(language-service): provide completion for $event variable (#34570)
This commit adds a completion for the `$event` variable in bound event
expressions.

This is the first in a series of PRs to support completions for
properties on `$event` variables (https://github.com/angular/vscode-ng-language-service/issues/531).

PR Close #34570
2020-01-28 09:07:43 -08:00
Ayaz Hafiz 90b303faa3 refactor(language-service): make findOutputBinding a utility function (#34997)
This commit makes `findOutputBinding` a utility function for the
language service, which will be used by the `expression_diagnostics`
module in #34570. Keeping the function in `locate_symbol` results in a
circular dependency between `expression_diagnostics` and
`locate_symbol`.

PR Close #34997
2020-01-27 15:53:57 -08:00
ivanwonder 09869af90f fix(language-service): remove repeated symbol definitions for structural directive (#34847)
For the structural directive, the 'path' will contain multiple `BoundDirectivePropertyAst` which depends on the number of directive property in the attribute value(e.g. '*ngFor="let item of []; trackBy: test;"', it has 2 `BoundDirectivePropertyAst`, 'ngForOf' and 'ngForTrackBy').

PR Close #34847
2020-01-27 10:47:46 -08:00
ivanwonder e7dff9eb0c feat(language-service): provide hover for microsyntax in structural directive (#34847)
PR Close #34847
2020-01-27 10:47:46 -08:00
Keen Yee Liau 3414ef276e refactor(language-service): Avoid leaking host outside of LanguageService (#34941)
As part of the effort to tighten the API surface of
`TypeScriptServiceHost` in preparation for the migration to Ivy, I realized
some recently added APIs are not strictly needed.
They can be safely removed without sacrificing functionality.

This allows us to clean up the code, especially in the implementation of
QuickInfo, where the `TypeScriptServiceHost` is leaked outside of the
`LanguageService` class.

This refactoring also cleans up some duplicate code where the QuickInfo
object is generated. The logic is now consolidated into a simple
`createQuickInfo` method shared across two different implementations.

PR Close #34941
2020-01-24 15:53:52 -08:00
Keen Yee Liau 0223aa6121 fix(language-service): Diagnostic span should point to class name (#34932)
Right now, if an Angular diagnostic is generated for a TypeScript node,
the span points to the decorator Identifier, i.e. the Identifier node
like `@NgModule`, `@Component`, etc.
This is weird. It should point to the class name instead.
Note, we do not have a more fine-grained breakdown of the span when
diagnostics are emitted, this work remains to be done.

PR Close #34932
2020-01-23 15:55:44 -08:00
Keen Yee Liau b50ed5c22c fix(language-service): Make metadata in Declaration non-optional (#34936)
The `metadata` field in `Declaration` should not be optional.

PR Close #34936
2020-01-23 15:54:59 -08:00
ayazhafiz 4ba478267e feat(language-service): specific suggestions for template context diags (#34751)
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
2020-01-23 12:25:42 -08:00
Ayaz Hafiz 1ea04ffc05 feat(language-service): support multiple symbol definitions (#34782)
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
2020-01-23 10:14:19 -08:00
Keen Yee Liau f723a27a71 refactor(language-service): Consistent naming between ts and ng LanguageService (#34888)
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
2020-01-22 14:36:04 -05:00
ayazhafiz 6c8e322fa1 refactor(language-service): cleanup of low-hanging TODOs (#34784)
Cleans up some simple TODOs. Also removes
`typescript_symbols#getTypeWrapper`, which I thought I had but failed to
remove in #34571.

PR Close #34784
2020-01-21 13:09:30 -05:00
Andrius 1f79e624d1 build: typescript 3.7 support (#33717)
This PR updates TypeScript version to 3.7 while retaining compatibility with TS3.6.

PR Close #33717
2020-01-14 16:42:21 -08:00
ayazhafiz d7ea389c84 feat(language-service): provide completion for $event variable (#34566)
This commit adds a completion for the `$event` variable in bound event
expressions.

This is the first in a series of PRs to support completions for
properties on `$event` variables (https://github.com/angular/vscode-ng-language-service/issues/531).

PR Close #34566
2020-01-14 15:54:02 -08:00
Keen Yee Liau 84c659e246 refactor(language-service): Construct proper template AST from HTML ast (#34764)
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
2020-01-14 13:32:58 -08:00
ivanwonder 1a453872c8 fix(language-service): apply suggested change. (#34564)
PR Close #34564
2020-01-14 09:30:27 -08:00
ivanwonder 6f916c1240 fix(language-service): only visit directives (#34564)
PR Close #34564
2020-01-14 09:30:27 -08:00
ivanwonder c8c6fd7153 refactor(language-service): test case (#34564)
PR Close #34564
2020-01-14 09:30:27 -08:00
ivanwonder 7005645592 fix(language-service): break the hover/definitions for two-way binding (#34564)
PR Close #34564
2020-01-14 09:30:27 -08:00
ivanwonder 5260021447 feat(language-service): support hover/definitions for structural directive (#34564)
PR Close #34564
2020-01-14 09:30:26 -08:00
ayazhafiz 7325053dfa refactor(language-service): adds Symbol#typeArguments and does cleanup (#34571)
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
2020-01-13 15:16:15 -08:00
ayazhafiz 15b4173a76 refactor(language-service): create attr for missing attr, bound tmpl (#34743)
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
2020-01-13 15:04:37 -08:00
Keen Yee Liau bfe9bc912a fix(language-service): CRLF offset in inline template (#34737)
This commit fixes incorrect CRLF offsets in inline template.

PR closes https://github.com/angular/vscode-ng-language-service/issues/520

PR Close #34737
2020-01-13 07:16:50 -08:00
ayazhafiz 4d95c3d39a refactor(language-service): rename expression completions method (#34518)
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
2020-01-10 08:31:09 -08:00
ayazhafiz 794dcb58d3 fix(language-service): do not use an i18n parser for templates (#34531)
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
2020-01-10 08:23:08 -08:00
ivanwonder 181d766941 feat(language-service): completions support for template reference variables (#34363)
PR Close #34363
2020-01-09 13:45:42 -08:00
ayazhafiz ee46b9b44f fix(language-service): correctly parse expressions in an attribute (#34517)
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
2020-01-06 11:37:21 -08:00
Keen Yee Liau c079f38cbb feat(language-service): Show documentation on hover (#34506)
This commit adds dpcumentation to the hover tooltip.

PR closes https://github.com/angular/vscode-ng-language-service/issues/321

PR Close #34506
2020-01-06 11:36:57 -08:00
ivanwonder ba2fd31e62 fix(language-service): The pipe method should not include parentheses (#34485)
PR Close #34485
2020-01-06 11:31:14 -08:00
Keen Yee Liau 9b9116c79d feat(language-service): Append symbol type to hover tooltip (#34515)
Now that https://github.com/angular/angular/pull/34177 fixed the `TypeWrapper`
to have a proper name, we have the information needed to show the type
name in a hover tooltip.

PR Close #34515
2019-12-20 14:40:04 -08:00
Keen Yee Liau 2dffe65cfd fix(language-service): completions after "let x of |" in ngFor (#34473)
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
2019-12-19 11:34:03 -08:00