@@ -289,18 +289,20 @@ export class SymbolBuilder {
289
289
NgOriginalFile
290
290
] ;
291
291
292
- // This is a preliminary check ahead of a more expensive search
293
- const hasPotentialCandidate = directives . find (
294
- ( m ) => m . ref . node . name . text === directiveDeclaration . name ?. text ,
295
- ) ;
296
-
297
- if ( originalFile && hasPotentialCandidate ) {
298
- // In case the TCB has been inlined because of a non exported declaration
299
- // We will instead find a matching class
300
- // And if found one, look for it in the directives array
301
- const classWithSameName = findMatchingDirective ( originalFile , directiveDeclaration ) ;
302
- if ( classWithSameName ) {
303
- return directives . find ( ( m ) => m . ref . node === classWithSameName ) ?? null ;
292
+ if ( originalFile !== undefined ) {
293
+ // This is a preliminary check ahead of a more expensive search
294
+ const hasPotentialCandidate = directives . find (
295
+ ( m ) => m . ref . node . name . text === directiveDeclaration . name ?. text ,
296
+ ) ;
297
+
298
+ if ( hasPotentialCandidate ) {
299
+ // In case the TCB has been inlined,
300
+ // We will look for a matching class
301
+ // If we find one, we look for it in the directives array
302
+ const classWithSameName = findMatchingDirective ( originalFile , directiveDeclaration ) ;
303
+ if ( classWithSameName !== null ) {
304
+ return directives . find ( ( m ) => m . ref . node === classWithSameName ) ?? null ;
305
+ }
304
306
}
305
307
}
306
308
@@ -889,28 +891,47 @@ function unwrapSignalInputWriteTAccessor(expr: ts.LeftHandSideExpression): null
889
891
} ;
890
892
}
891
893
894
+ /**
895
+ * Looks for a class declaration in the original source file that matches a given directive
896
+ * from the type check source file.
897
+ *
898
+ * @param originalSourceFile The original source where the runtime code resides
899
+ * @param directiveDeclarationInTypeCheckSourceFile The directive from the type check source file
900
+ */
892
901
function findMatchingDirective (
893
- sourceFile : ts . SourceFile ,
894
- directiveDeclaration : ts . ClassDeclaration ,
895
- ) {
896
- // Because of https://github.com/microsoft/typescript/issues/9998 we need to trick the compiler
897
- let classWithSameName : ts . ClassDeclaration = null ! ;
902
+ originalSourceFile : ts . SourceFile ,
903
+ directiveDeclarationInTypeCheckSourceFile : ts . ClassDeclaration ,
904
+ ) : ts . ClassDeclaration | null {
905
+ let sameDeclarationInOriginalFile : ts . ClassDeclaration | null = null ;
906
+
907
+ const typecheckDirectiveDeclarationDepth = getDeclarationDepth (
908
+ directiveDeclarationInTypeCheckSourceFile ,
909
+ ) ;
910
+
911
+ const className = directiveDeclarationInTypeCheckSourceFile . name ?. text ?? '' ;
912
+ // We build an index of the class declarations with the same name
913
+ // To then compare the indexes to confirm we found the right class declaration
914
+ const ogClasses = collectClassesWithName ( originalSourceFile , className ) ;
915
+ const typcheckClasses = collectClassesWithName (
916
+ directiveDeclarationInTypeCheckSourceFile . getSourceFile ( ) ,
917
+ className ,
918
+ ) ;
898
919
899
920
function visit ( node : ts . Node ) : void {
900
921
if (
901
922
ts . isClassDeclaration ( node ) &&
902
- node . name ?. text === directiveDeclaration . name ?. text &&
903
- getDeclarationDepth ( node ) === getDeclarationDepth ( directiveDeclaration ) &&
904
- node . getText ( ) === directiveDeclaration . getText ( ) // compares text content
923
+ node . name ?. text === directiveDeclarationInTypeCheckSourceFile . name ?. text &&
924
+ getDeclarationDepth ( node ) === typecheckDirectiveDeclarationDepth &&
925
+ ogClasses . indexOf ( node ) === typcheckClasses . indexOf ( directiveDeclarationInTypeCheckSourceFile )
905
926
) {
906
- classWithSameName = node ;
927
+ sameDeclarationInOriginalFile = node ;
907
928
return ;
908
929
}
909
930
ts . forEachChild ( node , visit ) ;
910
931
}
911
- ts . forEachChild ( sourceFile , visit ) ;
932
+ ts . forEachChild ( originalSourceFile , visit ) ;
912
933
913
- return classWithSameName ;
934
+ return sameDeclarationInOriginalFile ;
914
935
}
915
936
916
937
function getDeclarationDepth ( decl : ts . Declaration ) : number {
@@ -924,3 +945,25 @@ function getDeclarationDepth(decl: ts.Declaration): number {
924
945
925
946
return depth ;
926
947
}
948
+
949
+ /**
950
+ * Builds a list of class declarations of a given name
951
+ * Is used as a index based reference to compare class declarations
952
+ * between the typecheck source file and the original source file
953
+ */
954
+ function collectClassesWithName (
955
+ sourceFile : ts . SourceFile ,
956
+ className : string ,
957
+ ) : ts . ClassDeclaration [ ] {
958
+ const classes : ts . ClassDeclaration [ ] = [ ] ;
959
+ function visit ( node : ts . Node ) {
960
+ if ( ts . isClassDeclaration ( node ) && node . name ?. text === className ) {
961
+ classes . push ( node ) ;
962
+ } else {
963
+ ts . forEachChild ( node , visit ) ;
964
+ }
965
+ }
966
+ sourceFile . forEachChild ( visit ) ;
967
+
968
+ return classes ;
969
+ }
0 commit comments