Skip to content

bug: resolveByReceiver typeMap lookup lacks cross-language guard, unlike resolveByGlobal #1981

Description

@carlos-alm

Summary

tests/unit/call-resolver.test.ts — describe block resolveByMethodOrGlobal — cross-language global fallback rejection (#1783) — has a failing test on fix/issue-1836-update-graph-sh-hook-fallback-build-path (confirmed at commit e0ab9dc8, no local modifications to src/):

FAIL tests/unit/call-resolver.test.ts > resolveByMethodOrGlobal — cross-language global fallback rejection (#1783) > does not resolve a typed-method lookup to a same-named type in a different language
AssertionError: expected [ { id: 3, file: 'lib/widget.js', kind: 'method' } ] to deeply equal []

Repro

const jsMethod = { id: 3, file: 'lib/widget.js', kind: 'method' };
const lookup = makeLookup({ 'Widget.render': [jsMethod] });
const result = resolveByMethodOrGlobal(
  lookup,
  { name: 'render', receiver: 'w' },
  'lib/widget.py',
  new Map([['w', 'Widget']]),
);
expect(result).toEqual([]); // actually returns [jsMethod]

A Python caller's w.render() (with w typed to Widget via the typeMap) incorrectly resolves to a same-directory JavaScript Widget.render method purely because the typeMap key matches — there is no static relationship between the two files/languages.

Root cause

resolveByGlobal's bare-call path guards against this exact cross-language false-positive class via isModuleScopedLanguage(relPath) (see src/domain/graph/resolver/strategy.ts:314if (!callerName || (isBareCall && isModuleScopedLanguage(relPath))) return [];), added for issue #1783.

resolveByReceiver's typeMap-based lookup (resolveReceiverTypeName and its callers in the same file) has no equivalent language-scoping guard — a typeMap-resolved type name (Widget) is looked up globally via lookup.byNameAndFile('Widget.render', ...)/lookup.byName(...) fallbacks without checking that the candidate's file extension is compatible with the caller's language.

Suggested fix

Apply the same (or an equivalent) cross-language guard used in resolveByGlobal to the receiver/typeMap resolution path in resolveByReceiver, so a typeMap hit in one language's file never satisfies a call site in a different language, mirroring the #1783 fix.

Found while

Validating the fix for issue #1838 (.claude/hooks/track-edits.sh) on this branch — confirmed unrelated to that change (no src/ modifications were made; failure reproduces on a clean worktree of fix/issue-1836-update-graph-sh-hook-fallback-build-path).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions