@@ -424,6 +424,28 @@ export class FileIndexer {
424424 }
425425 return relationships
426426 }
427+
428+ private prototypeAssignmentOwner ( node : ts . Node ) : ts . Declaration | undefined {
429+ if ( ! ts . isObjectLiteralExpression ( node ) ) {
430+ return
431+ }
432+ const assignment = node . parent
433+ if (
434+ ! ts . isBinaryExpression ( assignment ) ||
435+ assignment . operatorToken . kind !== ts . SyntaxKind . EqualsToken ||
436+ assignment . right !== node ||
437+ ! ts . isPropertyAccessExpression ( assignment . left ) ||
438+ assignment . left . name . text !== 'prototype'
439+ ) {
440+ return
441+ }
442+ let symbol = this . checker . getSymbolAtLocation ( assignment . left . expression )
443+ if ( symbol && ( symbol . flags & ts . SymbolFlags . Alias ) !== 0 ) {
444+ symbol = this . checker . getAliasedSymbol ( symbol )
445+ }
446+ return symbol ?. valueDeclaration ?? symbol ?. declarations ?. [ 0 ]
447+ }
448+
427449 private scipSymbol ( node : ts . Node ) : ScipSymbol {
428450 const fromCache : ScipSymbol | undefined =
429451 this . globalSymbolTable . get ( node ) || this . localSymbolTable . get ( node )
@@ -490,6 +512,14 @@ export class FileIndexer {
490512 }
491513 }
492514
515+ const prototypeOwner = this . prototypeAssignmentOwner ( node )
516+ if ( prototypeOwner ) {
517+ // Methods in `Constructor.prototype = { ... }` belong to the constructor,
518+ // not to an anonymous object local to this file. Giving that object the
519+ // constructor's identity makes its members stable across files.
520+ return this . cached ( node , this . scipSymbol ( prototypeOwner ) )
521+ }
522+
493523 const owner = this . scipSymbol ( node . parent )
494524 if ( owner . isEmpty ( ) || owner . isLocal ( ) ) {
495525 return this . newLocalSymbol ( node )
0 commit comments