haskell / haskell-language-server

Official haskell ide support via language server (LSP). Successor of ghcide & haskell-ide-engine.
Apache License 2.0
2.71k stars 368 forks source link

Inconsistency in Ormolu formatting #213

Closed sir4ur0n closed 4 years ago

sir4ur0n commented 4 years ago

Hey, sorry for opening yet another issue, I kinda feel guilty :sweat_smile: I noticed what appears to be a bug, and I took the opportunity to ask additional formatter-related questions, I can push them to other issues if it's simpler for you to manage.

I just tested in VS Code "Format document", which I assume relies on Ormolu (I configured the Ormolu formatter in languageServerHaskell.formattingProvider).

1 - Format is bugged, and inconsistent

We see an inconsistency between applying "Format" from HLS (in VS Code) or applying Ormolu directly in CLI.

Consider this code:

module Foo where

import Prelude
import GHC.Generics (Generic)
import Data.Text (Text)

data Foo
  = Foo
      { _name :: Text,
        _description :: Maybe Text
      }
  deriving (Generic, Show, Eq)

Applying reformatting from VS Code (and I checked in HLS Output view that it uses Ormolu), this gets reformatted as such:

module Foo where

import GHC.Generics (Generic)
import Prelude
import Data.Text (Text)

data Foo = Foo
  { _name :: Text,
    _description :: Maybe Text
  }
  deriving (Generic, Show, Eq)

Note in particular that import order was modified, yet it's not completely alphabetical

Now run the formatter again in VS Code (yes, without modifying anything) and the second time, import order is correct! :boom:

module Foo where

import Data.Text (Text)
import GHC.Generics (Generic)
import Prelude

data Foo = Foo
  { _name :: Text,
    _description :: Maybe Text
  }
  deriving (Generic, Show, Eq)

Now when running Ormolu in CLI, the original piece of code gets reformatted to:

module Foo where

import Data.Text (Text)
import GHC.Generics (Generic)
import Prelude

data Foo = Foo
  { _name :: Text,
    _description :: Maybe Text
  }
  deriving (Generic, Show, Eq)

i.e. Ormolu in CLI run once behaves the same as formatting twice in a row in VS Code :boom:

Edit: the situation seems to be even worse. Here's an additional example:

import Data.Text (Text)
import GHC.Generics (Generic)
import Prelude
import Data.Time.Calendar
import Data.Aeson

Even after 50 reformats, the import order remains:

import Data.Aeson
import Data.Text (Text)
import GHC.Generics (Generic)
import Data.Time.Calendar
import Prelude

While Ormolu in CLI correctly returns:

import Data.Aeson
import Data.Text (Text)
import Data.Time.Calendar
import GHC.Generics (Generic)
import Prelude

2 - Is it a packaged version of Ormolu, or does it use the path one?

3 - Custom options

If I am correct, how would one pass custom options to Ormolu, like --ghc-opt -XBangPatterns? So far we were using Nix + a custom shell wrapper to force our own options as such:

ormolu-wrapped = symlinkJoin {
  name = "ormolu";
  paths = [ ormolu ];
  buildInputs = [ pkgs.makeWrapper ];
  postBuild = ''
    wrapProgram $out/bin/ormolu \
      --add-flags "\
        --ghc-opt -XBangPatterns \
        --ghc-opt -XTypeApplications \
      "
  '';
};

Would this still work/get picked up by HLS?

4 - Formatter (plugins) versions in HLS logs

Shouldn't the HLS logs display the formatter version? Currently there's no way to know which one is picked/used I think the perfect opportunity would be at startup while listing plugins:

Starting (haskell-language-server)LSP server...
  with arguments: Arguments {argLSP = True, argsCwd = Nothing, argFiles = [], argsVersion = False, argsShakeProfiling = Nothing, argsTesting = False, argsExamplePlugin = False, argsDebugOn = False, argsLogFile = Nothing, argsThreads = 0}
  with plugins: [PluginId "brittany",PluginId "floskell",PluginId "ghcide",PluginId "ormolu",PluginId "pragmas",PluginId "stylish-haskell"]

Thank you again for the help, quick replies, and overall support :pray: Let me know if I can help (with my modest understanding of this project)

fendor commented 4 years ago

Hi! Thank you for this nice bug report and you should not guilty at all! It is nice to get such detailed bug reports.

I dont have details, just the following Information:

jneira commented 4 years ago

Shouldn't the HLS logs display the formatter version? Currently there's no way to know which one is picked/used I think the perfect opportunity would be at startup while listing plugins

That is a good idea. Anyway the ourmulu version used in master would be 0.1.2.0, you can check it in the .cabal file:

https://github.com/haskell/haskell-language-server/blob/037e7fe670bde18f78a41ef429421bb2dd7ac25c/haskell-language-server.cabal#L81

... having in account that there is no version greater than 0.1.2.0 (https://hackage.haskell.org/package/ormolu)