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)