Skip to content

code-graph: complete dependency detection in TypeScript, Python, and Go #52

@lsmonki

Description

@lsmonki

Context

While reviewing the code-graph work for dynamic dependencies in PHP, it became clear that there is also relevant debt in the non-PHP adapters.

Today the provider registers default adapters for TypeScript, Python, Go, and PHP, but the actual support level is uneven. In particular:

  • TypeScript handles static import ... from ... forms reasonably well and uses them for IMPORTS and CALLS.
  • Python covers import ... and from ... import ..., with some relative import resolution and simple call resolution.
  • Go parses imports and symbols, but in practice it still does not build useful IMPORTS or CALLS relations.
  • Resolution in the indexer still depends on extractImportedNames() + resolveImports() + extractRelations(), so anything that falls outside that model is invisible to the graph.

This makes the code graph acceptable for simple static imports, but incomplete for real dependency detection in modern projects.

Current gaps

TypeScript

  • No detection of dynamic import().
  • No detection of require('...') in CommonJS/interoperability scenarios.
  • Side-effect imports such as import './polyfill' do not enter the ImportDeclaration model, so they do not go through the normal resolution pipeline.
  • CALLS extraction resolves simple identifiers, but does not cover member expressions such as obj.method() or ns.fn() well.
  • There is no support for tsconfig path aliases (paths, baseUrl) or more complex project layouts.

Python

  • No detection of dynamic imports via importlib.import_module() or __import__().
  • import x.y is modeled syntactically, but that does not always match the name that is actually accessible in the importing module.
  • Package/submodule resolution is still limited for real-world layouts (src/, namespace packages, etc.).
  • CALLS resolution is heuristic and name-based; it does not cover instance dispatch, inheritance, mixins, monkey patching, etc. well.

Go

  • The adapter parses import statements, but extractRelations() currently emits only DEFINES.
  • No real IMPORTS relations are emitted.
  • No CALLS relations are emitted for imported functions or methods.
  • It still needs to resolve selector_expression (pkg.Func(), obj.Method()), which is the normal case in Go.
  • Alias imports, dot imports, and blank imports are not handled well yet.
  • Module/package resolution needs to be more precise than the current state based on imported name and prefix matching.

Cross-cutting gap: inheritance and type hierarchy

At some point we also need to address inheritance and type hierarchy explicitly, because that is currently not covered as part of the dependency model.

This applies at least to:

  • extends / implements in TypeScript
  • class inheritance and method resolution in Python
  • promoted methods / receiver-related composition in Go

Even if this eventually becomes a separate issue, it should remain visible here because it directly affects call analysis, navigation, and blast-radius accuracy.

Why this matters

Without these improvements, the code graph:

  • under-represents real dependencies
  • produces incomplete CALLS data
  • reduces the reliability of impact analysis
  • can make some repositories look more loosely coupled than they really are

Suggested direction

  • Complete Go until it can emit useful IMPORTS and CALLS, not just parse imports.
  • Extend TypeScript to cover dynamic import, require(), and side-effect imports.
  • Extend Python to cover importlib / __import__ and improve module/package resolution.
  • Design an extension to the model or adapters for inheritance/type relations.
  • Define explicitly what should count as a “detectable dependency”: safe static only, heuristic dynamic, or both with different confidence levels.

Related context

There is an active PHP-focused change already in progress:

  • php-adapter-dynamic-deps

This issue records the equivalent debt in the non-PHP adapters so it can be addressed later, ideally without mixing it into the PHP-specific framework/loader work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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