solidity-language-server 0.1.25

A fast Solidity language server powered by solc and Foundry
Documentation
## Agents

- User `jq` to analyze json outputs from ast.
- [poolmanager.json]./poolmanager.json - ast generated by solc.

## Testing and Debugging

Always use `lsp-bench` as the first choice when you want to debug lsp methods and their output. The lsp-bench is located locally at ../solidity-lsp-benchmarks.

There are many examples on ./benchmarks on how to write a simple yaml config to you needs.

## Building

Always build with `--release` flag

## Memory Optimization Notes (branch: cleanup/dead-code-and-memory)

### Current state

| State | RSS | vs v0.1.24 |
|---|---|---|
| v0.1.24 baseline | 230 MB ||
| Before this work (pre-branch) | 394 MB | +164 MB |
| After extract_decl_nodes + remove ast field | 309 MB | +79 MB |
| After with_capacity + build-filtered-map (P2) | **254 MB** | **+24 MB** |

Reclaimed **140 MB** of the 164 MB regression. The remaining +24 MB matches the
~23 MB of new retained data structures (`decl_index` + `DeclNode` contents).

### Completed optimizations

- **Removed `CachedBuild.ast` field** — raw JSON no longer retained after construction.
- **P2: build-filtered-map** — replaced `node.clone()` → strip with selective field
  copy in `walk_and_extract()`. Eliminated 234 MB of transient allocations (629→395 MB).
- **Pre-sized HashMaps**`with_capacity()` in `cache_ids()`, `extract_decl_nodes()`,
  `build_completion_cache()`, `build_hint_index()`, `build_constructor_index()`.

### DHAT profiling results (poolmanager-t-full.json, 95 files)

```
                 Before P2    After P2
Total allocated: 629 MB   →   395 MB  (-37%)
Peak (t-gmax):   277 MB   →   243 MB  (-12%)
Retained (t-end): 60 MB   →    60 MB  (unchanged)
RSS observed:    310 MB   →   254 MB  (-18%)
```

**Retained memory breakdown (t-end, unchanged):**

| # | Retained | Source | Notes |
|---|---|---|---|
| 1 | 16.4 MB | `cache_ids()``nodes` HashMap | All AST nodes with src, referencedDeclaration, etc. Existed in v0.1.24 too. |
| 2 | 12.6 MB | `walk_and_extract()``decl_index` + `node_id_to_source_path` | **New** — typed declaration index. |
| 3 | 4.1 MB | `FunctionDefinition` structs in `decl_index` | **New** |
| 4 | 4.1 MB | `ContractDefinition` structs (includes child `nodes` array) | **New** — P1 target. |
| 5 | 2.0 MB | `VariableDeclaration` structs | **New** |
| 6 | 1.9 MB | `CompletionCache` | Partially new. |
| 7+ | 3.4 MB | Strings, other indexes | Mixed. |

**Key insight:** The remaining +24 MB RSS gap is real retained data (~23 MB of new
`decl_index` structures), not fragmentation. The 395 MB of transient churn still
causes some fragmentation, but the gap is now within the expected range.

### Remaining optimization targets (diminishing returns)

1. **P1: ContractDefinition.nodes** (4.1 MB retained) — only needs selectors + doc text for
   `resolve_inheritdoc_typed()`, not the full child nodes. Could save ~2-3 MB retained.
2. **P3: CompletionCache** (1.9 MB) — check for name duplication with `nodes`.
3. **Further transient reduction** — the initial JSON parse (`serde_json::from_str`) allocates
   the full AST tree (~70+ MB for BTreeMap nodes), which is then walked by `cache_ids()` and
   `extract_decl_nodes()`. Streaming parse could avoid this but is a large refactor.