Skip to content

fummicc1/swift-complexity

Repository files navigation

swift-complexity

A command-line tool to analyze Swift code complexity and quality metrics using swift-syntax.

Features

  • Multiple Complexity Metrics: Supports cyclomatic complexity, cognitive complexity, and LCOM4 cohesion analysis
  • LCOM4 Class Cohesion: High-precision class cohesion measurement using IndexStore-DB semantic analysis
  • Web-based Debug Interface: Interactive browser-based complexity analyzer (Try it online)
  • Xcode Integration: Seamless integration with Xcode via Build Tool Plugin for complexity feedback during build phase
  • Xcode Diagnostics: Display complexity warnings and errors directly in Xcode editor with accurate line numbers
  • Configurable Thresholds: Set custom complexity thresholds via Xcode Build Settings or environment variables
  • Per-Type Thresholds: Assign different thresholds to types by name (prefix/suffix) via a .swift-complexity.yml config — e.g. stricter limits for *Repository, looser for *UseCase
  • Exit Code Integration: Returns exit code 1 when complexity thresholds are exceeded, perfect for CI/CD pipelines
  • Multiple Output Formats: Text, JSON, XML, Xcode diagnostics, and SARIF output for different use cases
  • Flexible Analysis: Single files, directories, or recursive directory analysis
  • Swift Syntax Based: Uses swift-syntax for accurate Swift code parsing
  • Cross-Platform Support: CLI works on macOS and Linux, library works on iOS 13+.
  • MCP Server: Expose complexity analysis as tools for LLM agents (Claude Code, etc.) via Model Context Protocol
  • Claude Plugin: Ready-to-use Claude Code plugin with MCP server and analysis skill
  • Extensible Architecture: Designed to support additional quality metrics in the future

Quick Start

Web Interface (Try Online)

Visit swift-complexity.fummicc1.dev to analyze Swift code instantly in your browser.

Web Interface

Installation

On macOS the recommended path is Homebrew:

brew install fummicc1/tap/swift-complexity

Or build from source:

git clone https://github.com/fummicc1/swift-complexity
cd swift-complexity
swift build -c release

Pre-built binaries are also available from GitHub Releases as Swift Artifact Bundles, or via nest install fummicc1/swift-complexity.

Basic Usage

# Analyze a single file
swift run SwiftComplexityCLI path/to/file.swift

# Analyze a directory with threshold enforcement
swift run SwiftComplexityCLI Sources --threshold 10

# JSON output for tooling integration
swift run SwiftComplexityCLI Sources --format json --recursive

# Xcode diagnostics format (for IDE integration)
swift run SwiftComplexityCLI Sources --format xcode --threshold 15

# SARIF format (for GitHub Code Scanning)
swift run SwiftComplexityCLI Sources --format sarif --threshold 10 --recursive > swift-complexity.sarif

# LCOM4 class cohesion analysis (requires swift build first)
swift build  # Generate index
swift run SwiftComplexityCLI Sources --lcom4 --index-store-path .build/debug/index/store

CLI Integration

The tool returns exit code 1 when any function exceeds the specified complexity threshold, making it ideal for:

  • CI/CD Pipelines: Fail builds when complexity thresholds are exceeded
  • Git Hooks: Prevent commits with overly complex code
  • Code Quality Gates: Enforce complexity standards across teams
# Example: Fail if any function has complexity > 15
swift run SwiftComplexityCLI Sources --threshold 15 --recursive
# Exit code 0: All functions below threshold
# Exit code 1: One or more functions exceed threshold

Per-Type Thresholds

Assign different thresholds per nominal type (class/struct/enum/actor and extensions) so each layer or feature gets its own complexity budget. Create a .swift-complexity.yml (auto-discovered in the current directory, or pass --config <path>):

# .swift-complexity.yml
defaultThreshold: 10            # Fallback for types matching no rule (optional)
rules:
  - prefix: Toilet              # Feature grouping (type name prefix)
    threshold: 12
  - suffix: Repository          # Layer grouping (type name suffix)
    threshold: 5
  - suffix: UseCase
    threshold: 15

A function's threshold is resolved from its enclosing type name: among all matching rules the strictest (lowest) wins (e.g. ToiletRepository matches Toilet=12 and Repository=5 → 5). Unmatched types fall back to --threshold or defaultThreshold.

# Auto-discovers .swift-complexity.yml
swift run SwiftComplexityCLI Sources --recursive

# Explicit config path
swift run SwiftComplexityCLI Sources --recursive --config config/complexity.yml

See the Usage Guide for full resolution rules.

Supported Complexity Metrics

Function-level Metrics

  • Cyclomatic Complexity: Measures the number of linearly independent paths through code
  • Cognitive Complexity: Measures how difficult code is for humans to understand

Class-level Metrics

  • LCOM4 (Lack of Cohesion of Methods): Measures class cohesion by analyzing method-property relationships
    • Connected Components: Counts independent groups of related methods
    • High Precision: Semantic analysis powered by IndexStore-DB
    • Implicit self Detection: Automatically detects both self.property and property accesses
    • Requirements: Requires swift build to generate index data

Documentation

Package Structure

Unified package with multiple components:

Core Package

  • SwiftComplexityCore: Core analysis library (supports macOS 14+, iOS 13+)
  • SwiftComplexityCLI: Command-line interface
  • SwiftComplexityMCP: MCP server for LLM agent integration
  • SwiftComplexityPlugin: Xcode Build Tool Plugin

Debug Website

  • Frontend: Next.js application deployed on Cloudflare Workers
  • Backend: Vapor 4 API containerized on Cloudflare Containers.
  • Live Demo: swift-complexity.fummicc1.dev

Usage Examples

# Analyze with verbose output
swift run SwiftComplexityCLI Sources --verbose --recursive

# Exclude test files with pattern matching
swift run SwiftComplexityCLI Sources --recursive --exclude "*Test*.swift"

# Show only cognitive complexity above threshold
swift run SwiftComplexityCLI Sources --cognitive-only --threshold 5

# Analyze class cohesion with LCOM4
swift build  # Generate index first
swift run SwiftComplexityCLI Sources --lcom4 --index-store-path .build/debug/index/store --format json

MCP Server

The MCP (Model Context Protocol) server exposes complexity analysis as tools for LLM agents like Claude Code.

Installation

# Homebrew (macOS, recommended)
brew install fummicc1/tap/swift-complexity-mcp

# Mint: MCP server only
mint install fummicc1/swift-complexity SwiftComplexityMCP

# Mint: both CLI and MCP server at once
mint install fummicc1/swift-complexity

MCP Tools

Tool Description
analyze_complexity Analyze Swift files/directories on disk (recursive, threshold, per-type thresholds via config_path, LCOM4 support)
analyze_code_string Analyze a Swift code string directly without files on disk

Configuration

Claude Code (settings.json):

{
  "mcpServers": {
    "swift-complexity": {
      "command": "SwiftComplexityMCP"
    }
  }
}

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "swift-complexity": {
      "command": "SwiftComplexityMCP"
    }
  }
}

Claude Plugin

A ready-to-use Claude Code plugin is available in claude-plugin/.

Prerequisite: The plugin requires SwiftComplexityMCP binary in your PATH. Install via Mint first:

mint install fummicc1/swift-complexity SwiftComplexityMCP

Then load the plugin:

# Load the plugin
claude --plugin-dir ./claude-plugin

# Use the skill
/swift-complexity:analyze-complexity

The plugin bundles the MCP server configuration and an analyze-complexity skill that guides Claude through complexity analysis workflows.

Xcode Build Tool Plugin

Integrates with both Swift Package Manager and Xcode projects for automatic complexity analysis during builds.

Swift Package Manager Integration

// swift-tools-version: 6.2
import PackageDescription

let package = Package(
    name: "YourProject",
    dependencies: [
        .package(url: "https://github.com/fummicc1/swift-complexity.git", from: "1.0.0")
    ],
    targets: [
        .target(
            name: "YourTarget",
            plugins: [
                .plugin(name: "SwiftComplexityPlugin", package: "swift-complexity")
            ]
        )
    ]
)

Xcode Project Integration

  1. Add swift-complexity package to your Xcode project
  2. In Build Phases, add "SwiftComplexityPlugin" to Run Build Tool Plug-ins
  3. Configure threshold in Build Settings (optional)

Configuration

Xcode Build Settings:

  • Key: SWIFT_COMPLEXITY_THRESHOLD
  • Value: 15 (or any number, defaults to 10)

Environment Variable (SPM):

  • SWIFT_COMPLEXITY_THRESHOLD=15

Features

  • Real-time feedback: Complexity warnings appear directly in Xcode editor
  • Accurate positioning: Errors show at exact function locations
  • Build integration: Builds fail when thresholds are exceeded
  • Configurable per target: Different thresholds for different modules

Xcode Output

Output Examples

CLI Text Output

File: Sources/ComplexityAnalyzer.swift
+------------------+----------+----------+
| Function/Method  | Cyclo.   | Cogn.    |
+------------------+----------+----------+
| analyzeFunction  |    3     |    2     |
| calculateTotal   |    5     |    7     |
+------------------+----------+----------+

Total: 2 functions, Average Cyclomatic: 4.0, Average Cognitive: 4.5

Class Cohesion (LCOM4):
+--------------------+----------+----------+----------+----------+
| Class/Struct       | LCOM4    | Methods  | Props    | Level    |
+--------------------+----------+----------+----------+----------+
| ComplexityAnalyzer |    1     |    5     |    3     | High     |
| FileProcessor      |    2     |    8     |    4     | Moderate |
+--------------------+----------+----------+----------+----------+

Xcode Diagnostics Output

/path/to/Sources/MyFile.swift:45:1: error: Function 'complexFunction' has high complexity (Cyclomatic: 15, Cognitive: 23, Threshold: 10)
/path/to/Sources/MyFile.swift:89:1: warning: Function 'anotherFunction' has high complexity (Cyclomatic: 12, Cognitive: 18, Threshold: 10)

SARIF Output (GitHub Code Scanning)

Generate a SARIF report and upload it to GitHub Code Scanning to get complexity violations as inline pull request annotations:

- name: Analyze complexity
  run: swift-complexity Sources --format sarif --threshold 10 --recursive > swift-complexity.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: swift-complexity.sarif

Violations are reported per metric (cyclomatic_complexity, cognitive_complexity, and lcom4_cohesion) with warning level, escalating to error at twice the threshold.

Requirements

CLI Tool

  • Swift 6.2+
  • macOS 14+ or Linux

Core Library

  • Swift 6.2+
  • macOS 14+, iOS 13+, or Linux

LCOM4 Feature (Optional)

  • macOS 14+: Xcode toolchain is auto-detected
  • Linux: Requires --toolchain-path option pointing to Swift toolchain
  • Project must be buildable with swift build
  • Index data at .build/debug/index/store (generated by build)

Linux Example:

# Using Swiftly-installed toolchain
TOOLCHAIN=~/.local/share/swiftly/toolchains/swift-6.2.2-RELEASE
swift build \
  -Xcxx -I${TOOLCHAIN}/usr/lib/swift \
  -Xcxx -I${TOOLCHAIN}/usr/lib/swift/Block
.build/debug/SwiftComplexityCLI Sources --lcom4 \
  --index-store-path .build/debug/index/store \
  --toolchain-path ${TOOLCHAIN}

License

MIT License

About

Code Complexity Analyzer for Swift

Topics

Resources

License

Stars

33 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages