Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -1481,11 +1481,15 @@ test-suite hls-fourmolu-plugin-tests
fourmolu:fourmolu
build-depends:
, aeson
, containers
, filepath
, haskell-language-server:hls-fourmolu-plugin
, hls-plugin-api
, hls-test-utils == 2.13.0.0
, lens
, lsp-test
, lsp-types
, text

-----------------------------
-- ormolu plugin
Expand Down Expand Up @@ -1538,12 +1542,15 @@ test-suite hls-ormolu-plugin-tests
ormolu:ormolu
build-depends:
, aeson
, containers
, filepath
, haskell-language-server:hls-ormolu-plugin
, hls-plugin-api
, hls-test-utils == 2.13.0.0
, lens
, lsp-types
, ormolu
, text

-----------------------------
-- stylish-haskell plugin
Expand Down
7 changes: 6 additions & 1 deletion plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ provider recorder plId ideState token typ contents fp fo = ExceptT $ pluginWithI
pure $ InL $ makeDiffTextEdit contents out
ExitFailure n -> do
logWith recorder Info $ StdErr err
throwError $ PluginInternalError $ "Fourmolu failed with exit code " <> T.pack (show n)
let cleanErr = T.stripEnd err
let cliError = if T.null cleanErr
then ""
else "\n" <> cleanErr
throwError $ PluginInternalError $
"Fourmolu failed with exit code " <> T.pack (show n) <> cliError

loadConfig ::
Recorder (WithPriority LogEvent) ->
Expand Down
26 changes: 26 additions & 0 deletions plugins/hls-fourmolu-plugin/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ module Main
( main
) where

import Control.Lens ((^.))
import Data.Aeson
import qualified Data.Aeson.KeyMap as KM
import Data.Functor
import qualified Data.Map as M
import qualified Data.Text as T
import Ide.Plugin.Config
import qualified Ide.Plugin.Fourmolu as Fourmolu
import qualified Language.LSP.Protocol.Lens as L
import Language.LSP.Protocol.Types
import Language.LSP.Test
import System.FilePath
Expand All @@ -31,6 +35,28 @@ tests =
formatDoc doc (FormattingOptions 4 True Nothing Nothing Nothing)
, goldenWithFourmolu cli "uses correct operator fixities" "Fourmolu3" "formatted" $ \doc -> do
formatDoc doc (FormattingOptions 4 True Nothing Nothing Nothing)
, testCase "error message contains stderr output" $ do
let cliConfig = def {
formattingProvider = "fourmolu",
plugins = M.fromList [("fourmolu", def { plcConfig = KM.fromList ["external" .= True] })]
}
runSessionWithServer cliConfig fourmoluPlugin testDataDir $ do
doc <- openDoc "FormatError.hs" "haskell"
void waitForBuildQueue
resp <- request SMethod_TextDocumentFormatting $
DocumentFormattingParams Nothing doc (FormattingOptions 4 True Nothing Nothing Nothing)
liftIO $ case resp ^. L.result of
Left err -> do
let msg = err ^. L.message
-- Verify the error message structure:
-- 1. Contains the exit code prefix (base message intact)
assertBool ("Expected exit code prefix, got: " <> T.unpack msg)
("failed with exit code" `T.isInfixOf` msg)
-- 2. Contains a stable parse-error phrase from formatter stderr
assertBool ("Expected parse error details from stderr, got: " <> T.unpack msg)
("parse error on input" `T.isInfixOf` msg)
Right _ ->
assertFailure "Expected formatting to fail on unparsable file"
]

goldenWithFourmolu :: Bool -> TestName -> FilePath -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree
Expand Down
3 changes: 3 additions & 0 deletions plugins/hls-fourmolu-plugin/test/testdata/FormatError.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module FormatError where

foo = let x = 1 in in x
7 changes: 6 additions & 1 deletion plugins/hls-ormolu-plugin/src/Ide/Plugin/Ormolu.hs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,12 @@ provider recorder plId ideState token typ contents fp _ = ExceptT $ pluginWithIn
pure $ InL $ makeDiffTextEdit contents out
ExitFailure n -> do
logWith recorder Info $ StdErr err
throwError $ PluginInternalError $ "Ormolu failed with exit code " <> T.pack (show n)
let cleanErr = T.stripEnd err
let cliError = if T.null cleanErr
then ""
else "\n" <> cleanErr
throwError $ PluginInternalError $
"Ormolu failed with exit code " <> T.pack (show n) <> cliError

newtype CLIVersionInfo = CLIVersionInfo
{ noCabal :: Bool
Expand Down
26 changes: 26 additions & 0 deletions plugins/hls-ormolu-plugin/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ module Main
( main
) where

import Control.Lens ((^.))
import Data.Aeson
import qualified Data.Aeson.KeyMap as KM
import Data.Functor
import qualified Data.Map as M
import qualified Data.Text as T
import Ide.Plugin.Config
import qualified Ide.Plugin.Ormolu as Ormolu
import qualified Language.LSP.Protocol.Lens as L
import Language.LSP.Protocol.Types
import System.FilePath
import Test.Hls
Expand All @@ -31,6 +35,28 @@ tests = testGroup "ormolu" $
, goldenWithOrmolu cli "formats operators correctly" "Ormolu3" "formatted" $ \doc -> do
formatDoc doc (FormattingOptions 4 True Nothing Nothing Nothing)
#endif
, testCase "error message contains stderr output" $ do
let cliConfig = def {
formattingProvider = "ormolu",
plugins = M.fromList [("ormolu", def { plcConfig = KM.fromList ["external" .= True] })]
}
runSessionWithServer cliConfig ormoluPlugin testDataDir $ do
doc <- openDoc "FormatError.hs" "haskell"
void waitForBuildQueue
resp <- request SMethod_TextDocumentFormatting $
DocumentFormattingParams Nothing doc (FormattingOptions 4 True Nothing Nothing Nothing)
liftIO $ case resp ^. L.result of
Left err -> do
let msg = err ^. L.message
-- Verify the error message structure:
-- 1. Contains the exit code prefix (base message intact)
assertBool ("Expected exit code prefix, got: " <> T.unpack msg)
("failed with exit code" `T.isInfixOf` msg)
-- 2. Contains a stable parse-error phrase from formatter stderr
assertBool ("Expected parse error details from stderr, got: " <> T.unpack msg)
("parse error on input" `T.isInfixOf` msg)
Right _ ->
assertFailure "Expected formatting to fail on unparsable file"
]

goldenWithOrmolu :: Bool -> TestName -> FilePath -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree
Expand Down
3 changes: 3 additions & 0 deletions plugins/hls-ormolu-plugin/test/testdata/FormatError.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module FormatError where

foo = let x = 1 in in x
Loading