energy-state-analyzer 0.18.1 → 0.19.0

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- last_commit_released: 00fd3e6fbca7cbfa1fec8417ffe5ee805b0960c5
2
+ last_commit_released: d638fb6b75608731fb0ff06d12717a1a0c9be442
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,15 @@ 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.0 - 2026-09-16
18
+
19
+ ### 🚀 Features
20
+
21
+ * Introduce anonymous callable model (#153) ([c3129f3](https://github.com/cardamomcode/energy-state-analyzer/commit/c3129f3427247d32d056bb6035e0efbd55017bea))
22
+ * Integrate bound callables with coherence (#155) ([d638fb6](https://github.com/cardamomcode/energy-state-analyzer/commit/d638fb6b75608731fb0ff06d12717a1a0c9be442))
23
+
24
+ <strong><small>[View changes on Github](https://github.com/cardamomcode/energy-state-analyzer/compare/00fd3e6fbca7cbfa1fec8417ffe5ee805b0960c5..d638fb6b75608731fb0ff06d12717a1a0c9be442)</small></strong>
25
+
17
26
  ## 0.18.1 - 2026-09-15
18
27
 
19
28
  ### 🐞 Bug Fixes
package/README.md CHANGED
@@ -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
- - TypeScript arrow functions aren't analyzed by complexity/parameter-count/coherence (same limitation Python already has for `lambda`), only named `function` declarations and class methods are.
152
- - C++ analysis is syntax-only: it does not preprocess macros, resolve includes, instantiate templates, or perform type checking. C++ lambdas are not treated as standalone functions by function-level detectors.
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.