Skip to content

Commit 0f08ba4

Browse files
committed
feat(languages): add F5 iRules language support
Add the `Irules` language (an F5 iRules / Tcl-scripting dialect) via the crates.io-pinned `tree-sitter-irules` =0.1.1 grammar, gated behind a new `irules` Cargo feature (enabled by `all-languages`). `.irule` / `.irules`. Wiring & public API: - enums codegen (Cargo.toml, languages.rs, macros.rs) plus the generated src/languages/language_irules.rs; dispatch-coverage guard bumped to 22. - Re-export IrulesCode / IrulesParser from lib.rs (additive new language, minor bump per STABILITY.md); exhaustive big-code-analysis-py LANG arm. Behaviour: - Checker / Getter / Alterator impls. `when` / `on` / `trap` event handlers and `proc` definitions are function spaces, so per-handler metrics are reported (handlers count as functions in nom). - Real metric impls: ABC, Cognitive, Cyclomatic (dedicated switch/arm plus the `and`/`or` keyword operators), Exit (return-by-command-name, iRules has no return node), Halstead, LoC, NArgs. The remaining metrics use the shared defaults. Tests & docs: - Rust-parity per-metric tests, a malformed-input synthetic-Unit-root test, a self-contained end-to-end integration test (tests/irules_test.rs driving the public analyze() API), and cross-language cyclomatic/cognitive parity entries vs Rust/Java/Tcl. - Supported-languages list, cargo-features table, and CHANGELOG entry. - HTML report gains an `irules` colour palette entry. Halstead operand double-count fix: iRules' variable_substitution inner leaf is the named `Id` (not Tcl's anonymous `Id2`), so every `$var` was counted twice. get_op_type now excludes `Id` whose parent is a VariableSubstitution; affected Halstead test values corrected. .bca-baseline.toml refreshed for the added code's file-level metric growth (per-function complexity stays within thresholds).
1 parent 9787682 commit 0f08ba4

40 files changed

Lines changed: 2266 additions & 128 deletions

.bca-baseline.toml

Lines changed: 116 additions & 102 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ for historical reference.
2323

2424
### Added
2525

26+
- Support for **F5 iRules** source files (`.irule`, `.irules`), a Tcl
27+
scripting dialect, via the
28+
[`tree-sitter-irules`](https://crates.io/crates/tree-sitter-irules)
29+
grammar. Adds the `Irules` `LANG` variant and the `IrulesCode` /
30+
`IrulesParser` re-exports, gated behind a new `irules` Cargo feature
31+
(enabled by `all-languages`). `when EVENT { … }` event handlers and
32+
`proc` definitions are treated as function spaces, so per-handler
33+
metrics are reported (the grammar's `on` / `trap` handler nodes are
34+
handled defensively but parse as ordinary commands in practice). Real
35+
implementations are provided for ABC,
36+
cognitive, cyclomatic (including the dedicated `switch`/`switch_arm`
37+
node and the `and`/`or` keyword operators), exit, Halstead, LoC, and
38+
NArgs; the remaining metrics use the shared defaults. Additive new
39+
language — minor bump per [STABILITY.md](./STABILITY.md).
2640
- Cyclomatic complexity's counting of Rust's `?` operator (the
2741
`try_expression` grammar node) is now configurable
2842
([#409](https://github.com/dekobon/big-code-analysis/issues/409)).

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ tree-sitter-c-sharp = "=0.23.5"
4646
tree-sitter-elixir = "=0.3.5"
4747
tree-sitter-go = "=0.25.0"
4848
dekobon-tree-sitter-groovy = "=0.2.0"
49+
tree-sitter-irules = "=0.1.1"
4950
tree-sitter-java = "=0.23.5"
5051
tree-sitter-javascript = "=0.25.0"
5152
tree-sitter-kotlin-ng = "1.1.0"
@@ -145,6 +146,7 @@ tree-sitter-c-sharp = { workspace = true, optional = true }
145146
tree-sitter-elixir = { workspace = true, optional = true }
146147
tree-sitter-go = { workspace = true, optional = true }
147148
dekobon-tree-sitter-groovy = { workspace = true, optional = true }
149+
tree-sitter-irules = { workspace = true, optional = true }
148150
tree-sitter-java = { workspace = true, optional = true }
149151
tree-sitter-javascript = { workspace = true, optional = true }
150152
tree-sitter-kotlin-ng = { workspace = true, optional = true }
@@ -188,6 +190,7 @@ all-languages = [
188190
"elixir",
189191
"go",
190192
"groovy",
193+
"irules",
191194
"java",
192195
"javascript",
193196
"kotlin",
@@ -218,6 +221,7 @@ csharp = ["dep:tree-sitter-c-sharp"]
218221
elixir = ["dep:tree-sitter-elixir"]
219222
go = ["dep:tree-sitter-go"]
220223
groovy = ["dep:dekobon-tree-sitter-groovy"]
224+
irules = ["dep:tree-sitter-irules"]
221225
java = ["dep:tree-sitter-java"]
222226
javascript = ["dep:tree-sitter-javascript"]
223227
kotlin = ["dep:tree-sitter-kotlin-ng"]

big-code-analysis-book/src/languages.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This is the list of programming languages parsed by
1313
- [x] Preproc
1414
- [x] Go
1515
- [x] Groovy
16+
- [x] Irules
1617
- [x] Java
1718
- [x] JavaScript
1819
- [x] Kotlin

big-code-analysis-book/src/library/cargo-features.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ per-language pipeline depends on).
4545
| `elixir` | `tree-sitter-elixir` |
4646
| `go` | `tree-sitter-go` |
4747
| `groovy` | `dekobon-tree-sitter-groovy` |
48+
| `irules` | `tree-sitter-irules` (F5 iRules, a Tcl dialect) |
4849
| `java` | `tree-sitter-java` |
4950
| `javascript` | `tree-sitter-javascript` |
5051
| `kotlin` | `tree-sitter-kotlin-ng` |

big-code-analysis-cli/src/html_report.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ section.lang-bash{background:rgba(96,128,96,0.08);border-left-color:rgba(96,128,
9191
section.lang-perl{background:rgba(180,120,60,0.08);border-left-color:rgba(180,120,60,0.55)}\
9292
section.lang-lua{background:rgba(0,86,180,0.08);border-left-color:rgba(0,86,180,0.55)}\
9393
section.lang-tcl{background:rgba(160,90,140,0.08);border-left-color:rgba(160,90,140,0.55)}\
94+
section.lang-irules{background:rgba(200,70,120,0.08);border-left-color:rgba(200,70,120,0.55)}\
9495
section.lang-ruby{background:rgba(204,52,45,0.08);border-left-color:rgba(204,52,45,0.55)}\
9596
section.lang-elixir{background:rgba(110,73,153,0.08);border-left-color:rgba(110,73,153,0.55)}\
9697
section.lang-other{background:rgba(127,127,127,0.06);border-left-color:rgba(127,127,127,0.45)}\
@@ -109,6 +110,7 @@ section.lang-bash{background:rgba(96,128,96,0.18)}\
109110
section.lang-perl{background:rgba(180,120,60,0.18)}\
110111
section.lang-lua{background:rgba(0,86,180,0.20)}\
111112
section.lang-tcl{background:rgba(160,90,140,0.20)}\
113+
section.lang-irules{background:rgba(200,70,120,0.20)}\
112114
section.lang-ruby{background:rgba(204,52,45,0.18)}\
113115
section.lang-elixir{background:rgba(110,73,153,0.20)}\
114116
section.lang-other{background:rgba(200,200,200,0.10)}\
@@ -156,6 +158,7 @@ const LANGUAGE_PALETTE: &[(&str, &str)] = &[
156158
("perl", "perl"),
157159
("lua", "lua"),
158160
("tcl", "tcl"),
161+
("irules", "irules"),
159162
("ruby", "ruby"),
160163
("elixir", "elixir"),
161164
];

big-code-analysis-cli/src/snapshots/big_code_analysis_cli__html_report__tests__html_report_two_lang.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ expression: out
77
<head>
88
<meta charset="utf-8">
99
<title>Code Quality Metrics Summary — big-code-analysis</title>
10-
<style>body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;margin:1.5rem;color:#222;background:#fafafa}h1{font-size:1.4rem;margin:0 0 0.5rem}h2{font-size:1.15rem;margin:1.5rem 0 0.5rem;border-bottom:1px solid #ccc;padding-bottom:0.25rem}h3{font-size:1rem;margin:1rem 0 0.4rem;color:#444}section{margin-top:2rem}section.lang-section{padding:0.5rem 1rem;border-radius:4px;border-left:3px solid rgba(127,127,127,0.35)}section.lang-section>h2{margin-top:0.25rem}section.lang-rust{background:rgba(222,128,82,0.08);border-left-color:rgba(222,128,82,0.55)}section.lang-python{background:rgba(58,118,196,0.08);border-left-color:rgba(58,118,196,0.55)}section.lang-javascript{background:rgba(229,202,71,0.10);border-left-color:rgba(229,202,71,0.65)}section.lang-typescript{background:rgba(46,116,194,0.08);border-left-color:rgba(46,116,194,0.55)}section.lang-java{background:rgba(196,69,60,0.08);border-left-color:rgba(196,69,60,0.55)}section.lang-kotlin{background:rgba(193,71,167,0.08);border-left-color:rgba(193,71,167,0.55)}section.lang-go{background:rgba(0,173,181,0.08);border-left-color:rgba(0,173,181,0.55)}section.lang-cpp{background:rgba(120,80,180,0.08);border-left-color:rgba(120,80,180,0.55)}section.lang-csharp{background:rgba(83,150,80,0.08);border-left-color:rgba(83,150,80,0.55)}section.lang-php{background:rgba(98,113,178,0.08);border-left-color:rgba(98,113,178,0.55)}section.lang-bash{background:rgba(96,128,96,0.08);border-left-color:rgba(96,128,96,0.55)}section.lang-perl{background:rgba(180,120,60,0.08);border-left-color:rgba(180,120,60,0.55)}section.lang-lua{background:rgba(0,86,180,0.08);border-left-color:rgba(0,86,180,0.55)}section.lang-tcl{background:rgba(160,90,140,0.08);border-left-color:rgba(160,90,140,0.55)}section.lang-ruby{background:rgba(204,52,45,0.08);border-left-color:rgba(204,52,45,0.55)}section.lang-elixir{background:rgba(110,73,153,0.08);border-left-color:rgba(110,73,153,0.55)}section.lang-other{background:rgba(127,127,127,0.06);border-left-color:rgba(127,127,127,0.45)}@media (prefers-color-scheme:dark){section.lang-rust{background:rgba(222,128,82,0.16)}section.lang-python{background:rgba(58,118,196,0.18)}section.lang-javascript{background:rgba(229,202,71,0.16)}section.lang-typescript{background:rgba(46,116,194,0.18)}section.lang-java{background:rgba(196,69,60,0.18)}section.lang-kotlin{background:rgba(193,71,167,0.18)}section.lang-go{background:rgba(0,173,181,0.18)}section.lang-cpp{background:rgba(120,80,180,0.20)}section.lang-csharp{background:rgba(83,150,80,0.18)}section.lang-php{background:rgba(98,113,178,0.20)}section.lang-bash{background:rgba(96,128,96,0.18)}section.lang-perl{background:rgba(180,120,60,0.18)}section.lang-lua{background:rgba(0,86,180,0.20)}section.lang-tcl{background:rgba(160,90,140,0.20)}section.lang-ruby{background:rgba(204,52,45,0.18)}section.lang-elixir{background:rgba(110,73,153,0.20)}section.lang-other{background:rgba(200,200,200,0.10)}}.summary{font-size:0.9rem;color:#444;margin-bottom:0.5rem}.summary strong{color:#222}.summary p{margin:0.2rem 0}.note{font-size:0.85rem;color:#555;margin:0.4rem 0}ul{margin:0.4rem 0 0.4rem 1.2rem;padding:0}li{margin:0.15rem 0;font-size:0.9rem}table.hotspot{border-collapse:collapse;width:100%;font-size:0.85rem;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,0.06);margin-bottom:0.5rem}table.hotspot th,table.hotspot td{padding:0.4rem 0.6rem;border-bottom:1px solid #e5e5e5;text-align:left;white-space:nowrap}table.hotspot th{background:#f0f0f0;cursor:pointer;user-select:none;font-weight:600}table.hotspot th:hover{background:#e5e5e5}table.hotspot th[aria-sort=ascending]::after{content:" \2191"}table.hotspot th[aria-sort=descending]::after{content:" \2193"}table.hotspot tr:nth-child(even) td{background:#fafafa}table.hotspot td.numeric{text-align:right;font-variant-numeric:tabular-nums}</style>
10+
<style>body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;margin:1.5rem;color:#222;background:#fafafa}h1{font-size:1.4rem;margin:0 0 0.5rem}h2{font-size:1.15rem;margin:1.5rem 0 0.5rem;border-bottom:1px solid #ccc;padding-bottom:0.25rem}h3{font-size:1rem;margin:1rem 0 0.4rem;color:#444}section{margin-top:2rem}section.lang-section{padding:0.5rem 1rem;border-radius:4px;border-left:3px solid rgba(127,127,127,0.35)}section.lang-section>h2{margin-top:0.25rem}section.lang-rust{background:rgba(222,128,82,0.08);border-left-color:rgba(222,128,82,0.55)}section.lang-python{background:rgba(58,118,196,0.08);border-left-color:rgba(58,118,196,0.55)}section.lang-javascript{background:rgba(229,202,71,0.10);border-left-color:rgba(229,202,71,0.65)}section.lang-typescript{background:rgba(46,116,194,0.08);border-left-color:rgba(46,116,194,0.55)}section.lang-java{background:rgba(196,69,60,0.08);border-left-color:rgba(196,69,60,0.55)}section.lang-kotlin{background:rgba(193,71,167,0.08);border-left-color:rgba(193,71,167,0.55)}section.lang-go{background:rgba(0,173,181,0.08);border-left-color:rgba(0,173,181,0.55)}section.lang-cpp{background:rgba(120,80,180,0.08);border-left-color:rgba(120,80,180,0.55)}section.lang-csharp{background:rgba(83,150,80,0.08);border-left-color:rgba(83,150,80,0.55)}section.lang-php{background:rgba(98,113,178,0.08);border-left-color:rgba(98,113,178,0.55)}section.lang-bash{background:rgba(96,128,96,0.08);border-left-color:rgba(96,128,96,0.55)}section.lang-perl{background:rgba(180,120,60,0.08);border-left-color:rgba(180,120,60,0.55)}section.lang-lua{background:rgba(0,86,180,0.08);border-left-color:rgba(0,86,180,0.55)}section.lang-tcl{background:rgba(160,90,140,0.08);border-left-color:rgba(160,90,140,0.55)}section.lang-irules{background:rgba(200,70,120,0.08);border-left-color:rgba(200,70,120,0.55)}section.lang-ruby{background:rgba(204,52,45,0.08);border-left-color:rgba(204,52,45,0.55)}section.lang-elixir{background:rgba(110,73,153,0.08);border-left-color:rgba(110,73,153,0.55)}section.lang-other{background:rgba(127,127,127,0.06);border-left-color:rgba(127,127,127,0.45)}@media (prefers-color-scheme:dark){section.lang-rust{background:rgba(222,128,82,0.16)}section.lang-python{background:rgba(58,118,196,0.18)}section.lang-javascript{background:rgba(229,202,71,0.16)}section.lang-typescript{background:rgba(46,116,194,0.18)}section.lang-java{background:rgba(196,69,60,0.18)}section.lang-kotlin{background:rgba(193,71,167,0.18)}section.lang-go{background:rgba(0,173,181,0.18)}section.lang-cpp{background:rgba(120,80,180,0.20)}section.lang-csharp{background:rgba(83,150,80,0.18)}section.lang-php{background:rgba(98,113,178,0.20)}section.lang-bash{background:rgba(96,128,96,0.18)}section.lang-perl{background:rgba(180,120,60,0.18)}section.lang-lua{background:rgba(0,86,180,0.20)}section.lang-tcl{background:rgba(160,90,140,0.20)}section.lang-irules{background:rgba(200,70,120,0.20)}section.lang-ruby{background:rgba(204,52,45,0.18)}section.lang-elixir{background:rgba(110,73,153,0.20)}section.lang-other{background:rgba(200,200,200,0.10)}}.summary{font-size:0.9rem;color:#444;margin-bottom:0.5rem}.summary strong{color:#222}.summary p{margin:0.2rem 0}.note{font-size:0.85rem;color:#555;margin:0.4rem 0}ul{margin:0.4rem 0 0.4rem 1.2rem;padding:0}li{margin:0.15rem 0;font-size:0.9rem}table.hotspot{border-collapse:collapse;width:100%;font-size:0.85rem;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,0.06);margin-bottom:0.5rem}table.hotspot th,table.hotspot td{padding:0.4rem 0.6rem;border-bottom:1px solid #e5e5e5;text-align:left;white-space:nowrap}table.hotspot th{background:#f0f0f0;cursor:pointer;user-select:none;font-weight:600}table.hotspot th:hover{background:#e5e5e5}table.hotspot th[aria-sort=ascending]::after{content:" \2191"}table.hotspot th[aria-sort=descending]::after{content:" \2193"}table.hotspot tr:nth-child(even) td{background:#fafafa}table.hotspot td.numeric{text-align:right;font-variant-numeric:tabular-nums}</style>
1111
</head>
1212
<body>
1313
<h1>Code Quality Metrics Summary</h1>

big-code-analysis-py/src/language.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub(crate) fn lang_to_name(lang: LANG) -> &'static str {
5050
LANG::Elixir => "elixir",
5151
LANG::Go => "go",
5252
LANG::Groovy => "groovy",
53+
LANG::Irules => "irules",
5354
LANG::Java => "java",
5455
// `Javascript` has no extensions and is filtered out of
5556
// `public_languages`, so this arm is never reached through

enums/Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)