Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Ormolu formatter support #1481

Merged
merged 29 commits into from
Jan 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9766a61
WIP: Adding Ormolu support
DavSanchez Oct 24, 2019
864d8d9
Drop Ormolu for GHC 8.4.x
DavSanchez Dec 18, 2019
bb57d55
Removed comment. Reworded format selection warn.
DavSanchez Dec 18, 2019
a9299d2
Better error wording for selection formatting
DavSanchez Dec 24, 2019
8082825
Removed redundant $
DavSanchez Dec 27, 2019
8c51785
Guard ormolu to only be included if GHC > 8.4
DavSanchez Dec 27, 2019
1566f47
Modified GHC version requirement to >= 8.6
DavSanchez Dec 27, 2019
04f0d8f
Throwing error for GHC < 8.6
DavSanchez Dec 27, 2019
25b84fa
corrected import System.Log.Logger
DavSanchez Dec 27, 2019
c7469c6
Removed guard for exposed file
DavSanchez Dec 27, 2019
304d692
fine-tuned noop formatter for ghc < 8.6
DavSanchez Dec 27, 2019
c6e265b
Using MonadFunctions.errorm for error logging
DavSanchez Dec 27, 2019
5d2c155
Moved imports inside GHC guard
DavSanchez Dec 27, 2019
c1c40b4
WIP: Adding test cases
DavSanchez Dec 28, 2019
1f6b1fc
Completing formatting test
DavSanchez Dec 31, 2019
fa057ca
Exposing formatting providers to ormolu test suite
DavSanchez Dec 31, 2019
bb086ed
Removed unused config function
DavSanchez Dec 31, 2019
711776c
Refactor CPP guards, complete noop for GHC < 8.6
DavSanchez Jan 4, 2020
c2daf85
Corrected unused imports and parameters
DavSanchez Jan 4, 2020
b020cfb
Corrected MonadTypes import
DavSanchez Jan 4, 2020
500e2ea
Removed MonadFunctions (errorm no longer used)
DavSanchez Jan 4, 2020
b54e1e6
Added test case for hsImport.
DavSanchez Jan 5, 2020
d81afc6
Refactor CPP guards
DavSanchez Jan 5, 2020
93ab14d
Temporal CPP guard of Ormolu hsImport test case
DavSanchez Jan 5, 2020
d139e64
Added CPP extension, pending tests for GHC < 8.6
DavSanchez Jan 5, 2020
1b3d696
Update FunctionalCodeActionsSpec.hs
DavSanchez Jan 5, 2020
0483f1c
Deleted WIP comment
DavSanchez Jan 6, 2020
ba76fab
Corrected wrong syntax
DavSanchez Jan 6, 2020
3978177
Removed CPP guards in favor of ghcVersion check
DavSanchez Jan 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/MainHie.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import Haskell.Ide.Engine.Plugin.Haddock
import Haskell.Ide.Engine.Plugin.HfaAlign
import Haskell.Ide.Engine.Plugin.HsImport
import Haskell.Ide.Engine.Plugin.Liquid
import Haskell.Ide.Engine.Plugin.Ormolu
import Haskell.Ide.Engine.Plugin.Package
import Haskell.Ide.Engine.Plugin.Pragmas

Expand All @@ -63,6 +64,7 @@ plugins includeExamples = pluginDescToIdePlugins allPlugins
, floskellDescriptor "floskell"
, genericDescriptor "generic"
, ghcmodDescriptor "ghcmod"
, ormoluDescriptor "ormolu"
]
examplePlugins =
[example2Descriptor "eg2"
Expand Down
4 changes: 4 additions & 0 deletions haskell-ide-engine.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ library
Haskell.Ide.Engine.Plugin.HfaAlign
Haskell.Ide.Engine.Plugin.HsImport
Haskell.Ide.Engine.Plugin.Liquid
Haskell.Ide.Engine.Plugin.Ormolu
Haskell.Ide.Engine.Plugin.Package
Haskell.Ide.Engine.Plugin.Package.Compat
Haskell.Ide.Engine.Plugin.Pragmas
Expand All @@ -46,6 +47,7 @@ library
Haskell.Ide.Engine.Server
Haskell.Ide.Engine.Types
Haskell.Ide.Engine.Version

other-modules: Paths_haskell_ide_engine
build-depends: Cabal >= 1.22
, Diff
Expand Down Expand Up @@ -99,6 +101,8 @@ library
, bytestring-trie
, unliftio
, hlint >= 2.2.2
if impl(ghc >= 8.6)
build-depends: ormolu

ghc-options: -Wall -Wredundant-constraints
if flag(pedantic)
Expand Down
46 changes: 46 additions & 0 deletions src/Haskell/Ide/Engine/Plugin/Ormolu.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}

module Haskell.Ide.Engine.Plugin.Ormolu ( ormoluDescriptor ) where

import Haskell.Ide.Engine.MonadTypes

#if __GLASGOW_HASKELL__ >= 806
import Control.Exception
import Control.Monad.IO.Class ( liftIO , MonadIO(..) )
import Data.Aeson ( Value ( Null ) )
import Data.Text
import Ormolu
import Ormolu.Config (defaultConfig)
import Ormolu.Exception (OrmoluException)
import Haskell.Ide.Engine.PluginUtils
#endif

ormoluDescriptor :: PluginId -> PluginDescriptor
ormoluDescriptor plId = PluginDescriptor
{ pluginId = plId
, pluginName = "Ormolu"
, pluginDesc = "A formatter for Haskell source code."
, pluginCommands = []
, pluginCodeActionProvider = Nothing
, pluginDiagnosticProvider = Nothing
, pluginHoverProvider = Nothing
, pluginSymbolProvider = Nothing
, pluginFormattingProvider = Just provider
}


provider :: FormattingProvider
provider _contents _uri _typ _opts =
#if __GLASGOW_HASKELL__ >= 806
case _typ of
FormatRange _ -> return $ IdeResultFail (IdeError PluginError (pack "Selection formatting for Ormolu is not currently supported.") Null)
FormatText -> pluginGetFile _contents _uri $ \file -> do
result <- liftIO $ try @OrmoluException (ormolu defaultConfig file (unpack _contents))
case result of
Left err -> return $ IdeResultFail (IdeError PluginError (pack $ "ormoluCmd: " ++ show err) Null)
Right new -> return $ IdeResultOk [TextEdit (fullRange _contents) new]
#else
return $ IdeResultOk [] -- NOP formatter
#endif
1 change: 1 addition & 0 deletions stack-8.6.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extra-deps:
- monoid-subclasses-0.4.6.1
- multistate-0.8.0.1
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- primes-0.2.1.0
- resolv-0.1.1.2
- rope-utf16-splay-0.3.1.0
Expand Down
1 change: 1 addition & 0 deletions stack-8.6.2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extra-deps:
- monad-memo-0.4.1
- multistate-0.8.0.1
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- rope-utf16-splay-0.3.1.0
- strict-list-0.1.5
- syz-0.2.0.0
Expand Down
1 change: 1 addition & 0 deletions stack-8.6.3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extra-deps:
- multistate-0.8.0.1
- optparse-simple-0.1.0
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- rope-utf16-splay-0.3.1.0
- syz-0.2.0.0
- temporary-1.2.1.1
Expand Down
1 change: 1 addition & 0 deletions stack-8.6.4.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extra-deps:
- monad-memo-0.4.1
- multistate-0.8.0.1
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- rope-utf16-splay-0.3.1.0
- syz-0.2.0.0
- temporary-1.2.1.1
Expand Down
1 change: 1 addition & 0 deletions stack-8.6.5.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extra-deps:
- lsp-test-0.10.0.0
- monad-dijkstra-0.1.1.2@rev:1
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- syz-0.2.0.0
- temporary-1.2.1.1

Expand Down
1 change: 1 addition & 0 deletions stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extra-deps:
- lsp-test-0.10.0.0
- monad-dijkstra-0.1.1.2@rev:1
- parser-combinators-1.2.1
- ormolu-0.0.2.0
- syz-0.2.0.0
- temporary-1.2.1.1
- unix-compat-0.5.2
Expand Down
38 changes: 38 additions & 0 deletions test/functional/FormatSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ spec = do
liftIO $ edits `shouldBe` [TextEdit (Range (Position 1 0) (Position 3 0))
"foo x y = do\n print x\n return 42\n"]

describe "ormolu" $ do
let formatLspConfig provider =
object [ "languageServerHaskell" .= object ["formattingProvider" .= (provider :: Value)] ]

it "formats correctly" $ runSession hieCommand fullCaps "test/testdata" $ do
sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams (formatLspConfig "ormolu"))
doc <- openDoc "Format.hs" "haskell"
formatDoc doc (FormattingOptions 2 True)
docContent <- documentContents doc
case ghcVersion of
GHC86 -> liftIO $ docContent `shouldBe` formattedOrmolu
_ -> liftIO $ docContent `shouldBe` unchangedOrmolu


formattedDocTabSize2 :: T.Text
formattedDocTabSize2 =
Expand Down Expand Up @@ -165,3 +178,28 @@ formattedBrittanyPostFloskell =
\bar s = do\n\
\ x <- return \"hello\"\n\
\ return \"asdf\"\n\n"

formattedOrmolu :: T.Text
formattedOrmolu =
"module Format where\n\
\\n\
\foo :: Int -> Int\n\
\foo 3 = 2\n\
\foo x = x\n\
\\n\
\bar :: String -> IO String\n\
\bar s = do\n\
\ x <- return \"hello\"\n\
\ return \"asdf\"\n"

unchangedOrmolu :: T.Text
unchangedOrmolu =
"module Format where\n\
\foo :: Int -> Int\n\
\foo 3 = 2\n\
\foo x = x\n\
\bar :: String -> IO String\n\
\bar s = do\n\
\ x <- return \"hello\"\n\
\ return \"asdf\"\n\
\ \n"
44 changes: 44 additions & 0 deletions test/functional/FunctionalCodeActionsSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,50 @@ spec = describe "code actions" $ do
, " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")"
]
]
describe "formats with ormolu" $
case ghcVersion of
GHC86 -> hsImportSpec "ormolu"
[ -- Expected output for simple format.
[ "import Control.Monad"
, "import qualified Data.Maybe"
, "main :: IO ()"
, "main = when True $ putStrLn \"hello\""
]
, -- Use an import list and format the output.
[ "import Control.Monad (when)"
, "import qualified Data.Maybe"
, "main :: IO ()"
, "main = when True $ putStrLn \"hello\""
]
, -- Multiple import lists, should not introduce multiple newlines.
[ "import System.IO (hPutStrLn, stdout)"
, "import Control.Monad (when)"
, "import Data.Maybe (fromMaybe)"
, "-- | Main entry point to the program"
, "main :: IO ()"
, "main ="
, " when True"
, " $ hPutStrLn stdout"
, " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")"
]
, -- Complex imports for Constructos and functions
[ "{-# LANGUAGE NoImplicitPrelude #-}"
, "import System.IO (IO, hPutStrLn, stderr)"
, "import Prelude (Bool (..))"
, "import Control.Monad (when)"
, "import Data.Function (($))"
, "import Data.Maybe (Maybe (Just), fromMaybe)"
, "-- | Main entry point to the program"
, "main :: IO ()"
, "main ="
, " when True"
, " $ hPutStrLn stderr"
, " $ fromMaybe \"Good night, World!\" (Just \"Hello, World!\")"
]
]
_ -> it "is NOP formatter" $
pendingWith "Ormolu only supported by GHC >= 8.6. Need to restore this."

describe "add package suggestions" $ do
it "adds to .cabal files" $ do
flushStackEnvironment
Expand Down