Commit Graph

144 Commits

Author SHA1 Message Date
Paul Gschwendtner 8d3365e4fc fix(core): static-query usage migration strategy should detect ambiguous query usage (#30215)
Currently we always just set the timing to `false` if we aren't
able to analyze a given call expression or new expression. e.g.

```ts
ngOnInit() {
  thirdPartyCallSync(() => this.query.doSomething())
}
```

In that case the `thirdPartyCallSync` function comes from the `node_modules`
and is only defined through types while there is no code for the
actual function logic that can be analyzed. This makes it impossible
to tell whether the given call expression actually causes the specified
arrow function to be executed synchronously or not. In order to be able
to make this better, we now peek into the passed arrow function and
check for a synchronous query usage. If so, we set the query timing to
static and mark it as ambiguous. This ensures that the usage strategy is
less "magical" and more correct with third-party code.

Additionally since functions like `setTimeout` are not analyzable but known
to be asynchronous, there is a hard-coded list of known functions which
shouldn't be marked as ambiguous.

Resolves FW-1214. As planned within https://hackmd.io/hPiLWpPlQ4uynC1luIBdfQ

PR Close #30215
2019-05-09 14:39:06 -07:00
Paul Gschwendtner 0ffdb48f62 fix(core): static-query migration should handle queries on accessors (#30327)
Currently the static-query migration ignores queries declared on getters
or setters as these are not part of a `PropertyDeclaration`. We need to
handle these queries in order to cover all queries within a given project.

The usage strategy is not able to detect timing for queries on accessors,
so we add a TODO and print a message. The template strategy is able
to detect the proper timing for such queries because it's not dependent
on detecting the usage of the query.

Resolves FW-1215

PR Close #30327
2019-05-09 11:22:37 -07:00
Paul Gschwendtner 509352fc36 fix(core): static-query migration should gracefully exit if AOT compiler throws (#30269)
The static-query template strategy leverages the AOT compiler
in order to determine the query timing. Unfortunately the AOT
compiler has open bugs that can cause unexpected failures which
make the template strategy unusable in rare cases. These rare
exceptions need to be handled gracefully in order to avoid confusion
and to provide a more smooth migration.

Additionally migration strategy setup failures are now reported with
stack traces as the `ng update` command does not print stack traces.
This makes it easier to reproduce and report migration issues.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner 349935a434 fix(core): migrations not always migrating all files (#30269)
In an Angular CLI project scenario where projects only reference
top-level source-files through the `tsconfig` `files` option, we currently
do not migrate referenced source-files. This can be fixed checking all
referenced source-files which aren't coming from an external library.

This is similar to how `tslint` determines project source-files.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner 6357d4a0d3 fix(core): static-query migration fails with default parameter values (#30269)
Currently when someone has a call expression within the `ngOnInit` call
and we try to peek into that function with respect to the current function
context, the schematic errors because a call expression argument is
undefined. This is valid because the target function declaration defines
that parameter with a default value. In order to fix this, we need to
respect parameter default values.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner f094bb54a7 test(core): run schematic tests with public migration collection (#30198)
572b54967c changed how the schematic
tests are executed. Tests no longer use the schematic collection
that is also used by the CLI `ng update` command and therefore
the migration collection could  technically be invalid.

In order to ensure that the public migration collection is guaranteed
to work and to avoid duplication within two schematic collections, the
changes are partially reverted and only the disabled `injectable-pipe`
schematic has its own collection.

PR Close #30198
2019-05-08 09:23:28 -07:00
Paul Gschwendtner 4c12d742dc fix(core): static-query migration should not prompt if no queries are used (#30254)
Currently we always prompt when the static-query migration runs. This is not
always needed because some applications do not even use `ViewChild` or
`ContentChild` queries and it just causes confusion if developers need to
decide on a migration strategy while there is nothing to migrate.

In order to avoid this confusion, we no longer prompt for a strategy
if there are no queries declared within the project.

PR Close #30254
2019-05-08 09:22:48 -07:00
Paul Gschwendtner 164d160b22 refactor(core): static-query migrations fails if options cannot be transformed (#30178)
Currently the `static-query` migrations fails at the final step of
updating a query when the query already specifies options which
cannot be transformed easily. e.g. the options are computed through
a function call: `@ViewChild(..., getQueryOpts());` or `@ViewChild(..., myOptionsVar)`.

In these cases we technically could add additionally logic to update
the query options, but given that this is an edge-case and it's
potentially over-engineering the migration schematic, we just
always add a TODO for the timing and print out the determined
query timing in the console. The developer in that case just needs
to manually update the logic for the query options to contain the
printed query timing.

Potentially related to: https://github.com/angular/angular-cli/issues/14298

PR Close #30178
2019-04-29 13:30:37 -07:00
crisbeto 572b54967c fix: disable injectable-pipe migration (#30180)
Disables the injectable pipe migration until we can decide whether this is the right solution for Ivy. Rolling it out properly will involve a more detailed plan and more changes like updating the styleguide, scaffolding schematics etc.

Context for the new `test-migrations.json`: since we use the `migrations.json` both for the real migrations and for tests, it doesn't allow us to disable a schematic, but continue running its tests. This change adds the test-specific file so that we can continue running the `injectable-pipe` tests, even though the schematic itself is disabled.

PR Close #30180
2019-04-29 09:40:00 -07:00
crisbeto 6f433887e0 fix(ivy): injectable pipe schematic generating incorrect import statements (#30170)
Currently the injectable pipe schematic generates invalid imports like `import import { Pipe, PipeTransform, Injectable } from '@angular/core'; from '@angular/core';`. The issue wasn't caught by the unit tests, because the invalid import still contains the valid one.

Fixes #30159.

PR Close #30170
2019-04-29 09:39:11 -07:00
Kristiyan Kostadinov d92fb25161 feat(ivy): add injectable-pipe schematic (#29847)
Adds a schematic that will annotate all `Pipe` classes with `Injectable` so that they can be injected.

This PR resolves FW-1228.

PR Close #29847
2019-04-23 15:12:19 -07:00
Paul Gschwendtner 364250e7a6 refactor(core): static-query migration should not fail for test files (#30034)
Currently when someone runs `ng update` with the static-query migration,
the migration can fail with an error saying that the `AOT` compiler could not
be created. This can happen if the CLI project contains a test `tsconfig.json`
that is picked up by the schematic.

Due to the fact that spec tsconfig files cannot be ran with NGC (e.g. test
components are not part of a module; not all source files are guaranteed to
be included), test `tsconfig` projects will now use a new `test` migration
strategy where all queries within tests are left untouched and a TODO is added.

PR Close #30034
2019-04-23 08:32:35 -07:00
Paul Gschwendtner a9242c4fc2 refactor(core): template-var-assignment migration incorrectly warns (#30026)
Currently the `template-var-assignment` migration incorrectly warns if
the template writes to a property in the component that has the same
`ast.PropertyWrite´ name as a template input variable but different
receiver. e.g.

```html
<!-- "someProp.element" will be incorrectly reported as template variable assignment -->
<button *ngFor="let element of list" (click)="someProp.element = null">Reset</button>
```

Similarly if an output writes to a component property with the same name as a
template input variable, but the expression is within a different template scope,
the schematic currently incorrectly warns. e.g.

```html
<button *ngFor="let element of list">{{element}}</button>

<!-- The "element = null" expression does not refer to the "element" template input variable -->
<button (click)="element = null"></button>
```

PR Close #30026
2019-04-22 11:16:19 -07:00
Adam Plumer 645e305733 feat(core): add schematics to move deprecated DOCUMENT import (#29950)
PR Close #29950
2019-04-22 08:48:48 -07:00
Paul Gschwendtner c1d5fbd0ad refactor(core): static-query template strategy should not parse stylesheets (#29876)
Currently the `template-strategy` for the static query migration uses the
Angular compiler in order to determine the query timing. This is problematic
as the AngularCompilerProgram also collects metadata for referenced
component stylesheets which aren't necessarily present. e.g. in a CLI
project the component can reference a Sass file. It's not guaranteed
that the standalone Angular compiler plugin supports Sass without
custom logic that is brought in by the Angular CLI webpack plugin.

In order to avoid any failures for invalid stylesheets, we just disable
normalizing of all referenced stylesheets.

PR Close #29876
2019-04-18 18:22:09 -07:00
Paul Gschwendtner ca591641c7 refactor(core): allow developers to select static-query migration strategy (#29876)
Currently there are two available migration strategies for the `static-query`
schematic. Both have benefits and negatives which depend on what the
developer prefers. Since we can't decide which migration strategy is the
best for a given project, the developer should be able to select a specific
strategy through a simple choice prompt.

In order to be able to use prompts in a migration schematic, we need to
take advantage of the "inquirer" package which is also used by the CLI
schematic prompts (schematic prompts are usually only statically defined
in the schema). Additionally the schematic needs to be made "async"
because with prompts the schematic can no longer execute synchronously
without implementing some logic that blocks the execution.

PR Close #29876
2019-04-18 18:22:09 -07:00
Greg Magolan 506f478f08 build(bazel): fix deps of test (#29799)
PR Close #29799
2019-04-17 13:02:03 -07:00
Paul Gschwendtner b0c1282fbe refactor(core): migrations do not properly handle multiple templates in source file (#29841)
Currently if there are multiple source files within a given
TypeScript source file, only the last template in the source
file is checked as we store templates in a `Map` with the
source file paths as keys.

This is problematic as multiple templates can live within the
same source file and we therefore accidentally overwrite
existing entries in the resolved templates map.

PR Close #29841
2019-04-15 11:13:39 -07:00
Paul Gschwendtner 446e3573e3 refactor(core): add static-query template strategy (#29815)
Introduces a new strategy for the `static-query` schematic that
is enabled by default. In order to provide a migration that works
for the most Angular applications and makes the upgrade as easy
as possible, the template strategy leverages the view engine
Angular compiler logic in order to determine the query timing
that is currently used within applications using view engine.

PR Close #29815
2019-04-15 10:53:54 -07:00
Paul Gschwendtner 205a45e9a8 refactor(core): move usage detection into usage strategy (#29815)
In order to support multiple strategies for detecting the query timing, the
query usage logic has been moved into a query usage strategy.

PR Close #29815
2019-04-15 10:53:53 -07:00
Igor Minar 54058ba3a7 fix(core): resolve ts compile issues due to lenient tsconfig (#29843)
The code failed presubmit in google3 because the original ts config was not as strict
as the one used elsewhere in angular/angular and google3.

PR Close #29843
2019-04-11 11:04:07 -07:00
Paul Gschwendtner 5b32f55a3a refactor(core): static-query schematic should check templates (#29713)
Queries can technically be also accessed within component templates
e.g.

```html
<my-comp [binding]="myQuery"></my-comp>
```

In that case the query with the property "myQuery" is accessed
statically and needs to be marked with `static: true`. There are
other edge cases that need to be handled as the template property
read doesn't necessarily resolve to the actual query property.

For example:

```html
<foo #myQuery></foo>
<my-comp [binding]="myQuery"></my-comp>
```

In this scenario the binding doesn't refer to the actual query
because the template reference variable takes precedence. The
query doesn't need to be marked with "static: true" this time.

This commit ensures that the `static-query` migration schematic
now handles this cases properly. Also template property reads
that access queries from within a `<ng-template>` are ignored
as these can't access the query before the view has been initialized.

Resolves FW-1216

PR Close #29713
2019-04-11 08:22:44 -07:00
Paul Gschwendtner b507d076be refactor(core): move schematic component template visitor to utils (#29713)
PR Close #29713
2019-04-11 08:22:44 -07:00
Bowen Ni faf8fdde14 refactor(core): Fix "explicit-query-timing" failure span. (#29792)
PR Close #29792
2019-04-11 07:40:10 -07:00
Paul Gschwendtner 39bfd1a11f refactor(core): run migration schematics for v8 beta and rc releases (#29735)
Currently the `static-query` and `template-var-assignment` schematic only runs
for `8.0.0` which does not include any betas or release candidates. We want to
run the schematic in the beta's and RC in order to get early feedback about the
schematics. Enabling it promptly with V8 stable release can result in accidental
breakages that we would like to fix/identify before.

PR Close #29735
2019-04-10 12:15:25 -07:00
Paul Gschwendtner 4e8c2c3422 refactor(core): static-query schematic should handle abstract classes (#29688)
Queries can not only be accessed within derived classes, but also in
the super class through abstract methods. e.g.

```
abstract class BaseClass {

  abstract getEmbeddedForm(): NgForm {}

  ngOnInit() {
     this.getEmbeddedForm().doSomething();
  }
}

class Subclass extends BaseClass {
  @ViewChild(NgForm) form: NgForm;

  getEmbeddedForm() { return this.form; }

}
```

Same applies for abstract properties which are implemented in the base class
through accessors. This case is also now handled by the schematic.

Resolves FW-1213

PR Close #29688
2019-04-10 12:15:05 -07:00
Paul Gschwendtner 1102b02406 refactor(core): static-query schematic should handle function callbacks (#29663)
Currently the static-query schematic is not able to properly handle
call expressions that pass function declarations that access a given
query. e.g.

```ts
ngOnInit() {
  this._callFunction(() => this.myQuery.doSomething());
}

_callFunction(cb: any) { cb(); }
```

In that case the passed function is executed synchronously in
the "ngOnInit" lifecycle and therefore the query needs to be
detected as "static".

We can fix this by keeping track of the current function context
and using it to resolve identifiers to the passed arguments.

PR Close #29663
2019-04-08 17:21:24 -07:00
Paul Gschwendtner 00bf636afa refactor(core): static-query schematic should handle binary expressions (#29663)
Currently we only check getters for property access expressions. This is wrong
because property access expressions do not always cause the "getter" to be
triggered. e.g.

```ts
set a() {...}
get a() {...}

ngOnInit() {
  this.a = true;
}
```

In that case the schematic currently incorrectly checks the "getter", while this is a binary
expression and the property access is used as left-side of the binary expression. In that
case we need to check the setter declaration of the property and not the "getter". In order
to fix this, we need to also check `ts.BinaryExpression` nodes and check getters/setters
based on the used operator token. There are three types of binary expressions:

1) Value assignment (using `=`). In that case only the setter is triggered.
2) Compound assignment (e.g. using `+=`). In that case `getter` and `setter` are triggered.
3) Comparison (e.g. using `===`). In that case only the getter is triggered.

PR Close #29663
2019-04-08 17:21:24 -07:00
Paul Gschwendtner 6d35c5094a test(core): add test for template variable object property assignment (#29708)
The `template-var-assignment` schematic currently complains if someone
assigns a value to a template variable. This will no longer work with Ivy, but
it should be totally fine to update a property of the template variable if it refers
to an object. This commit adds a test that ensures that we don't incorrectly report
any failure for such property writes in bound events.

PR Close #29708
2019-04-08 09:46:57 -07:00
Paul Gschwendtner 4a2fb86b1e refactor(core): polish failure messages for template-var-assignment schematic (#29708)
Improves the failure messages for the `template-var-assignment` schematic. After manual
testing of the schematic it's not quite clear for developers what the failure message means
without any context. The schematic now also references a short markdown file mentioning
what needs to be changed, but eventually this document needs to be expanded with more
information and context of the reasoning behind this change within Ivy.

PR Close #29708
2019-04-08 09:46:57 -07:00
Filipe Silva 96b76dc3f1 fix(core): add missing migration to npm package (#29705)
While running `ng update @angular/core --next`, the following error would be displayed:

```
Cannot find module '....\node_modules\@angular\core\schematics\migrations\template-var-assignment\index'
```

This happened because the Schematics migration was referenced, but not included.

This commit fixes that bug by including the migration in the Bazel npm package dependencies.

PR Close #29705
2019-04-04 10:51:19 -07:00
Paul Gschwendtner 7c8f4e3202 feat(core): template-var-assignment update schematic (#29608)
Introduces a new update schematic called "template-var-assignment"
that is responsible for analyzing template files in order to warn
developers if template variables are assigned to values.

The schematic also comes with a driver for `tslint` so that the
check can be used wtihin Google.

PR Close #29608
2019-04-02 15:47:32 -07:00
Paul Gschwendtner 15eb1e0ce1 refactor(core): stronger type for resolved angular decorators (#29608)
PR Close #29608
2019-04-02 15:47:32 -07:00
Paul Gschwendtner 780081def0 refactor(core): move schematic typescript logic to utility package (#29608)
PR Close #29608
2019-04-02 15:47:32 -07:00
Paul Gschwendtner 33016b8929 fix(core): static-query schematic should detect static queries in getters. (#29609)
Queries can also be statically accessed within getters. e.g.

```ts
ngOnInit() {
  this.myQueryGetter.doSomething();
}
```

In that case we need to check if the `myQueryGetter` definition accesses
a query statically. As we need to use the type checker for every property acess
within lifecylce hooks, the schematic might become slower than before, but considering
that this is a one-time execution, it is totally fine using the type-checker extensively.

PR Close #29609
2019-04-01 10:58:51 -07:00
Paul Gschwendtner 09fab58109 fix(core): static-query schematic should detect queries in "ngDoCheck" and "ngOnChanges" (#29492)
Queries can be also used statically within the "ngDoCheck" and "ngOnChanges" lifecylce hook.
In order to properly detect all queries, we need to also respect these lifecycle hooks.

Resolves FW-1192

PR Close #29492
2019-03-25 09:21:35 -07:00
Paul Gschwendtner 4742385e95 refactor(core): fix misleading tslint schematic message (#29320)
Fixes the incorrect failure message or the TSLint rule that
is used within Google. The TSLint rule is not part of the
public schematic code.

Additionally in order to make it easier to understand what
action the developer needs to take, we rather print out the
expected "static: true/false" statement instead of saying that
a query needs to be static or dynamic. Dynamic is ambiguous, as
there is no `dynamic: true` option.

PR Close #29320
2019-03-18 17:37:45 -04:00
Paul Gschwendtner 90df7de54d refactor(core): better failure message for explicit-query timing tslint rule (#29258)
Improves the failure message for the `explicit-query` timing TSLint rule
that is used within Google. Currently it's not very clear what action
developers need to take in order to resolve the lint failure manually.

PR Close #29258
2019-03-14 16:02:37 -04:00
Paul Gschwendtner 8ef46f38f4 refactor(core): add tslint rule entry-point for static-query migration (#29258)
In order to be able to use the static-query migration logic within
Google, we need to provide a TSLint rule entry-point that wires up
the schematic logic and provides reporting and automatic fixes.

PR Close #29258
2019-03-14 16:02:37 -04:00
Paul Gschwendtner c5daaa91cf refactor(core): static-query schematic should not run multiple times (#29133)
With 6215799, we introduced a schematic for the new static-query timing.
Currently when someone runs the update schematic manually within his
CLI project (the schematic does not run automatically yet), he might have
noticed that the migration is executed for the same `tsconfig` file multiple
times. This can happen because the `getProjectTsConfigPaths` function
can incorrectly return the same tsconfig multiple times. The paths are not
properly deduped as we don't normalize the determined project tsconfig paths

PR Close #29133
2019-03-12 12:28:14 -07:00
Paul Gschwendtner 360730ce59 refactor(core): static-query migration does not detect external call expressions. (#29133)
Currently the static-query migration does not properly handle functions which
are declared externally. This is because we don't resolve the symbol of the
call-expression through its type. Currently we just determine the symbol of the
call-expression through the given call expression node, which doesn't necessarily
refer to the *value declaration* of the call expression. e.g. the symbol refers to the
import declaration which imports the external function. This means that we currently
can't check the external function as we couldn't find the actual value declaration.
We can fix this by resolving the type of the call expression and using the type in order
to retrieve the symbol containing the *value declaration*

PR Close #29133
2019-03-12 12:28:14 -07:00
Paul Gschwendtner fca1724ebf refactor(core): static-query schematic incorrectly handles multiple tsconfigs (#29133)
Currently when the static-query runs for a project with multiple TypeScript
configuration files (e.g. a usual CLI project), the migration incorrectly
applies the code transformation multiple times. This is because the migration
is currently based on the source file contents in the file system, while the
actual source file contents could have already changed in the devkit schematic
tree.

PR Close #29133
2019-03-12 12:28:14 -07:00
Paul Gschwendtner 3c53713616 refactor(core): static query schematic should handle asynchronous query usages properly (#29133)
With 6215799055, we introduced a schematic
for the Angular core package that automatically migrates unexplicit
query definitions to the explicit query timing (static <-> dynamic).

As the initial foundation was already big enough, it was planned
to come up with a follow-up that handles asynchronous query
usages properly. e.g. queries could be used in Promises,
`setTimeout`, `setInterval`, `requestAnimationFrame` and more, but
the schematic would incorrectly declare these queries as static.

This commit ensures that we properly handle these micro/macro
tasks and don't incorrectly consider queries as static.

The declaration usage visitor should only check the synchronous
control flow and completely ignore any statements within function
like expressions which aren't explicitly executed in a synchronous
way. e.g. IIFE's still work as the function expression is
synchronously invoked.

PR Close #29133
2019-03-12 12:28:14 -07:00
Paul Gschwendtner 6215799055 feat(core): update schematic to migrate to explicit query timing (#28983)
Introduces an update schematic for the "@angular/core" package
that automatically migrates pre-V8 "ViewChild" and "ContentChild"
queries to the new explicit timing syntax. This is not required
yet, but with Ivy, queries will be "dynamic" by default. Therefore
specifying an explicit query timing ensures that developers can
smoothly migrate to Ivy (once it's the default).

Read more about the explicit timing API here:
https://github.com/angular/angular/pull/28810

PR Close #28983
2019-03-05 14:21:40 -08:00