diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa851b03ff..84e75963d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 diff --git a/cabal.project b/cabal.project index 8b84a4a457..d406a40c36 100644 --- a/cabal.project +++ b/cabal.project @@ -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 @@ -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, diff --git a/haskell-language-server.cabal b/haskell-language-server.cabal index ce0e9797dd..acede2ec8f 100644 --- a/haskell-language-server.cabal +++ b/haskell-language-server.cabal @@ -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 @@ -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 diff --git a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs b/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs index 0f162d5af9..7615b7d2f2 100644 --- a/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs +++ b/plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs @@ -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) @@ -38,12 +39,17 @@ 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) @@ -51,7 +57,7 @@ descriptor 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 = @@ -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) @@ -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 @@ -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