polarmutex/beancount-language-server

Ledger sections in VSCode outline view

Opened this issue · 5 comments

Hi there, thanks again for the cool language server.

I had this desire to be able to jump quickly to headings in the ledger (where "headings" are lines that begin with some number of asterisks, which I believe comes from Emacs org-mode, i.e. "Hooli Income" or "Vanguard Brokerage"). VSCode has the "outline" view in the explorer, and that comes from the DocumentSymbolProvider extension API.

I coded it up here: https://github.com/aaronj1335/vscode-aaronsbeancountutils/blob/10499548429d0521241ca8bc80fddaeaf07d0dec/src/extension.ts#L112, (quick docs) and I find it quite helpful.

I think this is relatively performant since it's a single loop through the lines (which I guess I assume are already parsed). That being said, it seems like a bit of a shame this isn't baked into the language server more directly.

If you think this would be appropriate in your language server, I'd love to contribute it, but I'd need some pointers. WDYT? Any chance you could give me some guidance on building the VSCode extension and where this might fit in?

looks cool to me, i am in the process of moving the vscode-beancount repo to this repo. i can merge the code into master so you can make a PR with your changes. the vscode extension will be in the folder editor/code.

code should be in master now to write PR

awesome, i'll give it a try

OK so I did some reading. my understanding is there's essentially 3 parsers happening here:

  1. The Rust parser, which is incremental, and provides:
    1. Diagnostics (i.e. bean-check) output.
    2. (tab) Completion.
    3. Formatting (custom implementation, but similar to what bean-format does).
  2. The non-incremental semantic tokens parser, which is a second instance of the tree-sitter tree running in the VSCode node process, which provides semantic highlighting.
  3. (ish) the parsing that happens when bean-check runs, which of course is probably not worth changing.

Adding the symbol provider would add a 4th (albeit ad-hoc) parsing pass, also in VSCode's node process. A couple ideas:

  1. Simply add my DocumentSymbolProvider in a new file in the directory alongside your SemanticTokensProvider. It may duplicate some processing, but it's probably pretty lightweight.
  2. Try getting symbols from the same tree (or a lightweight copy of it) used by your semantic tokens provider.
  3. Do option 2, but use incremental parsing so theoretically there's less processing.
  4. Add the notion of semantic tokens and symbols to the Rust implementation, so there's actually just the one instance of the parsed tree in memory.

WDYT? Honestly option 1 feels not really better than just installing vscode-beancount-language-server + vscode-aarons-beancount-utils. Option 2 seems more fun, but based on the profiling I've done, it's unlikely to actually be a performance benefit unless we do option 3. Option 4 seems most theoretically pure, but (a) that's a lot of work and (b) you still need to create VSCode types at some point, and those would need to be serialized between processes, so IDK if it'd actually be any performance benefit.

I'd propose:

  • Step 1: do option 1 and push that to the marketplace just to get us to actually shipping something. (AFAICT we'll still need to re-connect the plumbing that bundles + starts the server... maybe I'm missing something).
  • Step 2: refactor to option 3 and see if there's actually any performance gain.

WDYT?

I like option 1 for now, it might make better sense to add to the rust parser later(so all editors can get the benefit). the semantic provider is in the vscode extension because it is only needed for vscode (since most editors support tree-sitter) .