Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(compiler-cli): accept inheriting the constructor from a class in … #48156

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -14,7 +14,7 @@ import {DirectiveMeta, flattenInheritedDirectiveMetadata, HostDirectiveMeta, Met
import {describeResolvedType, DynamicValue, PartialEvaluator, ResolvedValue, traceDynamicValue} from '../../../partial_evaluator';
import {ClassDeclaration, ReflectionHost} from '../../../reflection';
import {DeclarationData, LocalModuleScopeRegistry} from '../../../scope';
import {identifierOfNode} from '../../../util/src/typescript';
import {identifierOfNode, isFromDtsFile} from '../../../util/src/typescript';

import {InjectableClassRegistry} from './injectable_registry';
import {isAbstractClassDeclaration, readBaseClass} from './util';
Expand Down Expand Up @@ -256,6 +256,14 @@ export function checkInheritanceOfInjectable(
return getInheritedUndecoratedCtorDiagnostic(node, classWithCtor.ref, kind);
}

if (isFromDtsFile(classWithCtor.ref.node)) {
// The inherited class is declared in a declaration file, in which case there is not enough
// information to detect invalid constructors as `@Inject()` metadata is not present in the
// declaration file. Consequently, we have to accept such occurrences, although they might
// still fail at runtime.
return null;
}

if (!strictInjectionParameters || isAbstractClassDeclaration(node)) {
// An invalid constructor is only reported as error under `strictInjectionParameters` and
// only for concrete classes; follow the same exclusions for derived types.
Expand Down
31 changes: 31 additions & 0 deletions packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
Expand Up @@ -2960,6 +2960,37 @@ function allTests(os: string) {
`or add an explicit constructor to ConcreteDirWithoutCtor.`);
expect(getDiagnosticSourceCode(diags[2])).toBe('ConcreteDirWithoutCtor');
});

// https://github.com/angular/angular/issues/48152
it('should not give a compile-time error when a class inherits from foreign compilation unit',
() => {
env.tsconfig({strictInjectionParameters: true});
env.write('node_modules/external/index.d.ts', `
import * as i0 from '@angular/core';

export abstract class ExternalClass {
static ɵprov: i0.ɵɵInjectableDeclaration<ExternalClass>;
static ɵfac: i0.ɵɵFactoryDeclaration<ExternalClass, never>

constructor(invalid: string) {}
}
`);
env.write('test.ts', `
import {Directive} from '@angular/core';
import {ExternalClass} from 'external';

@Directive()
export abstract class AbstractMiddleDir extends ExternalClass {}

@Directive()
export class ConcreteMiddleDir extends AbstractMiddleDir {}

@Directive()
export class ConcreteDirWithoutCtor extends ConcreteMiddleDir {}
`);

env.driveMain();
});
});

describe('with strictInjectionParameters = false', () => {
Expand Down