Skip to content

Releases: O6lvl4/codopsy

v2.3.1

Choose a tag to compare

@github-actions github-actions released this 26 Sep 00:52
3168574

Almide: module-qualified patterns parse

tree-sitter-almide is now at v0.3.1 (was v0.3.0). It reads two more shapes of current Almide:

  • module-qualified names in patterns: core.Stop, finish.Done(x), wire.Folded { content, .. } as match arms
  • if let expressions

Before this, a match arm on a module-qualified pattern was a parse error, and the function around it was measured from a partly unread tree. (#10)

v2.3.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 23:42
546683d

Unreadable files no longer pass as clean

A file the grammar could not read produced no functions and no issues, so it scored close to a perfect A and counted as a clean file in the grade distribution. A Go file that was 85.6% unparsed scored A (99).

  • A file with more than 20% of its bytes unparsed is now unanalyzed: it gets no score and is left out of the weighted average and the grade distribution. The summary counts these files, and -v shows what share of each one was unparsed. (#4)
  • --fail-on-unanalyzed makes the run exit 1 when any file is unanalyzed, so CI can refuse code the tool could not read. It is off by default. (#5)

Almide: current syntax parses

tree-sitter-almide is now at v0.3.0 (was v0.1.0). It reads the Almide being written today:

  • types: T?, module-qualified types, -> T! / -> T!E
  • expressions: fan { a, b } and the fan.* heads
  • strings: escaped quotes and // inside them

Before this, 18 of 39 files across three real Almide projects came back unanalyzed. All 39 are read now. (#9)

Go 1.27

  • Generic methods parse, through a tree-sitter-go fork pinned until the upstream change lands (#8 tracks going back to crates.io). (#6)
  • New rule go-generic-method: when go.mod declares a version below 1.27, generic methods are reported, as go vet's stdversion check would. (#7)

Fixes

  • max-depth counted every else if as one level deeper. A long else-if chain reported "nesting depth 5" where the code nests once. An else if now stays at the depth of the if it continues, as ESLint's max-depth counts it. This affects every language with else-if chains. On one Almide project, warnings went from 85 to 15, and all 15 that remain are real. (#9)
  • Almide else if chains stay flat in cognitive complexity, as JS, Rust and Lean chains already did. (#9)
  • unused-import ignored uses in TypeScript type positions, so an import used only as a type was reported unused. On one app, 82 of 83 reports were this false positive. (5626620)

This changes reported numbers. Scores go down where unreadable files used to pass as clean. They go up where long else-if chains were reported as deep nesting. A baseline recorded with 2.2.0 will show both kinds of change.

v2.2.0

Choose a tag to compare

@github-actions github-actions released this 08 Aug 11:42

Lean 4 support

codopsy now analyses Lean 4 (.lean) — 35 languages, 182 lint rules.

  • Cyclomatic and cognitive complexity for def / theorem / abbrev / example / instance, scored against Lean's own control flow: if then else, match arms, induction, by_cases, and the ∧ / ∨ connectives. else if chains stay flat instead of nesting.
  • 8 lint rules aimed at the two things that make a Lean file untrustworthy rather than merely ugly — proofs that are not finished, and declarations that widen what the kernel takes on faith:
Rule Default
no-sorry error
no-axiom warning
no-native-decide warning
no-unsafe warning
no-unlimited-heartbeats warning
no-partial-def info
no-dbg-trace info
no-debug-command info

Lean is macro-extensible, so no tree-sitter grammar reads every file. Measured over lean4 and Mathlib core sources, the grammar codopsy uses leaves ~6% of bytes unparsed; hand-written Lean parses essentially in full. What it cannot read is now reported rather than silently skipped — see the next section.

New rule: syntax-error (all languages, info)

A file the parser could not read produced no functions, no issues, and therefore a perfect score. It now reports how many regions were unreadable and what share of the file they cover, so an unparsed file can no longer pass as a clean one. One issue per file; disable it with "syntax-error": false like any other rule.

Complexity fix: keyword tokens were counted twice

Several tree-sitter grammars name a keyword token exactly like the node it opens — Ruby's if token inside an if node, JavaScript's function inside a function_declaration. Both matched the classification tables, so every such branch was counted twice and phantom (anonymous) functions appeared in reports. Only named nodes are classified now.

This changes reported numbers for Ruby, Crystal, JavaScript and Lua: complexity and function counts go down. A baseline recorded with 2.0.x will register the difference as an improvement.

Other fixes

  • --hotspots silently produced nothing unless the analysed directory was the repository root. Churn keys from git log are repo-root-relative; the comparison was built relative to the analysed directory, so the two never matched in a subdirectory.
  • --help still described codopsy as being "for TypeScript, JavaScript & Rust".
  • --max-complexity / --max-cognitive-complexity CLI defaults were hardcoded instead of reading the centralised defaults, so they could drift from the documented values.
  • score_complexity now honours the configured max-complexity / max-cognitive-complexity thresholds instead of the built-in ones (this landed after v2.0.1 and was never released).

Internal

The language registry is a single table per language, replacing three lists that had to stay in lockstep: a name array indexed by enum declaration order, a grammar match, and an extension map. Adding a language is now one row, and a new test asserts that all 35 grammars actually load and that every extension round-trips.

codopsy's own analysis of src is A (100/100), 0 issues.

Full Changelog: v2.0.1...v2.2.0

v2.0.1

Choose a tag to compare

@github-actions github-actions released this 11 May 05:42

Full Changelog: v2.0.0...v2.0.1

v1.2.0 - Almide Support

Choose a tag to compare

@O6lvl4 O6lvl4 released this 10 Mar 07:01

What's New

  • Almide language support — 25th language added via tree-sitter-almide grammar
  • Almide-specific AST handling: function_name node, test_declaration, for_in_expression, do_expression
  • Keyword logical operators (and/or) recognized for cognitive complexity scoring

Full language list: TypeScript, TSX, JavaScript, Rust, Go, Python, C, C++, Java, Ruby, C#, PHP, Scala, Haskell, Bash, HTML, CSS, JSON, OCaml, Swift, Lua, Zig, Elixir, YAML, Almide

codopsy v1.1.0

Choose a tag to compare

@O6lvl4 O6lvl4 released this 10 Mar 06:04

What's New

Added 5 new languages:

  • Swift (.swift)
  • Lua (.lua)
  • Zig (.zig)
  • Elixir (.ex, .exs)
  • YAML (.yml, .yaml)

Total: 24 languages supported.

Note: Kotlin and Dart are not yet supported due to tree-sitter grammar ABI incompatibility. Will be added when their crates are updated.

Install / Update

cargo install --git https://github.com/O6lvl4/codopsy.git

codopsy v1.0.0

Choose a tag to compare

@O6lvl4 O6lvl4 released this 10 Mar 05:58

codopsy v1.0.0

AST-level code quality analyzer for 19 languages.

Supported Languages

TypeScript, TSX, JavaScript, Rust, Go, Python, C, C++, Java, Ruby, C#, PHP, Scala, Haskell, Bash, HTML, CSS, JSON, OCaml

Features

  • Cyclomatic & cognitive complexity analysis per function
  • Language-specific lint rules — JS/TS: 11 rules, Rust: 6 rules
  • Threshold rules for all languages (max-lines, max-depth, max-params, max-complexity)
  • A–F quality scoring (complexity 35% + issues 40% + structure 25%)
  • Baseline tracking for quality degradation detection
  • Hotspot detection — complexity × git churn
  • Parallel analysis via rayon
  • Configurable via .codopsyrc.json

Install

cargo install --git https://github.com/O6lvl4/codopsy.git

Quick Start

codopsy analyze ./src          # Analyze a project
codopsy analyze ./src -v       # Verbose per-file output
codopsy analyze ./src --hotspots  # Show complexity hotspots
codopsy init                   # Generate .codopsyrc.json