The Dependency Analyzer Core: Parsing module is the orchestration layer that turns a raw source repository into a dependency graph of code components (functions, classes, methods, etc.) ready for downstream documentation generation. It sits at the boundary between low-level, language-specific static analysis (performed by the Dependency_Analysis_Service and its Language_Analyzers) and the higher-level clustering/LLM documentation pipeline (see Backend_LLM_&_Documentation_Services).
It has two responsibilities:
- Parsing (
DependencyParserinast_parser.py) — walk a repository, run structure + call-graph analysis, and normalize the results into a flat dictionary of typedNodeobjects with resolveddepends_onedges. - Graph building (
DependencyGraphBuilderindependency_graphs_builder.py) — wrap the parser, persist the resulting graph to disk, and reduce the (typically huge) component graph down to a manageable set of leaf nodes that later drive bottom-up documentation generation.
This module is a child of Dependency_Analyzer_Core, sitting alongside its sibling Dependency_Analyzer_Core_models, which defines the Node, CallRelationship, Repository, and AnalysisResult data models consumed and produced here.
graph TB
subgraph FE["Frontend / CLI Entry Points"]
CLI[CLI Adapter]
DG["DocumentationGenerator<br/>(Backend_LLM_&_Documentation_Services)"]
end
subgraph THIS["Dependency_Analyzer_Core_parsing (this module)"]
DGB[DependencyGraphBuilder]
DP[DependencyParser]
end
subgraph SVC["Dependency_Analysis_Service"]
AS[AnalysisService]
RA[RepoAnalyzer]
CGA[CallGraphAnalyzer]
end
subgraph LANG["Language_Analyzers"]
PY[PythonASTAnalyzer]
TS[TreeSitter* Analyzers]
end
subgraph MODELS["Dependency_Analyzer_Core_models"]
Node[Node]
CR[CallRelationship]
AR[AnalysisResult]
end
subgraph SIB["Sibling helpers (Dependency_Analyzer_Core)"]
TOPO[topo_sort.py]
LEAF[leaf_selection.py]
end
subgraph CFG["Core_Config_&_Utils"]
Config[Config]
FM[FileManager]
end
CLI --> DG
DG -->|"build_dependency_graph()"| DGB
DGB -->|uses| Config
DGB -->|uses| FM
DGB --> DP
DP --> AS
AS --> RA
AS --> CGA
CGA --> LANG
LANG --> CR
DP -->|constructs| Node
DGB --> TOPO
DGB --> LEAF
DP -->|"components, leaf_nodes"| DG
DependencyParser is the entry point for turning a repository path into a dictionary of Node objects (Dict[str, Node]), keyed by a unique component id (e.g. path/to/file.py::ClassName.method_name).
Responsibilities:
- Accepts a
repo_path, optionalinclude_patterns/exclude_patternsfile filters, and ause_gitignoreflag. - Delegates all heavy lifting (file discovery, filtering, AST/tree-sitter parsing per language) to an internal
AnalysisServiceinstance from Dependency_Analysis_Service. - Normalizes the raw dict-based analysis output into strongly-typed
Nodeinstances (see Dependency_Analyzer_Core_models). - Resolves caller → callee relationships into each
Node.depends_onset, using both exact component-id matches and a fallback by-name lookup. - Persists the graph to JSON via
save_dependency_graph.
Key methods:
| Method | Purpose |
|---|---|
__init__(repo_path, include_patterns, exclude_patterns, use_gitignore) |
Configure the parser and instantiate an AnalysisService. |
parse_repository(filtered_folders=None) |
Orchestrates structure analysis → call-graph analysis → component/edge construction. Returns self.components. |
_build_components_from_analysis(call_graph_result) |
Converts raw functions/relationships dicts into Node objects and populates depends_on edges. |
_determine_component_type(func_dict) |
Maps raw analyzer output to a normalized component type (method, class, interface, function, etc.). |
_file_to_module_path(file_path) |
Converts a file path into a dotted module path (used for module bookkeeping). |
save_dependency_graph(output_path) |
Serializes all components (with depends_on sets converted to lists) to a JSON file. |
sequenceDiagram
participant Caller as DependencyGraphBuilder
participant DP as DependencyParser
participant AS as AnalysisService
participant RA as RepoAnalyzer
participant CGA as CallGraphAnalyzer
participant LANG as Language Analyzers
Caller->>DP: parse_repository(filtered_folders)
DP->>AS: _analyze_structure(repo_path, include, exclude, use_gitignore)
AS->>RA: analyze_repository_structure(repo_dir)
RA-->>AS: file_tree, summary
AS-->>DP: structure_result
DP->>AS: _analyze_call_graph(file_tree, repo_path)
AS->>CGA: extract_code_files(file_tree)
CGA->>LANG: analyze per language (Python AST / Tree-sitter)
LANG-->>CGA: functions, relationships
CGA-->>AS: call_graph_result
AS-->>DP: call_graph_result
DP->>DP: _build_components_from_analysis(call_graph_result)
Note over DP: Builds Node objects,<br/>resolves depends_on edges
DP-->>Caller: components: Dict[str, Node]
_build_components_from_analysis performs two passes:
- Node construction pass — for every function/class entry returned by the call-graph analyzer, a
Node(see Dependency_Analyzer_Core_models) is created with fields likeid,component_type,file_path,source_code,docstring,parameters,base_classes, etc. Acomponent_id_mappingis built to support both the canonical id and a legacyfile_path:nameid format. Module paths are also collected intoself.modules. - Relationship resolution pass — for each
CallRelationship-like dict (caller,callee,is_resolved), the parser resolves both ends to canonical component ids (falling back to a name-based scan ofself.componentsif the callee id isn't directly found) and adds the callee id into the callerNode.depends_onset.
flowchart LR
A[Raw functions list] --> B{For each function}
B --> C[Create Node]
C --> D[components dict]
C --> E[component_id_mapping]
C --> F[modules set]
G[Raw relationships list] --> H{For each relationship}
H --> I[Resolve caller id via mapping]
H --> J[Resolve callee id via mapping<br/>or name fallback scan]
I --> K{caller found in components?}
J --> K
K -->|yes| L[Add callee to caller.depends_on]
DependencyGraphBuilder is a thin orchestration wrapper used directly by DocumentationGenerator (see Backend_LLM_&_Documentation_Services). It wires together DependencyParser, disk persistence, and leaf-node computation to produce the two artifacts the documentation pipeline needs: the full components map and a curated list of leaf_nodes.
Key method — build_dependency_graph():
- Ensures the configured
dependency_graph_direxists (viaFileManager, Core_Config_&_Utils). - Computes a sanitized output path
{repo_name}_dependency_graph.jsonfor the serialized graph. - Reads
include_patterns/exclude_patterns/use_gitignorefromConfig. - Instantiates a
DependencyParserand callsparse_repository()to getcomponents. - Persists the graph via
parser.save_dependency_graph(...). - Builds an in-memory adjacency graph with
build_graph_from_components(components)(fromtopo_sort.py). - Computes leaf nodes with
get_leaf_nodes(graph, components). - Filters leaf nodes down to valid types using
compute_valid_leaf_types+filter_leaf_nodes(fromleaf_selection.py), ensuring only real, well-typed components (classes/interfaces/structs, or functions in function-heavy codebases) are kept. - Returns
(components, keep_leaf_nodes).
flowchart TD
A[build_dependency_graph] --> B[ensure_directory: dependency_graph_dir]
B --> C[Compute dependency_graph_path]
C --> D["DependencyParser(repo_path, include, exclude, use_gitignore)"]
D --> E["parser.parse_repository()"]
E --> F[components: Dict-str-Node]
F --> G["parser.save_dependency_graph(path)"]
F --> H["build_graph_from_components(components)"]
H --> I["get_leaf_nodes(graph, components)"]
I --> J["compute_valid_leaf_types(components)"]
J --> K["filter_leaf_nodes(leaf_nodes, components, valid_types)"]
K --> L["return (components, keep_leaf_nodes)"]
The documentation pipeline (Backend_LLM_&_Documentation_Services) processes the codebase bottom-up: it needs a manageable, semantically meaningful set of "atomic" components — classes, interfaces, structs, or (in function-heavy / non-OOP codebases) standalone functions — to seed clustering and per-module documentation generation. Leaf nodes are nodes in the dependency graph that nothing else depends on (i.e., not referenced as a dependency by any other node), representing top-level entry points of the dependency chain. topo_sort.py and leaf_selection.py (siblings within Dependency_Analyzer_Core) implement:
- Cycle resolution — the raw call graph may contain cycles (e.g., mutual recursion);
get_leaf_nodesfirst resolves cycles into a DAG. - Conciseness —
__init__methods are collapsed to their owning class name so constructors don't appear as separate leaves. - Leaf reduction — if too many leaf nodes are found (
LEAF_REDUCTION_THRESHOLD), nodes that are dependencies of others are pruned from the leaf set to keep it a manageable size. - Type filtering —
compute_valid_leaf_typesdecides whether standalone functions should be treated as valid leaves (e.g. for C-style procedural codebases) or whether only class/interface/struct-like types should count (OOP_TYPES), based on the ratio of OOP vs. function components in the repo.
This module produces and consumes types defined in Dependency_Analyzer_Core_models:
Node— the canonical in-memory representation of a parsed code component (function, method, class, etc.), includingdepends_on: Set[str]for outgoing dependency edges.CallRelationship— the raw caller/callee shape produced by language analyzers before being folded intoNode.depends_on.Repository/AnalysisResult— used further upstream byAnalysisService.analyze_repository_full(see Dependency_Analysis_Service), thoughDependencyParseritself only uses the lower-level_analyze_structure/_analyze_call_graphprimitives rather than the fullAnalysisResultwrapper.
classDiagram
class Node {
+str id
+str name
+str component_type
+str file_path
+str relative_path
+Set~str~ depends_on
+Optional~str~ source_code
+int start_line
+int end_line
+bool has_docstring
+str docstring
+Optional~List~str~~ parameters
+Optional~str~ node_type
+Optional~List~str~~ base_classes
+Optional~str~ class_name
+Optional~str~ display_name
+Optional~str~ component_id
+get_display_name() str
}
class CallRelationship {
+str caller
+str callee
+Optional~int~ call_line
+bool is_resolved
}
class DependencyParser {
+str repo_path
+Dict~str,Node~ components
+Set~str~ modules
+AnalysisService analysis_service
+parse_repository(filtered_folders) Dict~str,Node~
+save_dependency_graph(output_path)
}
class DependencyGraphBuilder {
+Config config
+build_dependency_graph() tuple
}
class AnalysisService {
<<Dependency_Analysis_Service>>
}
DependencyGraphBuilder --> DependencyParser : creates and drives
DependencyParser --> Node : constructs
DependencyParser ..> CallRelationship : consumes as dicts
DependencyParser --> AnalysisService : delegates parsing
Config(see Core_Config_&_Utils) suppliesrepo_path,dependency_graph_dir,include_patterns,exclude_patterns, anduse_gitignoretoDependencyGraphBuilder.FileManager(see Core_Config_&_Utils) is used byDependencyGraphBuilderto ensure output directories exist (JSON persistence of the graph itself is done directly byDependencyParser.save_dependency_graph, using standard file I/O rather thanFileManager).
sequenceDiagram
participant DocGen as DocumentationGenerator
participant DGB as DependencyGraphBuilder
participant DP as DependencyParser
participant Topo as topo_sort.py
participant Leaf as leaf_selection.py
participant Disk as Filesystem (JSON)
DocGen->>DGB: build_dependency_graph()
DGB->>DP: DependencyParser(repo_path, patterns, use_gitignore)
DGB->>DP: parse_repository()
DP-->>DGB: components: Dict[str, Node]
DGB->>DP: save_dependency_graph(path)
DP->>Disk: write {repo}_dependency_graph.json
DGB->>Topo: build_graph_from_components(components)
Topo-->>DGB: graph: Dict[str, Set[str]]
DGB->>Topo: get_leaf_nodes(graph, components)
Topo-->>DGB: leaf_nodes
DGB->>Leaf: compute_valid_leaf_types(components)
Leaf-->>DGB: valid_types
DGB->>Leaf: filter_leaf_nodes(leaf_nodes, components, valid_types)
Leaf-->>DGB: keep_leaf_nodes
DGB-->>DocGen: (components, keep_leaf_nodes)
Note over DocGen: Proceeds to module clustering<br/>and per-module LLM documentation
DocumentationGenerator.run() (in Backend_LLM_&_Documentation_Services) calls self.graph_builder.build_dependency_graph() as its very first step, then uses the returned components and leaf_nodes to drive module clustering and bottom-up, per-module LLM documentation generation.
| Aspect | Details |
|---|---|
| Primary role | Convert a raw repository into a normalized, typed dependency graph and extract a curated set of leaf components. |
| Key classes | DependencyParser, DependencyGraphBuilder |
| Upstream dependency | Dependency_Analysis_Service (AnalysisService, RepoAnalyzer, CallGraphAnalyzer) and Language_Analyzers for actual per-language parsing. |
| Sibling dependency | Dependency_Analyzer_Core_models for Node/CallRelationship types; topo_sort.py and leaf_selection.py helpers within Dependency_Analyzer_Core for graph traversal and leaf filtering. |
| Downstream consumer | Backend_LLM_&_Documentation_Services (DocumentationGenerator), which uses the produced components/leaf_nodes to drive clustering and documentation generation. |
| Configuration source | Core_Config_&_Utils (Config, FileManager). |
| Persisted artifact | {sanitized_repo_name}_dependency_graph.json under Config.dependency_graph_dir. |