Haskell-ide-engine: How to support other formatters?

Created on 13 Oct 2019  Â·  16Comments  Â·  Source: haskell/haskell-ide-engine

Right now I think hie only supports brittany and floskell. Is it possible to support other formatters via configuration?

plugin good first issue

Most helpful comment

Thanks @fendor ! I'll try to add support for the recent Ormolu formatter, mentioned in your example.

All 16 comments

You have to add another Plugin, e.g. Ormolu.hs and register it as a formatter.
Take a look at Floskell.hs or Brittany.hs for what a formatter plugin needs to support.
Then you have to add the Plugin to basePlugins in MainHie.hs.

Hi @bolt12 , are you taking care of the issue? I'll be exploring it as well to see if I can contribute to HIE in any way. I'm not that proficient with Haskell, but I got to start somewhere! This looks easy enough at first glance 😃

@DavSanchez Please go ahead! As of now I could try and tackle this issue but it would take me a while to find time.

Maybe someone can assign you this task?

@DavSanchez If you run into any problems, feel free to ask here or on irc. At the beginning the Code-base is a bit hard to explore, so if you need any explanations or pointers, please ask!

Thanks @fendor ! I'll try to add support for the recent Ormolu formatter, mentioned in your example.

Hi guys!

At the moment I have the following code to handle the formatting with ormolu, including the handling of a possible OrmoluException:

provider :: FormattingProvider
provider contents uri typ _opts =
  pluginGetFile contents uri $ \file -> do
    let (range, selectedContents) = case typ of
          FormatText    -> (fullRange contents, contents)
          FormatRange r -> (r, extractRange r contents)

    result <- try @OrmoluException (ormolu defaultConfig file (T.unpack selectedContents))
    case result of
      Left  err -> return $ IdeResultFail (IdeError PluginError (T.pack $  "ormoluCmd: " ++ show err) Null)
      Right new -> return $ IdeResultOk [TextEdit range new]

I thought that when doing result <- ... the m Text content of MonadIO m get extracted (and, via the try function, encapsulated into an Either OrmoluException Text that I can use in the next lines to return IdeResultFail or IdeResultOk. However, the whole function definition gets a red underline and HIE complains (emphasis mine):

• Couldn't match type ‘IO’
with ‘Control.Monad.Trans.Reader.ReaderT
Haskell.Ide.Engine.PluginsIdeMonads.IdeEnv
(MultiThreadState IdeState)’
Expected type: IdeM (IdeResult [TextEdit])
Actual type: IO (IdeResult [TextEdit])

• In the expression:
pluginGetFile contents uri
$ \ file
-> do let ...
result <- try
@OrmoluException
(ormolu defaultConfig file (T.unpack selectedContents))
....
In an equation for ‘provider’:
provider contents uri typ _opts
= pluginGetFile contents uri
$ \ file
-> do let ...
....

Why does it complain about an IO type? When I try something similar from GHCi, the type of result is result :: Either OrmoluException Data.Text.Internal.Text. Maybe the case sequence used is not what it should be, causing the function to return this type instead? If that is the case, how do I transform this IO type to that IdeM type?

Thanks!

If that is the case, how do I transform this IO type to that IdeM type?

With liftIO! IdeM is IO with a bunch of transformers stacked on top to keep track of HIE-related stuff.

Alright, thank you @bubba! I'll try to check the behaviour of the code as it currently is, to see if I need to add anything else in other sections of the codebase, and then I'll write some unit tests to do more formal checking.

I see that there is a FormatSpec.hs in the test directory and that it uses Hspec, but at present HIE throws some errors there about not finding some of the modules imported in the file, Hspec included... I'll need some time to check everything out and then I'll add some new tests for Ormolu. I guess I'll be able to use CircleCI (or Travis CI, although it seems to be broken) to automate the testing at some moment?

Circleci can be used for running the tests. Easiest way is probably to open a pr, so others can already see your progress and the tests are automatically run!
Hie, especially if stack is used, does not work with multiple components. This changes when #1126 lands, but for now, it does not work.

Thanks @fendor ! I'll try testing the behaviour locally and if it seems to work I'll open the PR so it can be tested more thoroughly.

At the moment I'm trying to manually test it within VS Code. Do I need to modify VS Code's HIE extension code to be able to select ormolu as a formatter in the options drop-down menu, or is there some location within the HIE codebase itself where I need to register the new plugin? At present, I have added the plugin to MainHie.hs (both importing the module and adding the descriptor to the basePlugins list), but it doesn't appear in VS Code's options:

image

It seems like you have to actually modify https://github.com/alanz/vscode-hie-server/blob/954e0a9ecc7be4d96bc71d05c65a730e642b65a6/package.json#L87 to see the options in vscode.
However, I would suggest to hardcode the formatter in https://github.com/haskell/haskell-ide-engine/blob/9feb2eb9329dd87bca815baebee9697110b0d57f/src/Haskell/Ide/Engine/Support/HieExtras.hs#L442 to "ormolu" for local tests.

E.g.

getFormattingPlugin :: Config -> IdePlugins -> Maybe (PluginDescriptor, FormattingProvider)
getFormattingPlugin config plugins = do
  let providerName = "ormolu"
  fmtPlugin <- Map.lookup providerName (ipMap plugins)
  fmtProvider <- pluginFormattingProvider fmtPlugin
  return (fmtPlugin, fmtProvider)

ping, @alanz or @bubba Is it indeed necessary to define the available formatters in vscode-hie-server?

Hi! The local tests seem to be working for entire files, but I have encountered some errors when formatting file selections...

As I think these errors have more to do with ormolu than with HIE I have opened a separate issue there, but maybe you are interested in checking it out, just in case?

The issue is https://github.com/tweag/ormolu/issues/480

UPDATE: Ok, so currently ormolu is not designed to work with file regions. I have some options to continue:

  1. Adding a fair amount of hacking to HIE in order to make it mostly work on segments.
  2. Disabling selection formatting when setting ormolu as a formatter.

To be honest, I don't feel currently capable enough with Haskell and HIE to go with option 1, maybe in a mid-term future...

Do you recommend any course of action?

This is unfortunate.

We should probably wait for support from upstream. Hacking it in HIE does not seem like a sustainable solution. It should be possible to disable selection formatting for ormolu.

@fendor I do believe so yes, the settings screen is all defined in package.json

Ok, I guess that to disable selection formatting for ormolu I would need to disable the option that handles using FormatRange :: Range -> FormattingType in my code and also it should throw a warning on the frontends (for example, the VS Code extension), right?

In case I need to do the latter, I'm checking the VS Code extension to see where I could put the logic. If I have any doubts I'll open an issue there.

closed by #1481

Was this page helpful?
0 / 5 - 0 ratings

Related issues

masaeedu picture masaeedu  Â·  4Comments

alanz picture alanz  Â·  3Comments

fendor picture fendor  Â·  4Comments

flip111 picture flip111  Â·  4Comments

JorisBlanken picture JorisBlanken  Â·  4Comments