Skip to content

Add design instantiation hierarchy queries#461

Open
nohous wants to merge 1 commit intoVHDL-LS:masterfrom
nohous:design-hierarchy
Open

Add design instantiation hierarchy queries#461
nohous wants to merge 1 commit intoVHDL-LS:masterfrom
nohous:design-hierarchy

Conversation

@nohous
Copy link
Copy Markdown

@nohous nohous commented May 1, 2026

Summary

Adds a walker over the analyzer's named-entity model that, given a top entity, produces the elaborated design instantiation tree, plus a candidate enumerator for "pick a top" UIs. Both are exposed as a CLI flag on vhdl_lang and as two custom LSP requests on vhdl_ls.

Companion PR for the official VS Code extension: VHDL-LS/rust_hdl_vscode (will link once opened).

Why

Hardware engineers routinely need a hierarchical overview of their design (top entity -> instantiated children, recursively). The analyzer already binds instantiations and resolves component default-binding; this PR turns that information into a public, well-typed tree and surfaces it via the LSP so editors can render a hierarchy view. A blank "type the entity name" prompt is unhelpful on a fresh project; the candidates query lets a UI pre-populate the picker with real top candidates first.

What's added

vhdl_lang

  • New module hierarchy exposing:
    • compute_design_hierarchy(root, library, entity) -> Result<DesignHierarchyNode, HierarchyError>
    • list_top_candidates(root) -> Vec<TopCandidate>
    • Types DesignHierarchyNode, HierarchyKind, HierarchyError, TopCandidate
  • Project::design_hierarchy, design_hierarchy_candidates, library_names thin wrappers
  • CLI flags: --hierarchy [LIB.]ENTITY, --hierarchy-format text|json, --hierarchy-quiet. JSON output is rendered via serde_json::to_string_pretty (new direct deps: serde, serde_json).
  • A bare entity name resolves against the project's libraries: prefers work, otherwise the single user library, otherwise lists known libraries and exits non-zero.

vhdl_ls

Two custom JSON-RPC requests (documented in README):

  • vhdl/designHierarchyCandidates -> { candidates: [{ library, entity, depth, instanceCount, isRoot, entityLocation }] }. Sorted roots-first / deepest-first.
  • vhdl/designHierarchy with params { library, entity } -> tree of { label, entity, architecture, kind, instanceLocation, entityLocation, notes, children }. kind is one of top, entity, boundComponent, unboundComponent, configuration, unresolved. Unknown library or entity yields InvalidRequest with a message listing the known names.

Behaviour notes

  • Component instantiations are followed through default binding to the bound entity.
  • Configuration instantiations appear as leaves (the configuration's block-configuration tree is not chased in this PR).
  • For-/if-/case-generate statements are visited once: each instance shows up at the source-text point it is written, not multiplied by the elaborated count.
  • When an entity has multiple architectures, the architecture named rtl is preferred; otherwise the alphabetically first architecture, with a note recorded on the node.
  • Cycles are detected and truncated with a note rather than recursing.

Tests

Nine new tests under analysis::tests::design_hierarchy covering: three-level entity nesting, component default-binding, unbound component, multi-architecture preference for rtl, alphabetical fallback, cycle protection, error messages with known-name lists, and candidate ranking. Full suite still passes (1417 + 9 = 1426 tests).

Test plan

  • cargo test --release -p vhdl_lang passes (1417 prior + 9 new)
  • CLI smoke test on a real project (~20 entities, 4 levels deep): tree renders correctly in both text and JSON
  • LSP smoke test (Python script): vhdl/designHierarchy and vhdl/designHierarchyCandidates round-trip end-to-end against a stdio-launched vhdl_ls
  • --hierarchy gev (no library prefix) on a project with multiple user libraries errors out and lists them; the same on a project with a single user library auto-resolves correctly

Adds a walker over the analyzer's named-entity model that, given a top
entity, produces the elaborated design instantiation tree. Component
instantiations are followed through default binding to the bound entity;
configuration instantiations and unbound components appear as annotated
leaves; cycles are detected and truncated. A second helper enumerates
every entity in the design ranked as a top-level candidate, with roots
(no incoming instantiations) sorted deepest-first - useful for picking a
top in a UI without typing the name blind.

vhdl_lang
  - New module `hierarchy` with `compute_design_hierarchy`,
    `list_top_candidates`, `DesignHierarchyNode`, `HierarchyKind`,
    `HierarchyError`, `TopCandidate`. When an entity has multiple
    architectures the one named `rtl` is preferred, otherwise the
    alphabetically first architecture, with a note recorded on the node.
  - `Project::design_hierarchy`, `design_hierarchy_candidates`, and
    `library_names` thin wrappers.
  - CLI flags `--hierarchy [LIB.]ENTITY`, `--hierarchy-format text|json`,
    `--hierarchy-quiet`. JSON output via serde. A bare entity name
    resolves against the project's libraries: prefers `work`, otherwise
    the single user library, otherwise lists known libraries and exits
    non-zero. `serde` and `serde_json` are now direct dependencies.

vhdl_ls
  - New custom requests `vhdl/designHierarchy` and
    `vhdl/designHierarchyCandidates`. Responses are LSP-shaped trees /
    arrays with `Location`s for the instantiation site and the entity
    declaration. `kind` is one of `top`, `entity`, `boundComponent`,
    `unboundComponent`, `configuration`, `unresolved`. Unknown library
    or entity yields `InvalidRequest` with a message listing the known
    names.

Tests
  - Nine new tests under `analysis::tests::design_hierarchy` covering
    three-level entity nesting, component default-binding, unbound
    component, multi-architecture preference for `rtl` and alphabetical
    fallback, cycle protection, error messages, and candidate ranking.

Documentation
  - README "Design hierarchy" section documenting both LSP requests
    (params, response shape, error semantics) and the CLI counterpart.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Schottkyc137
Copy link
Copy Markdown
Contributor

Hi! Thanks for tackling this issue! I think this is a feature many (including myself) will appreciate. I have a couple of comments though.

  1. This is a pretty large PR (~1500 lines of completely new and fairly dense code) which puts a lot of burden on me as maintainer and reviewer. I would like to ask you to split this into multiple smaller PRs for each new concept introduced to make the review process easier. It looks to me like your contribution is mainly three-fold: 1) Extract the design hierarchy, 2) LSP integration, 3) CLI binary. Splitting that into three separate PRs already helps a lot.
  2. There is already a hierarchy concept in the code base (EntHierarchy in analysis/root.rs.). Your solution uses a new one. Check, if your concept fits there or if the existing infrastructure can be extended. If the requirements are truly too different, this should be made clear by renaming the two concepts appropriately.
  3. There are a couple of "stringly typed" attributes (see for example the pub notes: Vec<String>, entity_path: String, ...). These should be first-class types (e.g., `Vec with variants like MultipleArchitectures { chosen, all }, UnboundComponent, ...). Conversion to English should happen at the CLI / LSP level.
  4. This PR introduces two custom LSP methods. However, to me it feels like some of your suggested changes fit functionality that is already part of the existing protocol. For example, the CallHierarchy is pretty close to the suggested vhdl/designHierarchy. The advantage in using already existing infrastructure is that the latter works on all kinds of editors that support LSP.
    This doesn't mean that I want you to shoehorn the functionality into existing LSP functionality, but simply to consider a more standard approach where feasible.
  5. The vhdl_lang binary is likely not the right tool to dump the hierarchy. A different binary is probably the better place. This also avoids the fact that, after this change, vhdl_langnow needs to pull in the entireserde/serde_json` stack only to print the hierarchy.
  6. The comment "if a library named work is configured, use it;" is incorrect. A VHDL library is not allowed to be called "work"

@nohous
Copy link
Copy Markdown
Author

nohous commented May 3, 2026

Noted and thanks for the pointers - I just wanted to share this early (so maybe sorry for making it a PR) - so you can build and see it work and give your feedback - which you have did. I will go through it, make it more consistent with your intents and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants