debtmap 0.21.0

Code complexity and technical debt analyzer
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# Solidity Support — Remaining Work

This document tracks what is **done**, what is **partially implemented**, and what remains to bring Solidity analysis in debtmap to parity with mature language support (Rust/TypeScript) and the original implementation plan.

**Status as of MVP delivery:** Solidity is usable for single-file and project analysis via `--languages sol`. The analyzer produces `FunctionMetrics`, `FileMetrics`, complexity debt, generic smells, and heuristic security advisories. Everything below builds on that foundation.

---

## Current State Summary

### Implemented

| Area | Location | Notes |
|------|----------|-------|
| Language routing | `src/core/mod.rs`, `src/utils/language_parser.rs`, `src/io/walker.rs` | `.sol` extension, CLI aliases `solidity` / `sol` |
| Parser | `src/analyzers/solidity/parser.rs` | `tree-sitter-solidity` 1.2.13, `tree-sitter` 0.25 |
| Analyzer trait | `src/analyzers/solidity/analyzer.rs` | Registered in `get_analyzer()` |
| Complexity | `src/analyzers/solidity/complexity.rs`, `visitor.rs` | Cyclomatic, cognitive, nesting, function length |
| Callable extraction | `src/analyzers/solidity/visitor.rs` | Functions, modifiers, constructor, fallback, receive |
| Generic debt | `src/analyzers/solidity/debt/mod.rs` | Threshold complexity, nesting, length, TODO/FIXME, smells |
| Security advisories | `src/analyzers/solidity/debt/security_patterns.rs` | 11 heuristic patterns (see below) |
| Dependencies | `src/analyzers/solidity/dependencies.rs` | Imports + inheritance (`DependencyKind::Inheritance`) |
| Test detection | `src/analyzers/solidity/test_detection.rs` | Foundry `*.t.sol`, `forge-std/Test.sol` |
| Batch / validation | `src/analyzers/batch.rs`, `src/builders/validated_analysis.rs` | Parse validation wired |
| Config schema | `src/config/languages.rs` | `SolidityLanguageConfig`, `SoliditySecurityConfig` (schema only) |
| LOC counting | `src/metrics/loc_counter.rs` | `LocLanguage::Solidity` |
| Tests | `src/analyzers/solidity/*`, `tests/solidity_analyzer_tests.rs` | 15 unit + 10 integration tests |
| Book docs | `book/src/configuration/languages.md`, etc. | Partial updates |

### Security patterns currently detected

| Pattern ID | Priority (typical) |
|------------|-------------------|
| `tx-origin-usage` | High |
| `unchecked-low-level-call` | High |
| `external-call-before-state-update` | High |
| `delegatecall-usage` | Medium |
| `selfdestruct-usage` | Medium |
| `assembly-block` | Medium |
| `unbounded-loop` | Medium |
| `missing-access-control` | Medium |
| `large-contract` | Medium |
| `hardcoded-address` | Low |
| `floating-pragma` | Low |

All advisories use “review recommended” wording — not formal verification.

---

## Gap Overview

```mermaid
flowchart TB
    subgraph done [MVP Complete]
        Parse[Parse and route .sol files]
        Complexity[Complexity metrics]
        GenericDebt[Generic debt]
        Heuristics[Security heuristics]
    end

    subgraph phase1 [Phase 1 — Config and polish]
        ConfigWire[Wire config to analyzer]
        DocsUX[README init template]
        SecurityTests[Security fixture coverage]
    end

    subgraph phase2 [Phase 2 — Analysis depth]
        Entropy[Entropy dampening]
        AdvancedDebt[Advanced advisory signals]
        Suppression[Suppression verification]
        VendorCode[Vendor/generated handling]
    end

    subgraph phase3 [Phase 3 — Cross-file]
        CallGraph[Cross-contract call graph]
        ImportResolve[Import path resolution]
        ProjectCtx[Project-level Solidity context]
    end

    subgraph phase4 [Phase 4 — Ecosystem]
        NatSpec[NatSpec analysis]
        LangSpecific[LanguageSpecificData]
        Benchmarks[Parsing benchmarks]
        GrammarBump[Grammar version alignment]
    end

    done --> phase1
    phase1 --> phase2
    phase2 --> phase3
    phase3 --> phase4
```

---

## Phase 1: Config Wiring and User-Facing Polish

**Goal:** Make existing behavior configurable and visible. Low risk, high user value.

### 1.1 Wire `SolidityLanguageConfig` into the analyzer

**Problem:** Config structs exist in [`src/config/languages.rs`](../src/config/languages.rs) but [`SolidityAnalyzer`](../src/analyzers/solidity/analyzer.rs) ignores them. Security checks are always on; `large_contract_threshold` is hardcoded to `20` in [`security_patterns.rs`](../src/analyzers/solidity/debt/security_patterns.rs).

**Tasks:**

1. Add config accessor in [`src/config/accessors.rs`]../src/config/accessors.rs:
   ```rust
   pub fn get_solidity_config() -> SolidityLanguageConfig
   ```

2. Extend `SolidityAnalyzer` (mirror [`GoAnalyzer`]../src/analyzers/go/analyzer.rs):
   - `with_config(SolidityLanguageConfig)` or load from `get_solidity_config()` in `new()`
   - Pass config through `orchestration.rs``debt/``security_patterns.rs`

3. Gate each security pattern on its config flag:
   - Extend `SoliditySecurityConfig` with toggles for **all** patterns (today only 4 flags exist; add the rest or group them logically)
   - Respect `detect_complexity`, `detect_duplication`, `detect_dead_code` from flattened `LanguageFeatures`

4. Pass `large_contract_threshold` into `detect_contract_patterns()` instead of literal `20`.

5. Wire batch analysis in [`src/analyzers/batch.rs`]../src/analyzers/batch.rs:
   - Add `solidity_config_from_debtmap(config)` similar to `go_generated_code_mode()`
   - Optionally pass global complexity threshold from `DebtmapConfig` (today hardcoded default `10`)

**Files to touch:**

- `src/config/accessors.rs`
- `src/analyzers/solidity/analyzer.rs`
- `src/analyzers/solidity/orchestration.rs`
- `src/analyzers/solidity/debt/mod.rs`
- `src/analyzers/solidity/debt/security_patterns.rs`
- `src/analyzers/batch.rs`
- `src/config/languages.rs` (expand `SoliditySecurityConfig` if needed)

**Tests:**

- Config disables `tx_origin` → no `tx-origin-usage` debt
- `large_contract_threshold = 5` triggers advisory on smaller contract
- Config test in `src/config/mod.rs` (follow Go config test pattern)

**Estimated effort:** 1–2 days

---

### 1.2 README and init template

**Problem:** User-facing entry points still list five languages.

**Tasks:**

1. Update [`README.md`]../README.md:
   - Supported languages list
   - Example: `debtmap analyze ./contracts --languages sol`
   - Roadmap checkbox for Solidity

2. Update [`src/commands/init.rs`]../src/commands/init.rs default template:
   ```toml
   enabled = ["rust", "python", "solidity"]
   # or include all six — decide product default
   [languages.solidity]
   detect_complexity = true
   ```

3. Align [`book/src/configuration/languages.md`]../book/src/configuration/languages.md — ensure all `enabled` examples include `solidity` consistently.

**Estimated effort:** 0.5 day

---

### 1.3 Security pattern test coverage

**Problem:** Only `tx-origin-usage` has a dedicated positive test. Plan called for positive + negative fixture per pattern.

**Tasks:**

1. Expand `tests/fixtures/solidity/security/`:
   ```
   security/
   ├── tx_origin_positive.sol / tx_origin_negative.sol
   ├── unchecked_call_positive.sol / unchecked_call_negative.sol
   ├── reentrancy_positive.sol / reentrancy_negative.sol
   ├── assembly_positive.sol / assembly_negative.sol
   ├── access_control_positive.sol / access_control_negative.sol
   └── ...
   ```

2. Add parametrized integration tests in `tests/solidity_analyzer_tests.rs` asserting pattern presence/absence.

3. Add unit tests in `security_patterns.rs` for edge cases (nested assembly, `require` wrapping calls, etc.).

**Estimated effort:** 1–2 days

---

## Phase 2: Analysis Depth

**Goal:** Reduce false positives and add signals comparable to Go’s `advanced.rs`.

### 2.1 Entropy dampening

**Problem:** Repetitive Solidity patterns (similar `require` chains, boilerplate ERC hooks) inflate cognitive scores. Rust/JS/TS use [`LanguageEntropyAnalyzer`](../src/complexity/entropy_core.rs).

**Tasks:**

1. Create `src/analyzers/solidity/entropy/`:
   - `token.rs``SolidityEntropyToken` implementing `EntropyToken`
   - `analyzer.rs``SolidityEntropyAnalyzer` implementing `LanguageEntropyAnalyzer`
   - Classify: keywords, identifiers, literals, operators, `require`/`assert`/`revert`

2. Integrate in `visitor.rs` / `metrics.rs`:
   - Populate `FunctionMetrics.entropy_analysis`, `entropy_score`, `adjusted_complexity`

3. Follow [`src/analyzers/typescript/entropy/`]../src/analyzers/typescript/entropy/ as template (tree-sitter token walk).

**Tests:** Property tests for dampening on repetitive require chains vs genuinely complex control flow.

**Estimated effort:** 3–5 days

---

### 2.2 Advanced advisory signals (`advanced.rs`)

**Problem:** Go detects swallowed errors, goroutines, defer-in-loop, etc. Solidity lacks equivalent depth.

**Candidate signals:**

| Signal | Detection approach |
|--------|-------------------|
| `unchecked-arithmetic` | Pre-0.8.0 style or missing `SafeMath`/checked blocks |
| `unsafe-erc20-transfer` | `transfer`/`transferFrom` without return check (non-standard tokens) |
| `push-without-length-cap` | `.push()` in loop without max length |
| `self-assign-reentrancy` | State read after external call in same function |
| `block-timestamp-dependency` | `block.timestamp` in critical logic |
| `tx-gas-price-dependency` | `tx.gasprice` usage |
| `encode-packed-collision` | `abi.encodePacked` with dynamic types |
| `delegatecall-in-constructor` | Proxy misconfiguration heuristic |

**Tasks:**

1. Add `src/analyzers/solidity/advanced.rs` with pure detection functions
2. Merge patterns into `SolidityFunction.advisory_patterns` in visitor
3. Map to debt items in `debt/mod.rs` (reuse Go advisory pattern)

**Estimated effort:** 3–4 days

---

### 2.3 Suppression support verification

**Problem:** [`get_comment_prefix_pattern`](../src/debt/suppression.rs) maps unknown languages to `//`, which should work for Solidity — but this is **untested**.

**Tasks:**

1. Add suppression tests with `Language::Solidity` and `// debtmap:ignore` comments
2. Verify block and line suppressions filter complexity/security debt correctly
3. Document Solidity suppression syntax in book

**Estimated effort:** 0.5–1 day

---

### 2.4 Vendor and generated contract handling

**Problem:** Go suppresses `*.pb.go`, mockgen output. Solidity projects include OpenZeppelin, Foundry `out/`, Hardhat `artifacts/`.

**Tasks:**

1. Add `src/analyzers/solidity/generated.rs`:
   - Detect `@openzeppelin/contracts` imports-only vendor files (optional exclude)
   - Skip `out/`, `cache/`, `artifacts/`, `node_modules/` via existing walker ignore patterns
   - SPDX + “Automatically generated” header detection

2. Optional config (mirror Go):
   ```toml
   [languages.solidity]
   vendor_code = "suppress_debt"  # analyze | suppress_debt | exclude
   ```

3. Update default ignore patterns in config if not already covering Foundry/Hardhat dirs.

**Estimated effort:** 1–2 days

---

### 2.5 Hardhat test detection

**Problem:** Only Foundry tests are detected (`*.t.sol`, `forge-std`).

**Tasks:**

1. Extend `test_detection.rs`:
   - `@nomicfoundation/hardhat-chai-matchers` / `hardhat` import paths
   - File naming: `*.test.sol` convention (if used)
   - `contract.*Test` naming (already partial via `is_test_contract_name`)

2. Add fixtures and tests.

**Estimated effort:** 0.5 day

---

### 2.6 Heuristic quality improvements

**Problem:** Current security detectors are intentionally simple and produce false positives/negatives.

**Priority refinements:**

| Pattern | Current weakness | Improvement |
|---------|------------------|-------------|
| `external-call-before-state-update` | Flat statement order scan | Walk AST for CEI ordering; distinguish `transfer` vs internal calls |
| `unchecked-low-level-call` | Parent text `require` check | Detect `(bool success, )` destructuring and `if (!success)` |
| `missing-access-control` | String search for `onlyOwner` | Parse modifier list; detect `_checkOwner()`-style internal guards |
| `unbounded-loop` | Crude array-length heuristic | Track `storage` array `.length` vs calldata with explicit bounds |
| `hardcoded-address` | Token split | Regex with word boundaries; exclude common constants |

**Tasks:** Incremental PRs per pattern with fixture-driven tests.

**Estimated effort:** 2–4 days (ongoing)

---

## Phase 3: Cross-File and Project-Level Analysis

**Goal:** Enable architectural insights across a Solidity codebase.

### 3.1 Import path resolution

**Problem:** [`dependencies.rs`](../src/analyzers/solidity/dependencies.rs) records raw import strings (`"./Token.sol"`) but does not resolve to project files.

**Tasks:**

1. Build remapping support:
   - Foundry `remappings.txt`
   - Hardhat config paths (lower priority)

2. Resolve import paths to absolute project paths for dependency graph.

3. Feed resolved graph into [`src/debt/circular.rs`]../src/debt/circular.rs.

**Estimated effort:** 3–5 days

---

### 3.2 Cross-contract call graph

**Problem:** `FunctionMetrics.call_dependencies` contains raw call text (`token.transfer`) with no cross-file linking.

**Tasks:**

1. Add `src/analyzers/solidity/call_graph.rs`:
   - Parse `call_expression`, `member_expression` with type hints where possible
   - Link interface calls (`IERC20(token).transfer`) to imported symbols

2. Integrate with existing [`call_graph/`]../src/analyzers/call_graph/ infrastructure or add Solidity-specific project pass (like Go cross-file resolution in `batch.rs`).

3. Emit `upstream_callers` / `downstream_callees` on `FunctionMetrics`.

**Estimated effort:** 5–8 days

---

### 3.3 Contract-level project metrics

**Tasks:**

1. Populate `FileMetrics.classes` with richer `ClassDef` (method list, line numbers, abstract/interface flag)
2. Project-level aggregation: contracts per file, inheritance depth, external call surface
3. Optional: proxy pattern detection (EIP-1967 slot, `delegatecall` in constructor)

**Estimated effort:** 2–3 days

---

## Phase 4: Extended Features and Infrastructure

### 4.1 NatSpec / documentation debt

**Tasks:**

1. Parse `/// @notice`, `@dev`, `@param` NatSpec blocks (text-level or tree-sitter comment nodes)
2. Debt types:
   - Missing NatSpec on public/external functions
   - Empty or placeholder `@notice`
   - Mismatch between `@param` count and function signature

**Estimated effort:** 2–3 days

---

### 4.2 `LanguageSpecificData::Solidity(...)`

**Problem:** [`FunctionMetrics.language_specific`](../src/core/mod.rs) only has a Rust variant today.

**Tasks:**

1. Define `SolidityPatternResult` (proxy usage, upgradeable pattern, payable functions, state mutability)
2. Add enum variant and serialization tests
3. Surface in JSON/TUI output

**Estimated effort:** 1–2 days

---

### 4.3 Purity analysis (EVM-aware)

**Problem:** Deferred from MVP. Solidity “pure/view/payable” mutability exists at language level but debtmap does not use it.

**Tasks:**

1. Extract state mutability from function definition nodes
2. Detect state writes (`SSTORE` heuristic via assignment to state variables)
3. Classify `PurityLevel` for Solidity functions (ReadOnly for `view`, etc.)
4. Flag `nonReentrant` modifier absence on state-changing external calls (optional)

**Estimated effort:** 3–4 days

---

### 4.4 Single-pass extraction layer

**Problem:** Rust uses [`UnifiedFileExtractor`](../src/extraction/extractor.rs) to avoid re-parsing. Solidity re-walks the tree in visitor + debt + dependencies.

**Tasks:**

1. Add `src/extraction/solidity.rs` — one walk producing `ExtractedFileData`
2. Adapter in `src/extraction/adapters/``FileMetrics`
3. Benchmark parse+analyze time before/after

**Estimated effort:** 3–5 days (optimization, not blocking)

---

### 4.5 Parsing benchmarks

**Tasks:**

1. Add `benches/solidity_parsing_bench.rs` (criterion)
2. Fixtures: small contract, Uniswap-style size, deeply nested control flow
3. CI threshold or tracking only (no hard gate initially)

**Estimated effort:** 0.5–1 day

---

### 4.6 Tree-sitter grammar alignment

**Problem:** Core bumped to `tree-sitter 0.25` for Solidity ABI 15; other grammars remain on `0.23`.

**Tasks:**

1. Evaluate bumping `tree-sitter-javascript`, `tree-sitter-python`, `tree-sitter-go`, `tree-sitter-typescript` to 0.25-compatible versions
2. Run full test suite + parser smoke tests
3. Pin exact versions in `Cargo.toml`

**Risk:** ABI breakage across grammars. Do as dedicated PR with rollback plan.

**Estimated effort:** 1–2 days

---

### 4.7 External tool integration (optional, long-term)

| Tool | Integration idea |
|------|------------------|
| Slither | Feature flag to merge Slither JSON detectors into `DebtItem` |
| Mythril | Post-process symbolic findings |
| Foundry coverage | LCOV from `forge coverage` for risk scoring |

**Not recommended until core heuristics stabilize** — avoids duplicate/conflicting signals.

**Estimated effort:** 5+ days each

---

## Phase 5: AST and Pattern Extraction Gaps

### 5.1 `Ast::Solidity` node extraction

**Problem:** [`Ast::extract_nodes()`](../src/core/ast.rs) returns `vec![]` for Solidity — pattern/design extraction pipeline skips `.sol` files.

**Tasks:**

1. Implement `extract_solidity_nodes()` mapping contracts → `NodeKind::Class`, functions → `NodeKind::Function`
2. Enable architectural analysis stages that consume `AstNode` trees

**Estimated effort:** 1–2 days

---

## Recommended PR Sequence

Split work into reviewable PRs:

| PR | Scope | Depends on |
|----|-------|------------|
| **PR A** | Config wiring + security toggles + threshold ||
| **PR B** | README, init template, book polish ||
| **PR C** | Security fixture suite (all patterns) ||
| **PR D** | Suppression tests for Solidity ||
| **PR E** | Entropy dampening ||
| **PR F** | Advanced advisory signals | PR C |
| **PR G** | Heuristic refinements (batch 1: reentrancy, unchecked calls) | PR C |
| **PR H** | Vendor/generated code handling | PR A |
| **PR I** | Import remapping + circular deps ||
| **PR J** | Cross-contract call graph | PR I |
| **PR K** | NatSpec debt ||
| **PR L** | `LanguageSpecificData`, mutability/purity | PR E |
| **PR M** | tree-sitter 0.25 grammar alignment ||
| **PR N** | Benchmarks + extraction optimization | PR M |

PRs A–D can land in parallel. PR J depends on import resolution (PR I).

---

## Quality Gates (per PR)

Every Solidity PR should satisfy:

```bash
just fmt
cargo test --lib analyzers::solidity
cargo test --test solidity_analyzer_tests
cargo test --test language_tests
```

Before merge to main:

```bash
just test   # full suite
```

Add clippy clean for touched modules.

---

## Risk Register

| Risk | Mitigation |
|------|------------|
| `tree-sitter-solidity` AST instability | Pin exact version; parser regression tests on upgrade |
| Security heuristic false positives | Config opt-out per pattern; conservative defaults; clear advisory wording |
| Cross-file resolution complexity | Start with Foundry remappings only; defer Hardhat |
| Entropy token classifier accuracy | Property tests; compare adjusted scores on real fixtures |
| Grammar bump breaks JS/Python/Go | Dedicated PR, multi-platform CI, pin all grammars together |

---

## Definition of Done (Full Solidity Support)

Solidity support is **feature-complete** (beyond MVP) when:

- [ ] All config in `debtmap.toml` is honored at runtime
- [ ] Entropy dampening active for Solidity functions
- [ ] All 11+ security patterns have positive/negative fixture tests
- [ ] Suppression comments verified for `.sol` files
- [ ] Import remapping resolves dependencies for Foundry projects
- [ ] Cross-contract call graph populated on project analysis
- [ ] README and init template list Solidity
- [ ] NatSpec missing-docs detection on public/external functions
- [ ] No known parser ABI mismatches across tree-sitter grammars

---

## Out of Scope (Explicit)

- Formal verification or symbolic execution
- Replacing Slither/Mythril/Foundry built-in linters
- Yul-only files (`.yul`) — separate grammar would be needed
- Vyper support — separate language module
- On-chain bytecode analysis

---

## References

- MVP implementation: `src/analyzers/solidity/`
- Original plan: `.cursor/plans/add_solidity_support_*.plan.md` (Cursor plan artifact)
- Go analyzer template: `src/analyzers/go/`
- TypeScript entropy template: `src/analyzers/typescript/entropy/`
- Config schema: `src/config/languages.rs`
- Integration tests: `tests/solidity_analyzer_tests.rs`
- Fixtures: `tests/fixtures/solidity/`