energy-state-analyzer 0.18.1 โ 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/README.md +6 -3
- package/anonymous-callables-plan.md +245 -0
- package/dist/cli.js +1 -1
- package/docs/agent-integration.md +4 -4
- package/docs/detectors/README.md +1 -1
- package/docs/detectors/cognitive-complexity.md +7 -5
- package/docs/detectors/cyclomatic-complexity.md +6 -3
- package/docs/detectors/file-coherence.md +5 -3
- package/docs/detectors/parameter-explosion.md +9 -1
- package/docs/detectors/primitive-obsession.md +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
last_commit_released:
|
|
2
|
+
last_commit_released: c6607b76a5705d83e19bc3198c7f012a6c34692c
|
|
3
3
|
name: energy-state-analyzer
|
|
4
4
|
updaters:
|
|
5
5
|
- command: npm version {version} --no-git-tag-version --allow-same-version
|
|
@@ -14,6 +14,24 @@ All notable changes to the "energy-state-analyzer" extension are generated by
|
|
|
14
14
|
[EasyBuild.ShipIt](https://github.com/easybuild-org/EasyBuild.ShipIt) from
|
|
15
15
|
[Conventional Commits](https://www.conventionalcommits.org/).
|
|
16
16
|
|
|
17
|
+
## 0.19.1 - 2026-09-17
|
|
18
|
+
|
|
19
|
+
### ๐ Bug Fixes
|
|
20
|
+
|
|
21
|
+
* Give boolean blindness a targeted primitive-obsession message (#156) ([bafb1ce](https://github.com/cardamomcode/energy-state-analyzer/commit/bafb1cef928b09870583d59e31207ecd2b22e96b))
|
|
22
|
+
* Add typed format specifiers to detector messages (#158) ([c6607b7](https://github.com/cardamomcode/energy-state-analyzer/commit/c6607b76a5705d83e19bc3198c7f012a6c34692c))
|
|
23
|
+
|
|
24
|
+
<strong><small>[View changes on Github](https://github.com/cardamomcode/energy-state-analyzer/compare/d638fb6b75608731fb0ff06d12717a1a0c9be442..c6607b76a5705d83e19bc3198c7f012a6c34692c)</small></strong>
|
|
25
|
+
|
|
26
|
+
## 0.19.0 - 2026-09-16
|
|
27
|
+
|
|
28
|
+
### ๐ Features
|
|
29
|
+
|
|
30
|
+
* Introduce anonymous callable model (#153) ([c3129f3](https://github.com/cardamomcode/energy-state-analyzer/commit/c3129f3427247d32d056bb6035e0efbd55017bea))
|
|
31
|
+
* Integrate bound callables with coherence (#155) ([d638fb6](https://github.com/cardamomcode/energy-state-analyzer/commit/d638fb6b75608731fb0ff06d12717a1a0c9be442))
|
|
32
|
+
|
|
33
|
+
<strong><small>[View changes on Github](https://github.com/cardamomcode/energy-state-analyzer/compare/00fd3e6fbca7cbfa1fec8417ffe5ee805b0960c5..d638fb6b75608731fb0ff06d12717a1a0c9be442)</small></strong>
|
|
34
|
+
|
|
17
35
|
## 0.18.1 - 2026-09-15
|
|
18
36
|
|
|
19
37
|
### ๐ Bug Fixes
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Real-time analysis of the active Python, F#, TypeScript, Kotlin, C++, or C# file
|
|
|
19
19
|
- [Recovery Dominance](docs/detectors/recovery-dominance.md), recovery policy that dominates a function.
|
|
20
20
|
- [Oversized Recovery Block](docs/detectors/oversized-recovery-block.md), individual handlers or cleanup bodies exceeding their line limit.
|
|
21
21
|
- [Inversion opportunities](docs/detectors/inversion-opportunities.md), nested conditionals that could be guard clauses.
|
|
22
|
-
- [Primitive obsession](docs/detectors/primitive-obsession.md), strings/numbers standing in for a real type.
|
|
22
|
+
- [Primitive obsession](docs/detectors/primitive-obsession.md), strings/numbers standing in for a real type, and boolean blindness.
|
|
23
23
|
- [Match opportunities](docs/detectors/match-opportunities.md), if/elif chains that could be a match/switch.
|
|
24
24
|
- [Logical operator as control flow](docs/detectors/logical-operator-control-flow.md), an `if` hidden behind `&&`/`||`.
|
|
25
25
|
- [Parse, don't validate](docs/detectors/parse-dont-validate.md), checks whose successful result does not preserve the domain constraint.
|
|
@@ -148,6 +148,9 @@ To exclude files/folders (e.g. test fixtures, generated code) from both the exte
|
|
|
148
148
|
|
|
149
149
|
## Known Issues
|
|
150
150
|
|
|
151
|
-
-
|
|
152
|
-
|
|
151
|
+
- Cyclomatic complexity, cognitive complexity, and parameter count analyze anonymous callables in
|
|
152
|
+
all supported languages. File-coherence analysis still counts only named definitions and methods;
|
|
153
|
+
direct anonymous-callable bindings are not yet treated as file or class responsibilities.
|
|
154
|
+
- C++ analysis is syntax-only: it does not preprocess macros, resolve includes, instantiate
|
|
155
|
+
templates, or perform type checking. Macro-generated callable syntax is therefore invisible.
|
|
153
156
|
- Several detectors have per-language gaps beyond the above, see the "Known limitations" section of the relevant [detector doc](docs/detectors/README.md).
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Anonymous Callable Analysis Plan
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Analyze anonymous callables as real function boundaries across Python, F#, TypeScript, Kotlin,
|
|
6
|
+
C++, and C# without accidentally broadening unrelated detectors or making file-coherence results
|
|
7
|
+
noisy.
|
|
8
|
+
|
|
9
|
+
The completed work should cover:
|
|
10
|
+
|
|
11
|
+
- cyclomatic complexity;
|
|
12
|
+
- cognitive complexity;
|
|
13
|
+
- parameter count; and
|
|
14
|
+
- the function-related parts of file coherence.
|
|
15
|
+
|
|
16
|
+
TypeScript function expressions and C# anonymous methods are included with arrow functions and
|
|
17
|
+
lambdas so equivalent anonymous-function syntax does not retain the same gap under another name.
|
|
18
|
+
|
|
19
|
+
## Current state
|
|
20
|
+
|
|
21
|
+
- [x] Confirm all six supported language adapters and their anonymous-callable grammar nodes.
|
|
22
|
+
- [x] Parse representative anonymous callables with every bundled grammar.
|
|
23
|
+
- [x] Verify the existing cyclomatic and cognitive scorers can score an anonymous-callable node
|
|
24
|
+
directly.
|
|
25
|
+
- [x] Identify the shared `IsFunctionDefinition` predicate as a boundary used by detectors beyond
|
|
26
|
+
the four in scope.
|
|
27
|
+
- [x] Implement anonymous-callable reporting for complexity and parameter count.
|
|
28
|
+
- [x] Remove or narrow the corresponding documented limitations for the first behavior change.
|
|
29
|
+
|
|
30
|
+
The existing scorers are not the main obstacle. The important design work is distinguishing a
|
|
31
|
+
callable boundary from a named function definition and distinguishing file/class responsibilities
|
|
32
|
+
from inline callbacks.
|
|
33
|
+
|
|
34
|
+
## Intended semantics
|
|
35
|
+
|
|
36
|
+
### Callable roles
|
|
37
|
+
|
|
38
|
+
Use one shared callable representation with enough information to distinguish:
|
|
39
|
+
|
|
40
|
+
1. **Named definition** โ an existing named function, method, constructor, or supported local
|
|
41
|
+
function.
|
|
42
|
+
2. **Bound anonymous callable** โ an anonymous function assigned directly to a module-level name or
|
|
43
|
+
class member, such as `export const parse = value => ...`.
|
|
44
|
+
3. **Inline anonymous callable** โ a callback or returned closure, such as
|
|
45
|
+
`items.map(value => ...)`.
|
|
46
|
+
|
|
47
|
+
The exact F# type and field names may change during implementation, but the distinction must stay
|
|
48
|
+
explicit rather than being reconstructed independently inside each detector.
|
|
49
|
+
|
|
50
|
+
### Detector behavior
|
|
51
|
+
|
|
52
|
+
- **Cyclomatic complexity:** report every anonymous callable independently. Decisions inside a
|
|
53
|
+
nested anonymous callable must not be folded into the enclosing callable's McCabe graph.
|
|
54
|
+
- **Cognitive complexity:** report every anonymous callable independently. Preserve the current
|
|
55
|
+
behavior where a nested closure's body also contributes to its enclosing callable at an
|
|
56
|
+
additional nesting level. These are independent scores and must not be summed as a file total.
|
|
57
|
+
- **Parameter count:** report every anonymous callable, including inline callbacks, using the same
|
|
58
|
+
configured thresholds as named functions.
|
|
59
|
+
- **File coherence:** count only named definitions and anonymous callables bound at a module or
|
|
60
|
+
class boundary. Do not count inline callbacks or function-local callable variables as additional
|
|
61
|
+
file-level responsibilities.
|
|
62
|
+
- **Class coherence:** treat a callable assigned directly to a class member as method-like when the
|
|
63
|
+
language uses that idiom. Do not treat callbacks nested inside a method as more methods on the
|
|
64
|
+
class.
|
|
65
|
+
- **Other detectors:** preserve their current named-function behavior unless a separate, explicit
|
|
66
|
+
review shows that anonymous callables belong in their scope.
|
|
67
|
+
|
|
68
|
+
### Syntax-only limitations to retain
|
|
69
|
+
|
|
70
|
+
- Do not infer types from compiler or type-checker information.
|
|
71
|
+
- Kotlin lambdas without an explicit parameter list may use implicit `it`; because syntax alone
|
|
72
|
+
cannot determine the expected function arity, count only parameters explicitly present in the
|
|
73
|
+
syntax tree.
|
|
74
|
+
- C++ macro-expanded code remains invisible without preprocessing.
|
|
75
|
+
- Anonymous-callable binding names and class roles are recognized only from direct syntax; aliases,
|
|
76
|
+
returned closures, and assignments through intermediate expressions are not resolved.
|
|
77
|
+
|
|
78
|
+
## Phase 1: Introduce the callable boundary
|
|
79
|
+
|
|
80
|
+
- [x] Add a grammar-neutral callable role/type in `src/Core/LanguageAdapter.fs`.
|
|
81
|
+
- [x] Expose adapter hooks that can classify a node as a callable and return its analysis view.
|
|
82
|
+
- [x] Include an anchor, body, role, optional binding name, and parameter nodes in that view.
|
|
83
|
+
- [x] Preserve `IsFunctionDefinition` for detectors that intentionally remain named-function-only,
|
|
84
|
+
or replace it with explicitly named predicates whose consumers retain the same behavior.
|
|
85
|
+
- [x] Replace the fixed single `NodeTypes.Parameters` assumption for callable analysis with
|
|
86
|
+
adapter-provided parameter nodes.
|
|
87
|
+
- [x] Preserve F# mutually recursive `and`-binding decomposition into independent logical heads.
|
|
88
|
+
- [x] Add or update Agent Decision Comments explaining why callable role is separate from syntax
|
|
89
|
+
node type and why unrelated detectors are not broadened.
|
|
90
|
+
- [x] Add shared test helpers for locating anonymous-callable nodes and checking their source ranges.
|
|
91
|
+
|
|
92
|
+
### Phase 1 language adapters
|
|
93
|
+
|
|
94
|
+
- [x] Python: recognize `lambda` and `lambda_parameters`.
|
|
95
|
+
- [x] F#: recognize `fun_expression` and reuse `argument_patterns`.
|
|
96
|
+
- [x] TypeScript: recognize `arrow_function` and `function_expression`; support parenthesized and
|
|
97
|
+
bare arrow parameters.
|
|
98
|
+
- [x] Kotlin: recognize `lambda_literal` and explicit `lambda_parameters` whose children are
|
|
99
|
+
`variable_declaration` nodes.
|
|
100
|
+
- [x] C++: recognize `lambda_expression`, excluding the capture list from parameter count.
|
|
101
|
+
- [x] C#: recognize `lambda_expression` and `anonymous_method_expression`; support
|
|
102
|
+
`parameter_list` and single `implicit_parameter` forms.
|
|
103
|
+
- [x] Confirm every new fixture parses without missing or error nodes.
|
|
104
|
+
|
|
105
|
+
## Phase 2: Complexity reporting
|
|
106
|
+
|
|
107
|
+
### Cyclomatic complexity work
|
|
108
|
+
|
|
109
|
+
- [x] Traverse all callable views as independently reportable roots.
|
|
110
|
+
- [x] Stop a callable's graph and hotspot traversal at every nested callable boundary.
|
|
111
|
+
- [x] Ensure a nested anonymous callable is reported separately when it crosses a threshold.
|
|
112
|
+
- [x] Add a regression proving branches in an inline callback do not inflate the enclosing named
|
|
113
|
+
function's cyclomatic score.
|
|
114
|
+
- [x] Add medium/high threshold-boundary scenarios for anonymous callables in all six languages.
|
|
115
|
+
- [x] Verify switch/match/when branch counts and boolean operators retain their current scoring.
|
|
116
|
+
|
|
117
|
+
### Cognitive complexity work
|
|
118
|
+
|
|
119
|
+
- [x] Traverse all callable views as independently reportable roots.
|
|
120
|
+
- [x] Score an anonymous root from nesting zero for its own diagnostic.
|
|
121
|
+
- [x] Preserve the current additional nesting applied when that closure is read inside an enclosing
|
|
122
|
+
callable.
|
|
123
|
+
- [x] Add a regression proving a nested closure can have an independent score while still
|
|
124
|
+
contributing to its enclosing callable.
|
|
125
|
+
- [x] Add exact-score, hotspot-total, and threshold-boundary scenarios for all six languages.
|
|
126
|
+
- [x] Reuse the cached fixture/threshold test pattern so the expanded matrix does not reintroduce
|
|
127
|
+
parallel test timeouts.
|
|
128
|
+
|
|
129
|
+
## Phase 3: Parameter-count reporting
|
|
130
|
+
|
|
131
|
+
- [x] Count explicit anonymous-callable parameters through the new adapter hook.
|
|
132
|
+
- [x] Anchor diagnostics at the anonymous callable or its direct binding, consistently across hosts.
|
|
133
|
+
- [x] Cover clean, medium, and high examples for every language.
|
|
134
|
+
- [x] Cover TypeScript and C# single-parameter shorthand.
|
|
135
|
+
- [x] Cover default, optional, rest, or variadic forms where the existing language adapter already
|
|
136
|
+
counts the equivalent named-function form.
|
|
137
|
+
- [x] Confirm captures in C++ and implicit Kotlin `it` do not become declared parameters.
|
|
138
|
+
- [x] Ensure F# `let f = fun ...` and inline `fun ...` expressions both work.
|
|
139
|
+
- [x] Confirm existing named-function and F# `and`-binding parameter tests remain unchanged.
|
|
140
|
+
|
|
141
|
+
## Phase 4: File-coherence integration
|
|
142
|
+
|
|
143
|
+
Implement this in a separate reviewable change after complexity and parameter reporting are stable.
|
|
144
|
+
|
|
145
|
+
- [x] Extract a direct binding name for module-level anonymous callables in every language.
|
|
146
|
+
- [x] Classify direct class-member callables separately from module bindings and inline callbacks.
|
|
147
|
+
- [x] Refactor naming cohesion to consume the callable's explicit optional name rather than searching
|
|
148
|
+
each raw function node for a direct `identifier` child.
|
|
149
|
+
- [x] Refactor type cohesion to consume callable parameter views without weakening typed-coverage
|
|
150
|
+
requirements.
|
|
151
|
+
- [x] Include module-level bound callables in free-function count and large-function sprawl.
|
|
152
|
+
- [x] Include direct class-member callables in method-related coherence checks where the language
|
|
153
|
+
treats them as methods.
|
|
154
|
+
- [x] Exclude callbacks, returned closures, and function-local callable variables from file-level
|
|
155
|
+
function count.
|
|
156
|
+
- [x] Exclude callbacks nested inside methods from class method count and god-class scoring.
|
|
157
|
+
- [x] Preserve import, class-relatedness, and god-class results for files without anonymous
|
|
158
|
+
callables.
|
|
159
|
+
- [x] Add positive and negative coherence fixtures that make the bound-versus-inline policy explicit.
|
|
160
|
+
|
|
161
|
+
## Phase 5: Cross-language fixture parity
|
|
162
|
+
|
|
163
|
+
- [x] Add realistic anonymous-callable examples under every
|
|
164
|
+
`src/test/fixtures/<language>/` directory.
|
|
165
|
+
- [x] Add named clean and finding scenarios to `tests/DetectorFixtureMatrixTests.fs` for cyclomatic,
|
|
166
|
+
cognitive, and parameter-count behavior.
|
|
167
|
+
- [x] Add explicit coherence scenarios for module-bound, class-bound, function-local, and inline
|
|
168
|
+
callables where those forms exist.
|
|
169
|
+
- [x] State syntax forms that a language does not support as explicit limitation cases rather than
|
|
170
|
+
silently omitting them.
|
|
171
|
+
- [x] Run the complete registered pipeline in fixture tests; do not validate only private detector
|
|
172
|
+
helpers.
|
|
173
|
+
- [x] Assert valid source positions and expected severities for every new diagnostic.
|
|
174
|
+
|
|
175
|
+
## Phase 6: Documentation and user-facing behavior
|
|
176
|
+
|
|
177
|
+
- [x] Update the TypeScript adapter's existing decision comment that deliberately records the
|
|
178
|
+
current arrow-function limitation.
|
|
179
|
+
- [x] Update `README.md` Known Issues.
|
|
180
|
+
- [x] Update `docs/agent-integration.md` coverage notes.
|
|
181
|
+
- [x] Update `docs/detectors/cyclomatic-complexity.md` with anonymous-callable boundary semantics.
|
|
182
|
+
- [x] Update `docs/detectors/cognitive-complexity.md` with standalone reporting and nested-score
|
|
183
|
+
semantics.
|
|
184
|
+
- [x] Update `docs/detectors/parameter-explosion.md` with supported anonymous forms and remaining
|
|
185
|
+
syntax-only limitations.
|
|
186
|
+
- [x] Update `docs/detectors/file-coherence.md` with the bound-versus-inline rule.
|
|
187
|
+
- [x] Check `docs/detectors/README.md` and other coverage summaries for stale named-function-only
|
|
188
|
+
wording.
|
|
189
|
+
- [x] Ensure examples say โanonymous callableโ where the behavior covers more than lambdas alone.
|
|
190
|
+
|
|
191
|
+
## Phase 7: Validation
|
|
192
|
+
|
|
193
|
+
Run focused checks after each behavioral phase and the full gate before each PR.
|
|
194
|
+
|
|
195
|
+
- [x] Run `just format`.
|
|
196
|
+
- [x] Run `just lint`.
|
|
197
|
+
- [x] Run `just md-lint`.
|
|
198
|
+
- [x] Run `just build`.
|
|
199
|
+
- [x] Run `just test`.
|
|
200
|
+
- [x] Run focused CLI analysis against the six new fixture files and inspect every finding.
|
|
201
|
+
- [x] Run `just analyze` and triage every result rather than suppressing it for convenience.
|
|
202
|
+
- [x] Run `git diff --check`.
|
|
203
|
+
- [x] Review staged and unstaged changes separately and stage only files belonging to this work.
|
|
204
|
+
- [x] Confirm no unrelated TypeScript fixture modification or untracked skill note was present or
|
|
205
|
+
modified in this worktree.
|
|
206
|
+
|
|
207
|
+
## Delivery sequence
|
|
208
|
+
|
|
209
|
+
### Pull request 1: Callable model, complexity, and parameters
|
|
210
|
+
|
|
211
|
+
- [x] Land the shared callable abstraction and six adapter implementations.
|
|
212
|
+
- [x] Land cyclomatic, cognitive, and parameter-count behavior with cross-language fixtures.
|
|
213
|
+
- [x] Update the detector documentation affected by this first behavior change.
|
|
214
|
+
- [x] Verify CI and review any changes to existing findings caused by isolating nested callable
|
|
215
|
+
boundaries.
|
|
216
|
+
|
|
217
|
+
### Pull request 2: Bound-callable coherence
|
|
218
|
+
|
|
219
|
+
- [x] Branch from updated `main` after pull request 1 lands.
|
|
220
|
+
- [x] Land binding-name/class-role extraction and coherence integration.
|
|
221
|
+
- [x] Add bound-versus-inline coherence fixtures and documentation.
|
|
222
|
+
- [x] Verify CI and dogfood the packaged CLI against representative real repositories before
|
|
223
|
+
removing the final coherence limitation.
|
|
224
|
+
|
|
225
|
+
## Completion criteria
|
|
226
|
+
|
|
227
|
+
- [x] Every supported anonymous-function form has an explicit supported or unsupported case.
|
|
228
|
+
- [x] Anonymous callables can independently produce cyclomatic, cognitive, and parameter-count
|
|
229
|
+
diagnostics in all six languages.
|
|
230
|
+
- [x] Nested anonymous callables do not inflate an enclosing cyclomatic graph.
|
|
231
|
+
- [x] Nested anonymous callables preserve the documented enclosing cognitive-nesting behavior.
|
|
232
|
+
- [x] File coherence counts named responsibilities without counting ordinary inline callbacks.
|
|
233
|
+
- [x] Unrelated detectors retain their prior scope and fixture results.
|
|
234
|
+
- [x] CLI and extension use the same behavior through the shared Core pipeline.
|
|
235
|
+
- [x] Documentation no longer claims the resolved limitation and accurately states what remains.
|
|
236
|
+
- [x] Both pull requests pass the repository's formatting, build, test, markdown, analyzer, and diff
|
|
237
|
+
checks.
|
|
238
|
+
|
|
239
|
+
## Rough estimate
|
|
240
|
+
|
|
241
|
+
- Callable model, complexity, parameters, fixtures, and documentation: **2โ3 development days**.
|
|
242
|
+
- Coherence binding/classification, fixtures, dogfooding, and documentation: **2โ4 development
|
|
243
|
+
days**.
|
|
244
|
+
- Total expected effort: **4โ7 development days**, split into two independently reviewable pull
|
|
245
|
+
requests.
|