Skip to content

Rulesets & Linting

AST Metrics allows you to enforce rules on your codebase (Linting). You can check complexity, coupling, volume, and more.

Creating the configuration file

Rules live in an .ast-metrics.yaml file at the root of your project. Create it with:

ast-metrics init

You now have a documented starting point to edit, either by hand or by importing rulesets.

Managing Rulesets (CLI)

The easiest way to add rules is to use the ruleset command. It allows you to import pre-defined sets of rules.

Available Rulesets

You can list available rulesets with:

ast-metrics ruleset list
Ruleset Description
architecture Architecture-related constraints (e.g., coupling)
volume Volume metrics (e.g., lines of code)
complexity Complexity metrics (e.g., cyclomatic complexity)
golang Golang-specific best practices and API hygiene

Installing a Ruleset

To add a ruleset to your configuration:

ast-metrics ruleset add architecture
ast-metrics ruleset add volume

Detailed Rules

🏗️ Architecture Ruleset

ast-metrics ruleset add architecture

Rule Name Description
coupling Checks for forbidden coupling between packages
max_afferent_coupling Checks the afferent coupling of files/classes
max_efferent_coupling Checks the efferent coupling of files/classes
min_maintainability Checks the maintainability of the code
no_circular_dependencies Detect circular dependencies between classes
max_responsibilities Maximum number of responsibilities (LCOM) per class
no_god_class Avoid God Classes (too many methods/properties)
no_community_cycles Fails when communities depend on each other in a cycle
max_community_cross_share Maximum share (%) of dependencies crossing from one community to another
no_cross_community_dependencies Fails on every dependency crossing between communities; meant to be frozen with ast-metrics baseline

📏 Volume Ruleset

ast-metrics ruleset add volume

Rule Name Description
max_loc Checks the lines of code in a file
max_logical_loc Checks the logical lines of code in a file
max_loc_by_method Checks the lines of code by method/function
max_logical_loc_by_method Checks the logical lines of code by method/function
max_methods_per_class Maximum number of methods per class
max_switch_cases Maximum number of cases in switch statements
max_parameters_per_method Maximum number of parameters per method
max_nested_blocks Maximum nesting depth of blocks
max_public_methods Maximum number of public methods per class

🧠 Complexity Ruleset

ast-metrics ruleset add complexity

Rule Name Description
max_cyclomatic Checks the cyclomatic complexity of functions

🐹 Golang Ruleset

ast-metrics ruleset add golang

Rule Name Description
no_package_name_in_method Do not include the package name in exported function or method identifiers
max_nesting Limit nested depth of control structures (if/for/switch)
max_file_size Limit file size (LOC)
max_files_per_package Limit number of source files per package (excluding doc.go)
slice_prealloc Check if slice preallocation is used
context_missing Check if context is missing in function arguments
context_ignored Check if context is ignored

Manual Configuration

You can also manually edit the .ast-metrics.yaml file at the root of your project.

sources:
  - ./internal
exclude: []
reports:
  html: ./build/report
  markdown: ./build/report.md
requirements:
  rules:
    architecture:
      coupling:
        forbidden:
          - from: Controller
            to: Repository
          - from: Repository
            to: Service
      max_afferent_coupling: 10
      max_efferent_coupling: 10
      min_maintainability: 70
    volume:
      max_loc: 1000
      max_logical_loc: 600
      max_loc_by_method: 30
      max_logical_loc_by_method: 20
    complexity:
      max_cyclomatic: 10
    golang:
      no_package_name_in_method: true
      max_nesting: 4
      max_file_size: 1000
      max_files_per_package: 50
      slice_prealloc: true
      context_missing: true
      context_ignored: true

Check your rules with:

ast-metrics lint

The command exits with a non-zero status as soon as a requirement is violated, which makes it usable as-is in a pipeline. Add --report-sarif=lint.sarif to publish the violations to a platform that reads SARIF.

Starting on a legacy codebase: the baseline

On an existing project, the first ast-metrics lint can easily report hundreds of violations. You are not going to fix them all today, and they should not block your pipeline. Snapshot them instead:

ast-metrics baseline

This writes an .ast-metrics-baseline.yaml file recording every current violation. Commit it: from now on, ast-metrics lint (and ast-metrics ci) ignores the recorded violations and only fails on new ones.

Re-run ast-metrics baseline whenever you want to shrink the file as you pay off the debt. If you keep the file somewhere else, point the linter at it with ast-metrics lint --baseline=<path>.

Freezing the community boundaries

Three project rules read the communities the analysis finds on the dependency graph. They all pass when the project has fewer than two communities.

requirements:
  rules:
    architecture:
      no_community_cycles: true
      max_community_cross_share: 20
      no_cross_community_dependencies: true

no_community_cycles fails once per cycle and names the arrows to cut, lightest first. max_community_cross_share fails when more than the given percentage of the dependencies cross from one community to another, the shared kernel left aside. no_cross_community_dependencies fails on every single crossing, so it only makes sense with a baseline:

ast-metrics baseline   # accept today's crossings
ast-metrics lint       # fails only on a crossing added since

Each crossing is filed under the file of the class that depends, with the message Foo depends on Bar, which sits in another community. Community names stay out of the message on purpose: they change as the code moves, and the baseline recognizes an entry by rule, file and message. The communities page of the HTML report shows how many crossings are frozen and how many are new.

Baseline or review?

The two mechanisms are complementary. The baseline freezes today's violations in a committed file, so lint stays green on legacy code. ast-metrics review compares your branch with its base on the fly and needs no stored file: it is what gates your pull requests.