Skip to content

A high-performance, modular static analysis tool written in Zig that generates enriched call graphs for multiple programming languages using tree-sitter grammars.

License

Notifications You must be signed in to change notification settings

rand/calligrapher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

82 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Calligrapher

CI Version Zig

A fast, memory-safe static call graph analyzer for Python, written in Zig.

Calligrapher analyzes Python code to extract call graphs enriched with cyclomatic complexity metrics, control flow analysis, and powerful query operations. Built with tree-sitter for fast, error-tolerant parsing.

Features

  • 🎯 Python Call Graph Extraction: Functions, classes, methods, parameters, and calls
  • πŸ“‚ Multi-File Analysis: Project scanning, import resolution, cross-module call graphs
  • πŸ”— Module Dependencies: Dependency graphs, coupling analysis, instability metrics
  • πŸ“Š Cyclomatic Complexity: Automatic computation for all functions and methods
  • πŸ” Control Flow Analysis: Loop depth, nesting levels, and branch tracking
  • πŸ“€ Multiple Export Formats: JSON, DOT (GraphViz), and Mermaid
  • πŸ”Ž Query Operations: Find callers, callees, paths, and symbol search
  • πŸ“ˆ Project Metrics: Statistics, distribution analysis, and complexity hotspots
  • ⚑ High Performance: <50ms for small files, linear scaling for projects
  • πŸ”’ Memory Safe: Zero leaks, zero panics, comprehensive testing

Quick Start

Installation

Prerequisites:

  • Zig 0.13.0 or later

Build from source:

git clone https://github.com/rand/calligrapher.git
cd calligrapher
zig build

Binary available at zig-out/bin/calligrapher.

Basic Usage

# Analyze a Python file and generate call graph with metrics
zig build run -- enrich examples/python/minimal/project.py -o output.json

# Analyze entire project directory (multi-file)
zig build run -- enrich examples/python/multi_module/ -o project_output.json

# Export project manifest
zig build run -- enrich ./my_project --manifest -o manifest.json

# Generate GraphViz visualization
zig build run -- enrich examples/python/with_classes/shapes.py --format=dot -o graph.dot
dot -Tpng graph.dot -o graph.png

# Generate Mermaid diagram
zig build run -- enrich examples/python/with_types/types_demo.py --format=mermaid -o diagram.mmd

# Query operations
zig build run -- query output.json find Circle
zig build run -- query output.json callers module.function
zig build run -- query output.json path from_func to_func

Example Output

After running enrich, you'll see project metrics:

Project Metrics Summary
=======================

Complexity Distribution:
  Low (1-5):      15 functions (75.0%)
  Moderate (6-10): 4 functions (20.0%)
  High (11-20):    1 function  (5.0%)
  Very High (21+): 0 functions (0.0%)

Statistics:
  Mean complexity:     4.2
  Median complexity:   3.0
  Std deviation:       2.1

Top 5 Most Complex Functions:
  1. module.process_data (complexity: 12)
  2. module.validate_input (complexity: 8)
  ...

Documentation

  • QUICKSTART.md (824 lines) - Complete user guide with examples and troubleshooting
  • API.md (1,000+ lines) - Developer reference for library integration and extension
  • CHANGELOG.md - Release history and upgrade notes
  • STATUS.md - Project status and milestone tracking

Export Formats

JSON (Default)

Structured data with symbols, call graph, complexity metrics, and control flow:

zig build run -- enrich file.py -o output.json

DOT (GraphViz)

Visual graphs with complexity-based coloring:

zig build run -- enrich file.py --format=dot -o graph.dot
dot -Tpng graph.dot -o graph.png

Mermaid (Markdown)

GitHub/GitLab compatible diagrams:

zig build run -- enrich file.py --format=mermaid -o diagram.mmd

Query Operations

# Find symbols by name (partial match)
zig build run -- query output.json find symbol_name

# Find who calls this function
zig build run -- query output.json callers module.function

# Find what this function calls
zig build run -- query output.json callees module.function

# Find shortest path between functions
zig build run -- query output.json path from_func to_func

# Find all paths (depth-limited to 10)
zig build run -- query output.json allpaths from_func to_func

Metrics

Cyclomatic Complexity Ranges:

  • 1-5: Low (simple, easy to test)
  • 6-10: Moderate (acceptable)
  • 11-20: High (consider refactoring)
  • 21+: Very high (difficult to maintain)

Control Flow Metrics:

  • Maximum loop depth
  • Maximum nesting level
  • Conditional branch count

Project Statistics:

  • Mean, median, standard deviation
  • Complexity distribution
  • Top N most complex functions

Performance

  • Small files (<100 LOC): <50ms
  • Medium files (100-1K LOC): 50-200ms
  • Large files (1K-10K LOC): 200ms-2s
  • Memory usage: <100MB for typical projects

See PERFORMANCE.md for detailed benchmarks.

Testing

# Run all tests
zig build test

# Run release testing script
./scripts/test_release.sh

# Run performance benchmarks
./scripts/benchmark.sh

Test Coverage:

  • 50+ unit and integration tests
  • Automated CI on every commit
  • Memory leak audit (zero leaks)
  • Error handling review (zero panics)

Examples

The examples/python/ directory contains sample projects:

  • minimal: Basic Python project
  • with_imports: Import handling
  • with_classes: OOP patterns with inheritance
  • with_types: Type annotations
  • multi_module: Multi-file project structure

Each example includes expected output for validation.

Architecture

Calligrapher uses a modular pipeline architecture:

Input Python β†’ Tree-sitter Parser β†’ Symbol Extraction β†’ Name Resolution
                                    ↓
                         Complexity Computation
                                    ↓
                    Call Graph Construction
                                    ↓
              Export (JSON/DOT/Mermaid) or Query

Modules:

  • Core: Graph data structures (symbols, nodes, edges)
  • Parser: Tree-sitter bindings and query system
  • Extractors: Language-specific symbol extraction
  • Resolution: Scope-based name resolution
  • Integration: Bridges extraction and resolution
  • Export: Multi-format serialization
  • Query: Graph analysis operations
  • Metrics: Project-level statistics

See API.md for detailed architecture documentation.

Known Limitations

  • Single-file processing: Multi-file analysis planned for v0.2.0
  • Python-only: Additional languages (Rust, JS, TS) planned for v0.3.0
  • Static analysis only: No dynamic/runtime analysis
  • Import resolution: Limited to stdlib and relative imports
  • Query depth: Limited to 10 for performance

Roadmap

v0.2.0 (Next)

  • Multi-file project analysis
  • Cross-module dependency graphs
  • Package support (init.py)
  • Enhanced import resolution

v0.3.0

  • Rust language support
  • JavaScript/TypeScript support
  • Additional complexity metrics

v1.0.0

  • Stable API
  • Complete language coverage
  • Production-grade performance

See PROJECT_PLAN.md for detailed roadmap.

Contributing

Contributions welcome! See API.md for guides on:

  • Adding new languages (step-by-step tutorial)
  • Adding new export formats
  • Extending functionality

Please open an issue or PR referencing relevant items in STATUS.md.

Quality Assurance

  • Memory Safety: Comprehensive audit (750+ lines documented), zero leaks found
  • Error Handling: Zero panics in production code, consistent error messages
  • Testing: 50+ tests, 100% coverage of major operations
  • CI/CD: Automated testing on every commit
  • Performance: Baseline established, benchmarks documented

Code Metrics

  • ~13,000 lines of Zig code
  • 38 source files
  • 50+ tests
  • 8 major modules

Technical Stack

  • Language: Zig 0.13.0
  • Parser: Tree-sitter (vendored Python grammar v0.25.9)
  • Design: Modular architecture with clear layer separation
  • Memory: Arena allocators, string interning, RAII patterns
  • Complexity: Linear time for most operations

Credits

  • Primary Developer: Rand Arete
  • Development Assistance: Claude Code
  • Built With: Zig and Tree-sitter

License

Calligrapher is distributed under the MIT License.

Getting Help


Version 0.1.0 | October 13, 2025 | Initial Release

About

A high-performance, modular static analysis tool written in Zig that generates enriched call graphs for multiple programming languages using tree-sitter grammars.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •