/graph-slice-rs

A powerful Rust code analysis tool that builds call graphs and breaks down large functions"

Primary LanguageRustMIT LicenseMIT

graph-slice-rs

Crates.io Documentation License: MIT

A powerful Rust code analysis tool that builds comprehensive call graphs and breaks down large functions into manageable chunks. Perfect for understanding complex codebases, refactoring, and code review.

Note: This project is a fork of slicer from the c2saferrust project, updated to work with Rust nightly 1.90 and enhanced with additional features.

中文文档

Features

  • 📊 Call Graph Analysis: Build and visualize function call relationships
  • 🔍 Function Decomposition: Automatically split large functions into logical chunks
  • 🔗 Dependency Tracking: Track function calls, global variables, and imports
  • 📄 JSON Export: Structured output for integration with other tools
  • Performance: Efficient analysis using Rust's compiler infrastructure
  • 🎯 Configurable: Customize chunk sizes and analysis parameters

Installation

Prerequisites

graph-slice-rs requires the Rust nightly toolchain:

# Install Rust nightly
rustup install nightly
rustup default nightly

# Add required components
rustup component add rust-src rustc-dev llvm-tools-preview

Install from crates.io

cargo install graph-slice-rs

Install from source

git clone https://github.com/zhanghandong/graph-slice-rs
cd graph-slice-rs
cargo install --path .

Quick Start

# Analyze your Rust project
cd your-rust-project
cargo graph-slice-rs

# Or use the short alias
cargo gs

# Generate call graph visualization
cargo gs -Zoutput-file=analysis.json
dot callgraph.dot -Tpng -o callgraph.png

Usage

Command Line Options

Option Description Default
-Zmax-lines=<N> Maximum lines per chunk 100
-Zmin-lines=<N> Minimum lines per chunk 20
-Zoutput-file=<path> Output JSON file path stdout
-Zdataflow-only Focus on dataflow analysis false
-Zinput-file=<path> Analyze specific file all files
-Zappend Append to existing output false

Examples

Basic Analysis

# Analyze entire project
cargo gs

# Analyze with custom chunk size
cargo gs -Zmax-lines=50 -Zmin-lines=10

Export and Visualization

# Export to JSON
cargo gs -Zoutput-file=analysis.json

# Generate and view call graph
dot callgraph.dot -Tsvg -o callgraph.svg
open callgraph.svg  # macOS
# xdg-open callgraph.svg  # Linux

Integration with jq

# Find functions with most dependencies
cargo gs | jq '[.[] | {func: .func_defid, calls: (.calls | length)}] | sort_by(.calls) | reverse | .[0:10]'

# Find functions using global variables
cargo gs | jq '.[] | select(.globals | length > 0) | {func: .func_defid, globals}'

# Extract all imports
cargo gs | jq '[.[] | .imports[]] | unique'

Output Format

The tool generates JSON with the following structure:

{
  "func_defid": "DefId(0:10 ~ example::process_data)",
  "span": "src/main.rs:10:1: 50:2",
  "num_lines": 40,
  "source": "fn process_data(...) { ... }",
  "calls": [
    {
      "caller": "DefId(0:10 ~ example::process_data)",
      "span": "src/main.rs:15:5: 15:20",
      "source": "validate_input()"
    }
  ],
  "globals": ["CONFIG", "COUNTER"],
  "imports": ["use std::collections::HashMap;"],
  "chunks": [
    {
      "span": "src/main.rs:10:1: 30:2",
      "source": "<<chunk 1>>",
      "sub_chunks": []
    }
  ]
}

Advanced Usage

Configuration File

Create .graph-slice-rs.json in your project root:

{
  "max_lines": 75,
  "min_lines": 15,
  "output_file": "build/analysis.json",
  "dataflow_only": false
}

CI/CD Integration

GitHub Actions

name: Code Analysis
on: [push, pull_request]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: nightly
          override: true
          components: rust-src, rustc-dev, llvm-tools-preview
      
      - name: Install graph-slice-rs
        run: cargo install graph-slice-rs
      
      - name: Run Analysis
        run: cargo gs -Zoutput-file=analysis.json
      
      - name: Upload Results
        uses: actions/upload-artifact@v2
        with:
          name: analysis-results
          path: |
            analysis.json
            callgraph.dot

Custom Analysis Scripts

import json
import matplotlib.pyplot as plt

# Load analysis data
with open('analysis.json') as f:
    data = json.load(f)

# Analyze function complexity
functions = [(d['func_defid'], d['num_lines']) for d in data]
functions.sort(key=lambda x: x[1], reverse=True)

# Plot top 20 largest functions
names = [f[0].split('::')[-1] for f in functions[:20]]
sizes = [f[1] for f in functions[:20]]

plt.figure(figsize=(12, 6))
plt.bar(names, sizes)
plt.xticks(rotation=45, ha='right')
plt.ylabel('Lines of Code')
plt.title('Largest Functions in Codebase')
plt.tight_layout()
plt.savefig('function_sizes.png')

Architecture

graph-slice-rs leverages Rust's compiler infrastructure:

  • HIR Analysis: Uses High-level Intermediate Representation for accurate code analysis
  • Visitor Pattern: Efficiently traverses the AST to build call graphs
  • Incremental Processing: Analyzes functions in dependency order
  • Parallel Analysis: Utilizes multiple cores for large codebases

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone the repository
git clone https://github.com/zhanghandong/graph-slice-rs
cd graph-slice-rs

# Run tests
cargo test

# Run on example code
cd example_code
cargo gs

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Built on Rust's powerful compiler infrastructure
  • Inspired by code analysis needs in large Rust projects
  • Thanks to all contributors and users

Related Projects