Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite plugin tutorial #3655

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

cgeorgii
Copy link
Contributor

This is an almost-complete rewrite of the outdated plugin tutorial. The section about the code lens provider is still unchanged and probably incorrect. I'll try to get to it at some point.

To view the new docs locally follow the instructions from the docs. TLDR: cd docs; make html

It also contains some minor refactors to the files mentioned in the plugin since it aided in my understanding of what was going on.

@michaelpj
Copy link
Collaborator

What do you think about taking this opportunity to make the code snippets compiled? RST lets you include chunks from files, so it's relatively easy to define a separate source file and include the snippets from it, and then we can compile that source file to make sure the examples keep working.

@fendor
Copy link
Collaborator

fendor commented Jun 12, 2023

@michaelpj lots of the shown code is code from HLS directly, e.g. types from the PluginDescriptor.

What might be possible is to compile the actual plugin, but everything else is unlikely to work, I think.

@michaelpj
Copy link
Collaborator

What might be possible is to compile the actual plugin, but everything else is unlikely to work, I think.

I think we might just be able to include the relevant section from the files in HLS also!

@fendor
Copy link
Collaborator

fendor commented Jun 12, 2023

Referencing a code section from another file? Do you have an example of how we could do that?

@michaelpj
Copy link
Collaborator

See the use of literalinclude here: https://raw.githubusercontent.com/input-output-hk/plutus/master/doc/read-the-docs-site/tutorials/plutus-tx.rst

You just give it the path to a file, it has various ways of selecting what chunk to include into the doc. So we can have:

  • Snippets taken from files in HLS
  • Snippets taken from an example plugin file

@cgeorgii
Copy link
Contributor Author

Yep, I'll try to do it :)

@cgeorgii
Copy link
Contributor Author

As far as I can tell the literalInclude directive is only available for the restructured text, not markdown, and I don't want to do it in this PR. I suggest we create a follow-up issue for this and I'll focus on finishing the rewrite.

@fendor
Copy link
Collaborator

fendor commented Jun 14, 2023

That sounds good to me!

docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved

Providers are functions that receive some inputs and produce an IO computation that returns either an error or some result.
> **Note**: Check the [LSP spec](https://microsoft.github.io/language-server-protocol/specification) for a deeper understanding of how commands work.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason I like RST: proper support for admonitions like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an issue to track this.

docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
### The command handler

Our plugin provider has two components that need to be fleshed out. Let's start with the command provider, since it's the simplest of the two.
The most important (and still `undefined`) field is `commandFunc :: CommandFunction`, another type synonym from `LSP.Types`:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The most important (and still `undefined`) field is `commandFunc :: CommandFunction`, another type synonym from `LSP.Types`:
The most important (and still `undefined`) field is `commandFunc :: CommandFunction`, a type synonym from `LSP.Types`:

docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
docs/contributing/plugin-tutorial.md Outdated Show resolved Hide resolved
Copy link
Collaborator

@VeryMilkyJoe VeryMilkyJoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thank you! I read until the TODO section and only marked some grammar mistakes.


- The `ormolu`, `fourmolu`, `floskell` and `stylish-haskell` plugins
- The `eval` plugin, a code lens provider to evaluate code in comments
- The `retrie` plugin, a code actions provider to execute retrie commands
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- The `retrie` plugin, a code actions provider to execute retrie commands
- The `retrie` plugin, a code action provider to execute retrie commands

2. Extract the actual import lists from the type checked AST,
3. Ask GHC to produce the minimal import lists for this AST,
4. For every import statement without a explicit import list, find out the minimal import list, and produce a code lens to display it together with a command to graft it on.
4. For every import statement without a explicit import list:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
4. For every import statement without a explicit import list:
4. For every import statement without an explicit import list:

Once cabal is done take a note of the location of the `haskell-language-server` binary and point your LSP client to it. In VSCode this is done by editing the "Haskell Server Executable Path" setting. This way you can simply test your changes by reloading your editor after rebuilding the binary.

![Settings](settings-vscode.png)
Make sure you use the HLS package you just built by following [this section](https://haskell-language-server.readthedocs.io/en/latest/contributing/contributing.html#manually-testing-your-hacked-hls) of the "Contributing" guide.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Make sure you use the HLS package you just built by following [this section](https://haskell-language-server.readthedocs.io/en/latest/contributing/contributing.html#manually-testing-your-hacked-hls) of the "Contributing" guide.
Make sure you use the HLS package you just built by following [this section](https://haskell-language-server.readthedocs.io/en/latest/contributing/contributing.html#manually-testing-your-hacked-hls) of the Contributing section.

For consistency, since the Contributing section is also mentioned above.

* Commands are an LSP abstraction for actions initiated by the user which are handled in the server. These actions can be long running and involve multiple modules. Many plugins define command handlers.
* Providers are a query-like abstraction where the LSP client asks the server for information. These queries must be fulfilled as quickly as possible.
* Request handlers are called when an LSP client asks the server for information. These queries must be fulfilled as quickly as possible.
* Notification handlers are called by code that was not directly triggerd by an user/client.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Notification handlers are called by code that was not directly triggerd by an user/client.
* Notification handlers are called by code that was not directly triggered by a user/client.


-- | A GHC session that we reuse.
type instance RuleResult GhcSession = HscEnvEq
In short, commands works like this:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In short, commands works like this:
In short, commands work like this:

@gfarrell
Copy link

(am very interested in this, as am trying to work through the tutorial myself!)

@cgeorgii
Copy link
Contributor Author

I'll try to get back to this soon!

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.

None yet

5 participants