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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions