Skip to content

TypeScript: this.m() links to an imported function m instead of the class's own m #2954

Open

Description

@inth3shadows

this.m() inside a class links to a function m that the file imports, not to the class's own m. This is the common case of a class wrapping a helper of the same name.

// lib.ts
export function findAll(q: string): string[] { return [q]; }
export const getFactor = (w: number): number => w;

// tools.ts
import { findAll, getFactor } from './lib';
export class Tools {
  run(q: string) { return this.findAll(q); }                               // line 3
  private findAll(q: string): string[] { return findAll(q).concat('own'); } // line 4
  size(w: number) { return this.getFactor(w); }                            // line 5
  private getFactor = (w: number): number => getFactor(w) * 2;             // line 6
}
call edge on main expected
line 3 this.findAll(q) lib.ts findAll (resolvedBy: import) ✗ Tools.findAll (line 4)
line 4 findAll(q) lib.ts findAll ✓ same
line 5 this.getFactor(w) lib.ts getFactor (resolvedBy: import) ✗ Tools.getFactor (line 6)
line 6 getFactor(w) lib.ts getFactor ✓ same

The class's own findAll and getFactor get no callers from run/size, and the import gets callers that never call it directly. The edge's refName is the bare name (findAll), so the this. receiver is already lost by the time the import binding answers.

Reproduced on main at 2577601 with CODEGRAPH_KERNEL=0. Linux/WSL2, Node 22.23.2. 2577601 ("a call on the caller's own class reaches that class's member") doesn't change this: that path ranks same-named methods, and here the import answers first.

In this repo. ToolHandler in src/mcp/tools.ts imports groupDefinitions from ../graph/symbol-lookup and also has a private groupDefinitions(...) (line 3220). this.groupDefinitions(allMatches.nodes, fileFilter) at line 3250 links to src/graph/symbol-lookup.ts. this.findAllSymbols(cg, symbol) at lines 3245 and 3328 does the same with src/graph/named-symbol-flow.ts, ignoring the class's own findAllSymbols (line 8675). I counted 7 such edges in the index of this repo, and 1 in excalidraw (this.getFormFactor(…) in App.tsx → packages/common/src/editorInterface.ts, ignoring App's private getFormFactor = …). Found by checking every TS calls edge against the TypeScript checker.

Expected. A call with a this. (or super.) receiver should never resolve through the file's import bindings. It names a member, not a binding in scope.

Related: 2577601 / #1952 (own-class members for this. calls), #2953 (x.m() resolved through the import of x).

Activity

  1. inth3shadows commented on Oct 29, 2026

    @inth3shadows
    ContributorAuthor

    Re-checked on main at 60b0d7a (2026-10-29): still reproduces as described.

    More real cases, found by diffing codegraph's call edges against scip-typescript on codegraph's own source. ToolHandler in src/mcp/tools.ts wraps imported helpers in private methods of the same name, and each this.<name>(...) links to the import instead of the method. There are 7 such call sites, for example:

    • this.findAllSymbols(cg, symbol) (lines 3267, 3350, 3430) links to src/graph/named-symbol-flow.ts: findAllSymbols, but should link to ToolHandler.findAllSymbols (line 8697);
    • this.groupDefinitions(...) (lines 3272, 3355) links to src/graph/symbol-lookup.ts: groupDefinitions.

    I filed this again by mistake as #3034, which is now closed as a duplicate of this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions