Activate the TS/JS member-call resolver for .mjs and .cjs

`_DISPATCH` routes `.mjs`/`.cjs` to `extract_js` and the cross-file call gate
already lists them, but `typescript_member_calls` claimed only six suffixes, so a
repo written entirely in `.mjs` was the one shape where the resolver never ran and
`const s = new Svc(); s.doThing()` produced no edge.

Both the suffix set and the resolver now read one `_JS_TS_SUFFIXES` constant.
This commit is contained in:
xiongjianxu committed 2026-10-13 11:06:19 +08:00
1 parent a9860f70dc
commit 84fce94ce8
2 files changed
+18 -1

No files matched your search

+7 -1
View File
@@ -4975,6 +4975,11 @@ def _resolve_python_member_calls(
_emit_call(caller, children[0], rc)
# Every suffix the TS/JS extractors claim. The member-call resolver both activates on
# and parks by this set, so a pure-ESM (`.mjs`) repo is not silently left out.
_JS_TS_SUFFIXES = (".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs")
def _resolve_typescript_member_calls(
per_file: list[dict],
all_nodes: list[dict],
@@ -7049,7 +7054,8 @@ register_language_resolver(
LanguageResolver("ruby_member_calls", frozenset({".rb", ".rake"}), resolve_ruby_member_calls)
)
register_language_resolver(
LanguageResolver("typescript_member_calls", frozenset({".ts", ".tsx", ".mts", ".cts", ".js", ".jsx"}), _resolve_typescript_member_calls)
LanguageResolver("typescript_member_calls", frozenset(_JS_TS_SUFFIXES),
_resolve_typescript_member_calls)
)
# C++ (#1547) and ObjC (#1556) receiver-typed member-call resolution. `.h` is in
# both suffix sets because it routes to extract_cpp or extract_objc by content; the
+11
View File
@@ -296,3 +296,14 @@ def test_public_property_sharing_a_private_methods_node_keeps_its_edge(tmp_path)
"export function go(c: Ctx): number { return c.respond(); }\n"),
})
assert any("go" in str(s) and "respond" in str(t) for s, t in calls), calls
def test_a_pure_esm_corpus_still_activates_the_resolver(tmp_path):
# `.mjs` and `.cjs` route to extract_js like `.js` does, so a repo that uses
# only those must not be the one shape where the resolver never runs.
calls, _ = _calls(tmp_path, {
"svc.mjs": "export class Svc {\n doThing() { return 1; }\n}\n",
"app.mjs": ('import { Svc } from "./svc.mjs";\nconst s = new Svc();\n'
"export function usesDirect() { return s.doThing(); }\n"),
})
assert any("usesDirect" in s and "doThing" in t for s, t in calls)