Skip to content

Bash: calls to functions defined in a sourced file never get call edges #2141

Description

@HerenderKumar

Summary

When a Bash script calls a function that's defined in a sourced file, graphify never records the call edge. The function definitions and the source/import edge are all indexed fine, but the caller shows zero outgoing calls to the sourced function — so shell scripts look disconnected from the libraries they use.

This is separate from #2079. #2079 is about the source edge (source "${VAR}/lib.sh" pointing at nothing). This one is about the call edge, and it happens even with a plain source ./lib.sh where the source edge resolves fine.

Reproduction (mainline v8)

b.sh

#!/usr/bin/env bash
b_func() { echo ok; }

a.sh

#!/usr/bin/env bash
source ./b.sh
main() { b_func; }
graphify .

In graph.json:

  • imports_from: a.sh -> b.sh ✅ (source edge resolves)
  • calls: [] ❌ (expected main -> b_func)

b_func has no incoming call edge, so graphify path main b_func and graphify callers b_func come up empty even though both functions are indexed.

Root cause

  • extract_bash (graphify/extractors/bash.py) only records a call edge when the callee is defined in the same file (name in defined_functions). A call to a function from a sourced file is silently dropped, and the extractor returns just {"nodes", "edges"} — it never emits the raw_calls / bash_sources that other languages use for cross-file resolution.
  • There's already a resolver for exactly this — resolve_bash_source_edges (graphify/symbol_resolution.py:404), with unit tests — but it has no call site anywhere in graphify/. It's defined and tested but not wired into the extract pipeline, and it has no raw_calls / bash_sources to work from anyway.

Suggested fix

Have extract_bash emit raw_calls for calls whose callee isn't defined in the current file (plus bash_sources for the source edges), then run them through resolve_bash_source_edges in the pipeline so cross-file calls to sourced functions become real calls edges.

Acceptance

Prior art

Aziron's atlas hit the same thing and split it into these two exact halves — source resolution and the intra-function call — in aziron-ai/atlas#13, which also references #2079.

Environment: graphify 0.9.25 (v8), macOS arm64.

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