oxalica / nil

NIx Language server, an incremental analysis assistant for writing in Nix.
Apache License 2.0
1.38k stars 40 forks source link

`textDocument/documentSymbol` request #16

Closed leungbk closed 2 years ago

leungbk commented 2 years ago

It would be nice if this server supported textDocument/documentSymbol.

oxalica commented 2 years ago

Nix is expression-based and there is no "global" symbols. And it's tricky about the "correct" hierarchy of names. There are also many anonymous things, like lambdas.

As a reference, rust-analyzer includes only items (like mod, struct, enum, union, fn or impl) as symbols. Local variables and parameters don't count. But if we follows that, we'll have nothing to response -- all names in Nix are kinds of "local" bindings.

IMO, parameters, let-bindings and attrset keys should be included to make it actually helps.

For example,

{ stdenv, fetchurl }:
args:
let version = "1"; in
stdenv.mkDerivation ({
  inherit version;
  src = fetchurl {
    url = "example.com";
    inherit version;
  };
} // args)

gives,

You can spot some problems,

  1. It's quite deep and more like an AST dumping.
  2. Almost half of them are "anonymous".
  3. inherit introduces duplicated names.

We can flatten curried lambdas, with the cost of accuracy about scoping. But it may not work well with let-in or attrsets inside a binding: making url and version directly under src is wrong because src is not an attrset, it just contains one.

oxalica commented 2 years ago

Currently I only included fields and let-bindings, and flattened all anonymous nodes. The result is acceptable for me. If there is any better idea about the hierarchy, please comment.

image

asymmetric commented 1 year ago

Could someone share a snippet of code to get the above to work in their editor?

I think I got this to work in neovim with telescope (using the lsp_document_symbols function), but it displays a flat list of attributes, rather than the hierarchical one in the screenshot above.

oxalica commented 1 year ago

I think I got this to work in neovim with telescope (using the lsp_document_symbols function),

AFAIK, telescope is a fuzzy searching tool and cannot list trees. My screenshot is from coc.nvim using :CocOutline. You can search keyword symbol outline for this functionality. I found there are https://github.com/SmiteshP/nvim-navic and https://github.com/simrat39/symbols-outline.nvim which seem doing the same job with neovim native LSP. Hope it helps.