ceplx

package module
v0.0.0-...-fc3da63 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: BSD-3-Clause Imports: 5 Imported by: 0

README

ceplx (pronounced cə̃pléx)

Cyclomatic and cognitive complexity calculator for CEL expressions.

Install

go install github.com/efd6/ceplx/cmd/ceplx@latest

Usage

ceplx [flags] [file ...]

Each file is treated as a single CEL expression. If no files are given, the expression is read from stdin. Comment lines (starting with // or #) and blank lines are stripped before parsing.

Flags
Flag Default Description
-cyclomatic true Print cyclomatic complexity
-cognitive true Print cognitive complexity
-over N -1 Only show expressions with complexity > N
-diag false Show per-node diagnostics for cognitive complexity
-json false Encode output as JSON
Examples
$ echo 'a && b ? [1,2].map(x, x > 0 ? x : -x) : c || d' | ceplx
<stdin>  cyclomatic=6 cognitive=7  a && b ? [1,2].map(x, x > 0 ? x : -x) : c || d
$ echo '[1,2,3].filter(x, x > 0 && x < 10)' | ceplx -json
[
  {
    "source": "[1,2,3].filter(x, x \u003e 0 \u0026\u0026 x \u003c 10)",
    "file": "\u003cstdin\u003e",
    "cyclomatic": 3,
    "cognitive": 2
  }
]
$ echo 'x ? (y ? 1 : 2) : 0' | ceplx -diag
<stdin>  cyclomatic=3 cognitive=3  x ? (y ? 1 : 2) : 0
  +1 (nesting=0) ?:
  +2 (nesting=1) ?:

Metrics

Cyclomatic complexity

Base complexity is 1. Each of the following adds 1:

  • Ternary conditional (?:)
  • Logical && or ||
  • Comprehension (.map, .filter, .exists, .all, .as, .parallel, etc.)
Cognitive complexity

Follows the SonarSource cognitive complexity model, adapted for CEL:

  • Ternary: nesting+1 increment; both branches increase nesting.
  • Chained ternary in else position: flat +1 (else-if discount).
  • Comprehension: nesting+1 increment; loop body increases nesting.
  • Logical operators: +1 per sequence of identical operators; switching between && and || adds another +1.

Macro handling

CEL macros (.map, .filter, .exists, etc.) expand into synthetic AST nodes during parsing. Naively walking the expanded tree would inflate complexity scores with compiler-generated ternaries and loops that the programmer never wrote.

ceplx uses CEL's macro call tracking (SourceInfo.MacroCalls) to walk user-visible source structure rather than synthetic expansions. For accurate results, parse with macro call tracking enabled.

The CLI registers all mito library extensions, including custom macros like .as and .parallel, so it handles the full CEL dialect used by Elastic integrations.

Library

import "github.com/efd6/ceplx"

a, err := ceplx.Parse("a && b ? x.map(v, v+1) : c")
if err != nil {
    log.Fatal(err)
}
fmt.Println("cyclomatic:", ceplx.Cyclomatic(a))
fmt.Println("cognitive:", ceplx.Cognitive(a))

score, diags := ceplx.CognitiveWithDiagnostics(a)
for _, d := range diags {
    fmt.Printf("  +%d (nesting=%d) %s\n", d.Inc, d.Nesting, d.Text)
}

ceplx.Parse registers standard CEL macros and enables macro call tracking. Pass additional parser.Option values to register custom macros.

Documentation

Overview

Package ceplx calculates cyclomatic and cognitive complexities of CEL expressions.

CEL is a purely expression-based language — there are no statements or function declarations. The unit of analysis is a single expression.

In the CEL AST all operators are function calls with well-known names (e.g. "_&&_", "_?_:_") and macros like .map, .filter, .exists desugar into ComprehensionKind nodes. This package uses SourceInfo.MacroCalls to walk user-visible source structure rather than synthetic macro expansions.

For accurate results, the AST should be parsed with macro call tracking enabled (cel.EnableMacroCallTracking or parser.PopulateMacroCalls(true)). Without it, synthetic nodes inside macro expansions may inflate scores.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Cognitive

func Cognitive(a *ast.AST) int

Cognitive returns the cognitive complexity of a CEL expression.

The rules follow the gocognit model adapted for CEL:

  • Ternary (_?_:_): nesting+1 increment; both branches increase nesting
  • Chained ternary in else position: flat +1 (else-if discount)
  • Comprehension: nesting+1 increment; loop body increases nesting
  • Logical operators: +1 per sequence of identical operators; switching between && and || adds another +1

func Cyclomatic

func Cyclomatic(a *ast.AST) int

Cyclomatic returns the cyclomatic complexity of a CEL expression.

The base complexity is 1. Each of the following adds 1:

  • ternary conditional (_?_:_)
  • logical && or ||
  • comprehension (macro-expanded .map, .filter, .exists, .all, etc.)

func Parse

func Parse(src string, opts ...parser.Option) (*ast.AST, error)

Parse parses a CEL expression with macro call tracking enabled, returning an AST suitable for complexity analysis.

Standard CEL macros (has, all, exists, exists_one, map, filter) are registered by default. Additional parser options can be passed to register custom macros or enable additional syntax features.

Types

type Diagnostic

type Diagnostic struct {
	ExprID  int64  `json:"expr_id"`
	Inc     int    `json:"inc"`
	Nesting int    `json:"nesting"`
	Text    string `json:"text"`
}

Diagnostic records a single complexity increment with its cause.

func CognitiveWithDiagnostics

func CognitiveWithDiagnostics(a *ast.AST) (int, []Diagnostic)

CognitiveWithDiagnostics is like Cognitive but also returns per-node diagnostic records explaining each increment.

Directories

Path Synopsis
cmd
ceplx command
Command ceplx reports the cyclomatic and cognitive complexity of CEL expressions.
Command ceplx reports the cyclomatic and cognitive complexity of CEL expressions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL