refactor: enable ng update migrations for v10 (#36921)

Enables the `ng update` migrations for v10. Status for individual
migrations:

**undecorated-classes-with-di**.

This migration dealt exlusively with inherited constructors and
cases where a derived component was undecorated. In those cases,
the migration added `@Directive()` or copied the inherited decorator
to the derived class.

We don't need to run this migration again because ngtsc throws if
constructor is inherited from an undecorated class. Also ngtsc will
throw if a NgModule references an undecorated class in the declarations.

***undecorated-classes-with-decorated-fields***

This migration exclusively deals with undecorated classes that use
Angular features but are not decorated. Angular features include
the use of lifecycle hooks or class fields with Angular decorators,
such as `@Input()`.

We want to re-run this migration in v10 as we will disable the
compatibility code in ngtsc that detects such undecorated classes
as `@Directive`.

**module-with-providers**:

This migration adds an explicit generic type to `ModuleWithProviders`.
As of v10, the generic type is required, so we need to re-run the
migration again.

**renderer-to-renderer2**:

We don't need to re-run that migration again as the
renderer has been already removed in v9.

**missing-injectable**:

This migration is exclusively concerned with undecorated
providers referenced in an `NgModule`. We should re-run
that migration again as we don't have proper backsliding
prevention for this yet. We can consider adding an error
in ngtsc for v10, or v11. In either way, we should re-run
the migration.

**dynamic-queries**:

We ran this one in v9 to reduce code complexity in projects. Instead
of explicitly passing `static: false`, not passing any object literal
has the same semantics. We don't need to re-run the migration again
since there is no good way to prevent backsliding and we cannot always
run this migration for future versions (as some apps might actually
intentionally use the explicit `static: false` option).

PR Close #36921
This commit is contained in:
Paul Gschwendtner
2020-05-04 21:58:42 +02:00
committed by Alex Rickabaugh
parent 4c92cf43cf
commit 0577bf0e3e
13 changed files with 54 additions and 206 deletions

View File

@ -1,4 +1,4 @@
import {Component, Directive, NgModule, NgZone} from '@angular/core';
import {Component, Directive, NgModule, NgZone, Injectable} from '@angular/core';
export class ComponentTypeProvider {}
export class ComponentDontNeedCase {}
@ -28,8 +28,7 @@ export class ProvidersTestDirective {}
export class TypeCase {}
// undecorated-classes-with-di migration will add "@Injectable" here
// because the constructor is inherited in "ProvideCase".
@Injectable()
class BaseProviderCase {
constructor(zone: NgZone) {}
}

View File

@ -1,4 +1,4 @@
import { Component, Directive, NgModule, NgZone, Injectable } from '@angular/core';
import {Component, Directive, NgModule, NgZone, Injectable} from '@angular/core';
@Injectable()
export class ComponentTypeProvider {}
@ -34,8 +34,6 @@ export class ProvidersTestDirective {}
@Injectable()
export class TypeCase {}
// undecorated-classes-with-di migration will add "@Injectable" here
// because the constructor is inherited in "ProvideCase".
@Injectable()
class BaseProviderCase {
constructor(zone: NgZone) {}

View File

@ -1,42 +0,0 @@
import {Directive, NgModule, NgZone} from '@angular/core';
export class BaseClass1 {
constructor(zone: NgZone) {}
}
@Directive({selector: 'sel'})
export class DirectiveWithInheritedCtor extends BaseClass1 {}
export class BaseClass2 {
constructor(zone: NgZone) {}
}
@Directive({selector: 'sel'})
export class DirectiveWithExplicitCtor extends BaseClass2 {
constructor(zone: NgZone) {
super(zone);
}
}
export class BaseClassWithoutCtor {}
@Directive({selector: 'sel'})
export class DirectiveWithoutInheritedCtor extends BaseClassWithoutCtor {}
export class BaseClass3 {
constructor(zone: NgZone) {}
}
export class PassThroughClass extends BaseClass3 {}
@Directive({selector: 'sel'})
export class DirectiveWithInheritedCtorAndClassesInBetween extends PassThroughClass {}
@NgModule({
declarations: [
DirectiveWithInheritedCtor,
DirectiveWithoutInheritedCtor,
DirectiveWithExplicitCtor,
DirectiveWithInheritedCtorAndClassesInBetween,
]
})
export class TestModule {}

View File

@ -1,45 +0,0 @@
import {Directive, NgModule, NgZone} from '@angular/core';
@Directive()
export class BaseClass1 {
constructor(zone: NgZone) {}
}
@Directive({selector: 'sel'})
export class DirectiveWithInheritedCtor extends BaseClass1 {}
export class BaseClass2 {
constructor(zone: NgZone) {}
}
@Directive({selector: 'sel'})
export class DirectiveWithExplicitCtor extends BaseClass2 {
constructor(zone: NgZone) {
super(zone);
}
}
export class BaseClassWithoutCtor {}
@Directive({selector: 'sel'})
export class DirectiveWithoutInheritedCtor extends BaseClassWithoutCtor {}
@Directive()
export class BaseClass3 {
constructor(zone: NgZone) {}
}
@Directive()
export class PassThroughClass extends BaseClass3 {}
@Directive({selector: 'sel'})
export class DirectiveWithInheritedCtorAndClassesInBetween extends PassThroughClass {}
@NgModule({
declarations: [
DirectiveWithInheritedCtor,
DirectiveWithoutInheritedCtor,
DirectiveWithExplicitCtor,
DirectiveWithInheritedCtorAndClassesInBetween,
]
})
export class TestModule {}

View File

@ -49,6 +49,10 @@ export class MyCompBase extends MyCompSuperBase {}
})
export class MyComp extends MyCompBase {}
@Component({
selector: 'my-comp',
template: '',
})
export class WrappedMyComp extends MyComp {}
@NgModule({declarations: [MyComp, WrappedMyComp]})
@ -60,3 +64,15 @@ export class AbstractDir {}
export class DerivedAbstractDir extends AbstractDir {}
export class WrappedDerivedAbstractDir extends DerivedAbstractDir {}
export class UndecoratedService {
ngOnDestroy() {}
}
export class UndecoratedPipeBase {
ngOnDestroy() {}
}
export class WithDirectiveLifecycleHook {
ngOnInit() {}
}

View File

@ -56,8 +56,8 @@ export class MyCompBase extends MyCompSuperBase {}
export class MyComp extends MyCompBase {}
@Component({
selector: 'my-comp',
template: '',
selector: 'my-comp',
template: '',
})
export class WrappedMyComp extends MyComp {}
@ -72,3 +72,18 @@ export class DerivedAbstractDir extends AbstractDir {}
@Directive()
export class WrappedDerivedAbstractDir extends DerivedAbstractDir {}
// TODO: Add Angular decorator.
export class UndecoratedService {
ngOnDestroy() {}
}
// TODO: Add Angular decorator.
export class UndecoratedPipeBase {
ngOnDestroy() {}
}
@Directive()
export class WithDirectiveLifecycleHook {
ngOnInit() {}
}

View File

@ -1,31 +0,0 @@
import {Directive, NgModule, NgZone} from '@angular/core';
import {CheckboxControlValueAccessor} from '@angular/forms';
import {BaseComponentFromOtherFile} from './base-component';
@Directive({
selector: 'my-base-dir',
providers: [{provide: NgZone, useValue: null}]
})
export class BaseDirective {}
export class DerivedDirective extends BaseDirective {}
export class DerivedDirectiveFromNodeModules extends CheckboxControlValueAccessor {}
export class DerivedComponentFromOtherSourceFile extends BaseComponentFromOtherFile {}
@NgModule({
declarations: [
DerivedDirective,
DerivedDirectiveFromNodeModules,
DerivedComponentFromOtherSourceFile,
],
})
export class TestModule {}
@NgModule({
declarations: [BaseDirective],
})
export class BaseClassesModule {}

View File

@ -1,62 +0,0 @@
import { Directive, NgModule, NgZone, Component } from '@angular/core';
import { CheckboxControlValueAccessor, NG_VALUE_ACCESSOR, NG_ASYNC_VALIDATORS } from '@angular/forms';
import { BaseComponentFromOtherFile, hostBindings } from './base-component';
@Directive({
selector: 'my-base-dir',
providers: [{provide: NgZone, useValue: null}]
})
export class BaseDirective {}
@Directive({
selector: 'my-base-dir',
providers: [{ provide: NgZone, useValue: null }]
})
export class DerivedDirective extends BaseDirective {}
@Directive({
selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]",
host: {
"(change)": "onChange($event.target.checked)",
"(blur)": "onTouched()"
},
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: CheckboxControlValueAccessor,
multi: true
}]
})
export class DerivedDirectiveFromNodeModules extends CheckboxControlValueAccessor {}
@Component({
selector: 'base-comp',
template: `
<span>This is the template.</span>
`,
host: hostBindings,
providers: [
{ provide: NG_ASYNC_VALIDATORS, useValue: null },
],
// The following fields were copied from the base class,
// but could not be updated automatically to work in the
// new file location. Please add any required imports for
// the properties below:
styleUrls: nonExportedStyleUrlsVar
})
export class DerivedComponentFromOtherSourceFile extends BaseComponentFromOtherFile {}
@NgModule({
declarations: [
DerivedDirective,
DerivedDirectiveFromNodeModules,
DerivedComponentFromOtherSourceFile,
],
})
export class TestModule {}
@NgModule({
declarations: [BaseDirective],
})
export class BaseClassesModule {}