Skip to content

Tracking issue for LSP typechecking #1158

@cormacrelf

Description

@cormacrelf

Making a tracker because I have built:

  • Live typechecking in LSP
  • Hover-for-type and docs
  • Significantly improved typechecking local bindings, prelude glob imports in build files, types of imported symbols, ...

I have already done it, and I'd like to get it merged so I can use it. I've done 4 PRs already, and I have maybe 2-3 more of that size to go. I would like some help shepherding this into main. This issue should help clarify the overall direction.

I am aware that when imported, PRs get squashed into one commit. I think that approach won't really scale, I have been writing commits of about the size of the ones that get merged internally (to review commit by commit), and I have about 100 commits to get merged. Is there an option to review a batch and import them as individual commits?

Demos

All of the following is new functionality.

Typecheck build rules from BUCK files

We can model a prelude "glob import" in the typechecker. Won't check attrs.dep() vs string though, that would need full evaluation.

Image
Typecheck import symbols

The entire starlark Interface type (representing a loaded module) was basically unused, this is its time to shine.

Image
Live typechecking with hover for type information

Note also the provider type is routed through Dependency's [] indexing.

Image

PRs

Related:

Done but not a PR yet

  • Live typechecking in LSP.
  • Hover-for-type-info. As you can see in the demo, that extends to x.attr where x is of a known type.

Half-done

  • Eval-on-save for build files specifically. I originally introduced that in LSP gets type checking #1132 but it was too much. I would like to bring it back specifically for build files, so that you can e.g. "typecheck" the paths of source artifacts etc.
  • Workspace diagnostics, to typecheck multiple files in tandem

Unresolved questions

  1. I'm storing typechecker output in DICE. This is convenient because it's right there in buck2_interpreter_for_build with all its sibling functions for evaluation. All the helper functions are either shared with evaluation or very similar. I don't really like storing it in DICE forever since it's not used for running builds. There are some options:

    a. Leave as is. Prelude is 20MB. Don't worry about it.
    b. Can we just record all the dice keys that anyone has type checked, and when last LSP server exits, we drain this list and invalidate all the keys? Reading a bit of DICE source and I can't tell that this will actually free any memory. Seems like it just marks an OccupiedGraphNode as dirty but leaves it occupied. There is no transition back to vacant anywhere. If DICE is just not capable of freeing computed values, I don't know what to think.
    c. Use loaded/evaluated modules for dependencies, typecheck current module uncached. Nothing is stored, but we would not degrade typechecking gracefully when there are errors. An error in any module blocks all reverse deps.
    d. Something like the DocsCache in buck2_server::lsp. Use dice equality to invalidate typechecks when files change but otherwise manually store everything.

Issues fixed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions