diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/util.ts b/packages/compiler-cli/src/ngtsc/annotations/src/util.ts index 4d52eb6b80..073fa02897 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/util.ts @@ -516,7 +516,13 @@ export function resolveProvidersRequiringFactory( } } - if (tokenClass !== null && reflector.isClass(tokenClass.node)) { + // TODO(alxhub): there was a bug where `getConstructorParameters` would return `null` for a + // class in a .d.ts file, always, even if the class had a constructor. This was fixed for + // `getConstructorParameters`, but that fix causes more classes to be recognized here as needing + // provider checks, which is a breaking change in g3. Avoid this breakage for now by skipping + // classes from .d.ts files here directly, until g3 can be cleaned up. + if (tokenClass !== null && !tokenClass.node.getSourceFile().isDeclarationFile && + reflector.isClass(tokenClass.node)) { const constructorParameters = reflector.getConstructorParameters(tokenClass.node); // Note that we only want to capture providers with a non-trivial constructor, diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 377558555e..b613f5ee9b 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -7493,16 +7493,20 @@ export const Foo = Foo__PRE_R3__; expect(diags.length).toBe(0); }); - it('should error when an undecorated class with a non-trivial constructor in a declaration file is provided via useClass', - () => { - env.write('node_modules/@angular/core/testing/index.d.ts', ` + // TODO(alxhub): this test never worked correctly, as it used to declare a constructor with a + // body, which real declaration files don't have. Without the body, the ReflectionHost used to + // not return any constructor data, preventing an error from showing. That bug was fixed, but + // the error for declaration files is disabled until g3 can be updated. + xit('should error when an undecorated class with a non-trivial constructor in a declaration file is provided via useClass', + () => { + env.write('node_modules/@angular/core/testing/index.d.ts', ` export declare class NgZone {} export declare class Testability { - constructor(ngZone: NgZone) {} + constructor(ngZone: NgZone); } `); - env.write('test.ts', ` + env.write('test.ts', ` import {NgModule, Injectable} from '@angular/core'; import {Testability} from '@angular/core/testing'; @@ -7515,10 +7519,10 @@ export const Foo = Foo__PRE_R3__; export class SomeModule {} `); - const diags = env.driveDiagnostics(); - expect(diags.length).toBe(1); - expect(diags[0].messageText).toContain('cannot be created via dependency injection'); - }); + const diags = env.driveDiagnostics(); + expect(diags.length).toBe(1); + expect(diags[0].messageText).toContain('cannot be created via dependency injection'); + }); it('should not error when an class with a factory definition and a non-trivial constructor in a declaration file is provided via useClass', () => { @@ -7529,7 +7533,7 @@ export const Foo = Foo__PRE_R3__; export declare class Testability { static ɵfac: i0.ɵɵFactoryDef; - constructor(ngZone: NgZone) {} + constructor(ngZone: NgZone); } `); env.write('test.ts', `