@@ -26,7 +26,7 @@ const signatureErrorDiagnostics = [
2626] ;
2727
2828/** List of classes of which the constructor signature has changed. */
29- const signatureChangedClasses = getAllChanges ( constructorChecks ) ;
29+ const signatureChangeData = getAllChanges ( constructorChecks ) ;
3030
3131/**
3232 * Rule that visits every TypeScript new expression or super call and checks if the parameter
@@ -64,9 +64,19 @@ function visitSourceFile(context: WalkContext<null>, program: ts.Program) {
6464 const className = classType . symbol && classType . symbol . name ;
6565 const isNewExpression = ts . isNewExpression ( node ) ;
6666
67- // TODO(devversion): Consider handling pass-through classes better.
68- // TODO(devversion): e.g. `export class CustomCalendar extends MatCalendar {}`
69- if ( ! signatureChangedClasses . includes ( className ) ) {
67+ // Determine the class names of the actual construct signatures because we cannot assume
68+ // that the diagnostic refers to a constructor of the actual expression. In case the constructor
69+ // is inherited, we need to detect that the owner-class of the constructor is added to the
70+ // constructor checks upgrade data. e.g. `class CustomCalendar extends MatCalendar {}`.
71+ const signatureClassNames = classType . getConstructSignatures ( )
72+ . map ( signature => getClassDeclarationOfSignature ( signature ) )
73+ . map ( declaration => declaration && declaration . name ? declaration . name . text : null )
74+ . filter ( Boolean ) ;
75+
76+ // Besides checking the signature class names, we need to check the actual class name because
77+ // there can be classes without an explicit constructor.
78+ if ( ! signatureChangeData . includes ( className ) &&
79+ ! signatureClassNames . some ( name => signatureChangeData . includes ( name ! ) ) ) {
7080 continue ;
7181 }
7282
@@ -120,3 +130,22 @@ function findConstructorNode(diagnostic: ts.Diagnostic, sourceFile: ts.SourceFil
120130
121131 return resolvedNode ;
122132}
133+
134+ /** Determines the class declaration of the specified construct signature. */
135+ function getClassDeclarationOfSignature ( signature : ts . Signature ) : ts . ClassDeclaration | null {
136+ let node : ts . Node = signature . getDeclaration ( ) ;
137+
138+ // Handle signatures which don't have an actual declaration. This happens if a class
139+ // does not have an explicitly written constructor.
140+ if ( ! node ) {
141+ return null ;
142+ }
143+
144+ while ( ! ts . isSourceFile ( node = node . parent ) ) {
145+ if ( ts . isClassDeclaration ( node ) ) {
146+ return node ;
147+ }
148+ }
149+
150+ return null ;
151+ }
0 commit comments