MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / resolvePythonModuleMember

Function resolvePythonModuleMember

src/resolution/import-resolver.ts:1592–1644  ·  view source on GitHub ↗

* Resolve a Python qualified reference whose receiver is an imported MODULE: * `certs.where()` after `from . import certs`, `mod.func()` after `import mod` * or `from pkg import mod`. The receiver names a submodule (a file), not a * symbol, so the generic symbol lookup in `resolveViaImport` can't

(
  ref: UnresolvedRef,
  imports: ImportMapping[],
  context: ResolutionContext
)

Source from the content-addressed store, hash-verified

1590 * to the other strategies untouched.
1591 */
1592function resolvePythonModuleMember(
1593 ref: UnresolvedRef,
1594 imports: ImportMapping[],
1595 context: ResolutionContext
1596): ResolvedRef | null {
1597 const dotIdx = ref.referenceName.indexOf('.');
1598 if (dotIdx <= 0) return null;
1599 const receiver = ref.referenceName.substring(0, dotIdx);
1600 // The immediate member of the module (first segment after the receiver).
1601 const member = ref.referenceName.substring(dotIdx + 1).split('.')[0];
1602 if (!member) return null;
1603
1604 for (const imp of imports) {
1605 if (imp.localName !== receiver) continue;
1606
1607 // `import mod` / `import numpy as np` bind the module at `source` itself;
1608 // `from . import certs` / `from pkg import mod` bind a SUBMODULE whose
1609 // dotted path is the source joined with the imported name.
1610 const modulePath = imp.isNamespace
1611 ? imp.source
1612 : imp.source.endsWith('.')
1613 ? imp.source + imp.localName
1614 : imp.source + '.' + imp.localName;
1615
1616 // resolveImportPath only maps RELATIVE dotted paths (`.mod`, `..pkg.mod`); an
1617 // ABSOLUTE package path (`pkg.module` from `from pkg import module`, or a bare
1618 // `import pkg.mod`) resolves to null there, so fall back to the dotted-module
1619 // file lookup — the same asymmetry resolveModuleImportToFile already handles
1620 // for the file→file import edge. Without this, a `module.func()` call after
1621 // `from pkg import module` dropped its `calls` edge even though the import
1622 // edge resolved (#578).
1623 let resolvedPath = resolveImportPath(modulePath, ref.filePath, ref.language, context);
1624 if (!resolvedPath) {
1625 resolvedPath = findPythonModuleFile(modulePath, context, ref.filePath)?.filePath ?? null;
1626 }
1627 if (!resolvedPath || resolvedPath === ref.filePath) continue;
1628
1629 // Find the member as a top-level definition in the module file. Exclude
1630 // `method` so `mod.foo` never lands on a same-named class method.
1631 const target = context.getNodesInFile(resolvedPath).find(
1632 (n) =>
1633 n.name === member &&
1634 (n.kind === 'function' ||
1635 n.kind === 'class' ||
1636 n.kind === 'variable' ||
1637 n.kind === 'constant')
1638 );
1639 if (target) {
1640 return { original: ref, targetNodeId: target.id, confidence: 0.85, resolvedBy: 'import' };
1641 }
1642 }
1643 return null;
1644}
1645
1646/**
1647 * Resolve a whole-MODULE import to that module's file (a file→file dependency).

Callers 1

resolveViaImportFunction · 0.85

Calls 3

resolveImportPathFunction · 0.85
findPythonModuleFileFunction · 0.85
getNodesInFileMethod · 0.65

Tested by

no test coverage detected