Skip to content

Commit

Permalink
Add support for Fourmolu 0.16 (haskell#4314)
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonchinn178 authored Jun 14, 2024
1 parent 426b068 commit 4b344d3
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 42 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ jobs:
name: Test hls-ormolu-plugin
run: cabal test hls-ormolu-plugin-tests || cabal test hls-ormolu-plugin-tests

# TODO enable when it supports 9.10
- if: matrix.test && matrix.ghc != '9.10'
- if: matrix.test
name: Test hls-fourmolu-plugin
run: cabal test hls-fourmolu-plugin-tests || cabal test hls-fourmolu-plugin-tests

Expand Down
5 changes: 2 additions & 3 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ packages:
./hls-plugin-api
./hls-test-utils

index-state: 2024-06-10T12:08:58Z
index-state: 2024-06-13T17:12:34Z

tests: True
test-show-details: direct
Expand Down Expand Up @@ -49,10 +49,9 @@ if impl(ghc >= 9.9)
lens >= 5.3.2,
-- See
-- https://github.com/haskell/stylish-haskell/issues/479
-- https://github.com/fourmolu/fourmolu/issues/412
-- https://github.com/ennocramer/floskell/pull/82
-- https://github.com/ndmitchell/hlint/pull/1594
haskell-language-server -stylishHaskell -fourmolu -hlint -retrie -splice -floskell,
haskell-language-server -stylishHaskell -hlint -retrie -splice -floskell,
allow-newer:
entropy:base,
entropy:directory,
Expand Down
4 changes: 2 additions & 2 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,7 @@ library hls-fourmolu-plugin
build-depends:
, base >=4.12 && <5
, filepath
, fourmolu ^>= 0.14 || ^>= 0.15
, fourmolu ^>= 0.14 || ^>= 0.15 || ^>= 0.16
, ghc-boot-th
, ghcide == 2.8.0.0
, hls-plugin-api == 2.8.0.0
Expand All @@ -1470,7 +1470,7 @@ library hls-fourmolu-plugin
, process-extras >= 0.7.1
, text
, transformers

, yaml

test-suite hls-fourmolu-plugin-tests
import: defaults, pedantic, test-defaults, warnings
Expand Down
95 changes: 60 additions & 35 deletions plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Data.List (intercalate)
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Version (showVersion)
import Development.IDE hiding (pluginHandlers)
import Development.IDE.GHC.Compat as Compat hiding (Cpp, Warning,
hang, vcat)
Expand All @@ -38,20 +39,25 @@ import Language.LSP.Protocol.Types
import Language.LSP.Server hiding (defaultConfig)
import Ormolu
import Ormolu.Config
import qualified Paths_fourmolu as Fourmolu
import System.Exit
import System.FilePath
import System.Process.Run (cwd, proc)
import System.Process.Text (readCreateProcessWithExitCode)
import Text.Read (readMaybe)

#if MIN_VERSION_fourmolu(0,16,0)
import qualified Data.Yaml as Yaml
#endif

descriptor :: Recorder (WithPriority LogEvent) -> PluginId -> PluginDescriptor IdeState
descriptor recorder plId =
(defaultPluginDescriptor plId desc)
{ pluginHandlers = mkFormattingHandlers $ provider recorder plId
, pluginConfigDescriptor = defaultConfigDescriptor{configCustomConfig = mkCustomConfig properties}
}
where
desc = "Provides formatting of Haskell files via fourmolu. Built with fourmolu-" <> VERSION_fourmolu
desc = T.pack $ "Provides formatting of Haskell files via fourmolu. Built with fourmolu-" <> showVersion Fourmolu.version

properties :: Properties '[ 'PropertyKey "external" 'TBoolean, 'PropertyKey "path" 'TString]
properties =
Expand All @@ -77,36 +83,17 @@ provider recorder plId ideState token typ contents fp fo = ExceptT $ pluginWithI
handle @IOException (pure . Left . PluginInternalError . T.pack . show) $
runExceptT (cliHandler fourmoluExePath fileOpts)
else do
logWith recorder Debug $ LogCompiledInVersion VERSION_fourmolu
FourmoluConfig{..} <-
liftIO (loadConfigFile fp') >>= \case
ConfigLoaded file opts -> do
logWith recorder Info $ ConfigPath file
pure opts
ConfigNotFound searchDirs -> do
logWith recorder Info $ NoConfigPath searchDirs
pure emptyConfig
ConfigParseError f err -> do
lift $ pluginSendNotification SMethod_WindowShowMessage $
ShowMessageParams
{ _type_ = MessageType_Error
, _message = errorMessage
}
throwError $ PluginInternalError errorMessage
where
errorMessage = "Failed to load " <> T.pack f <> ": " <> T.pack (show err)

logWith recorder Debug $ LogCompiledInVersion (showVersion Fourmolu.version)
FourmoluConfig{..} <- loadConfig recorder fp'
let config =
#if MIN_VERSION_fourmolu(0,13,0)
refineConfig ModuleSource Nothing Nothing Nothing
#endif
defaultConfig
{ cfgDynOptions = map DynOption fileOpts
, cfgFixityOverrides = cfgFileFixities
, cfgRegion = region
, cfgDebug = False
, cfgPrinterOpts = resolvePrinterOpts [lspPrinterOpts, cfgFilePrinterOpts]
}
refineConfig ModuleSource Nothing Nothing Nothing $
defaultConfig
{ cfgDynOptions = map DynOption fileOpts
, cfgFixityOverrides = cfgFileFixities
, cfgRegion = region
, cfgDebug = False
, cfgPrinterOpts = resolvePrinterOpts [lspPrinterOpts, cfgFilePrinterOpts]
}
ExceptT . liftIO $
bimap (PluginInternalError . T.pack . show) (InL . makeDiffTextEdit contents)
<$> try @OrmoluException (ormolu config fp' contents)
Expand Down Expand Up @@ -158,6 +145,49 @@ provider recorder plId ideState token typ contents fp fo = ExceptT $ pluginWithI
logWith recorder Info $ StdErr err
throwError $ PluginInternalError $ "Fourmolu failed with exit code " <> T.pack (show n)

loadConfig ::
Recorder (WithPriority LogEvent) ->
FilePath ->
ExceptT PluginError (HandlerM Ide.Types.Config) FourmoluConfig
#if MIN_VERSION_fourmolu(0,16,0)
loadConfig recorder fp = do
liftIO (findConfigFile fp) >>= \case
Left (ConfigNotFound searchDirs) -> do
logWith recorder Info $ NoConfigPath searchDirs
pure emptyConfig
Right file -> do
logWith recorder Info $ ConfigPath file
liftIO (Yaml.decodeFileEither file) >>= \case
Left err -> do
let errorMessage = "Failed to load " <> T.pack file <> ": " <> T.pack (show err)
lift $ pluginSendNotification SMethod_WindowShowMessage $
ShowMessageParams
{ _type_ = MessageType_Error
, _message = errorMessage
}
throwError $ PluginInternalError errorMessage
Right cfg -> do
pure cfg
#else
loadConfig recorder fp = do
liftIO (loadConfigFile fp) >>= \case
ConfigLoaded file opts -> do
logWith recorder Info $ ConfigPath file
pure opts
ConfigNotFound searchDirs -> do
logWith recorder Info $ NoConfigPath searchDirs
pure emptyConfig
ConfigParseError f err -> do
lift $ pluginSendNotification SMethod_WindowShowMessage $
ShowMessageParams
{ _type_ = MessageType_Error
, _message = errorMessage
}
throwError $ PluginInternalError errorMessage
where
errorMessage = "Failed to load " <> T.pack f <> ": " <> T.pack (show err)
#endif

data LogEvent
= NoVersion Text
| ConfigPath FilePath
Expand Down Expand Up @@ -197,8 +227,3 @@ newtype CLIVersionInfo = CLIVersionInfo

mwhen :: Monoid a => Bool -> a -> a
mwhen b x = if b then x else mempty

#if !MIN_VERSION_fourmolu(0,14,0)
resolvePrinterOpts :: [PrinterOptsPartial] -> PrinterOptsTotal
resolvePrinterOpts = foldr fillMissingPrinterOpts defaultPrinterOpts
#endif

0 comments on commit 4b344d3

Please sign in to comment.