Static-query migration strategies
===
There are two ways of how we can migrate existing Angular applications to
the new `ViewChild` and `ContentChild` static timing syntax. Either by:
1) Looking at the current usage of the query
2) Inspecting what the query selects in the component template
Both approaches have benefits and downsides which are summarized here:
**Approach 1 (query usage)**
Positives:
* Best practices as we don't mark queries as static if they don't need to be (e.g. for Ivy)
* Can detect `ContentChild` query timing if used statically (for most cases: see negatives)
Negatives:
* Limited coverage of application. e.g. queries could be accessed in other parts
of the project. e.g. through dependency injection.
* These cases can be handled technically but there a lot of edge-cases that
need to be handled and this degenerates into a runtime Angular application
simulator eventually (e.g. template component scope, virtual injector tree)
* e.g. Testing code accessed the query before running `fixture.detectChanges`
* Lots of code needed for detection of query usage through TypeScript AST and type checking.
**Approach 2 (template selection)**
Positives:
* Guaranteed to determine *working* timing for `ViewQuery` due to the template analysis.
* Easy to implement. Less code needed as template AST can be visited and used to determine
query timing
Negatives:
* Difficult to determine query timing for `ContentChild` since projected content can
be inserted from anywhere:
* This could technically be handled, but in order to handle that we need to analyze
*all* other components that project content into the given component. This is nearly
impossible as other Angular projects, which are not statically analyzable, can also
project content into the component. Therefore the prediction is never 100% correct.
* The Angular compiler can only time the content queries properly at runtime when the
projected content and the component hierarchy is already known.
* Due to queries marked too aggressively, it makes the template inflexible to future changes.
---
### Usage strategy
We analyze the query _usage_ and check if we find a `static` query usage. If we
**definitely** found a static query usage, we mark the query as static.
If we are unsure about it being static (e.g. through a third-party callback function), the
query timing is ambiguous and we mark it as static with a `TODO` that requires the developer
to double-check if the query could _technically_ be marked as dynamic (e.g. for simpler
Ivy migration in the future)
If we didn't find any static query usage, the query is still **not definitely** dynamic, as
the query could be still referenced somewhere else (e.g. dependency injection). In that
case the query timing is *dynamic* and we just add an inline todo asking the developer to
double-check if the query is used somewhere statically.
### Template selection strategy
For `ViewChild` queries, we analyze the template and use the view engine sorting in order
to provide a **guaranteed working** migration for that view query.
For `ContentChild` queries, we can never determine a working/correct query timing with this
strategy and can just leave the decision up to the developer by adding an inline `TODO`.
**Implementation requirements**:
* Need to handle queries that select component/directives instead of template references.
* Requires us to determine selectors of specified component/directives identifiers.
* Requires us to work with third-party modules through metadata files.
### Mixed strategy
For `ViewChild` queries, we use the template selection strategy in order to get a 100% working
migration for these queries.
For `ContentChild` queries, we check if the query is statically used. If not, we fallback to the
template selection strategy and just add an inline todo and leave the decision up to the
developer. This allows us to correctly handle the migration for `ContentChild` in some cases as
well. Meaning that this strategy has:
* 100% validity and 100% migration-rate for view queries
* 100% validity and ~25% migration-rate for content queries
:::info
The **`25%`** are determined by estimating that `50%` content queries are statically
used in an application and that the query usage detection has a `50%` migration-rate.
(as it cannot always detect query usage due to various edge-cases)
:::
---
**General todo's**
* Consider adding another `ambigious` case to the usage strategy [see @kara's comment](https://github.com/angular/angular/pull/29663#discussion_r272755654)