{-# LANGUAGE OverloadedStrings #-} module Config (tests) where import Control.Lens hiding (List, (.=)) import Control.Monad import Data.Aeson import qualified Data.Map as Map import qualified Data.Text as T import Ide.Plugin.Config import qualified Ide.Plugin.Config as Plugin import Language.LSP.Test as Test import qualified Language.LSP.Types.Lens as L import System.FilePath (()) import Test.Hls import Test.Hls.Command {-# ANN module ("HLint: ignore Reduce duplication"::String) #-} tests :: TestTree tests = testGroup "plugin config" [ -- Note: because the flag is treated generically in the plugin handler, we -- do not have to test each individual plugin hlintTests , configTests ] hlintTests :: TestTree hlintTests = testGroup "hlint plugin enables" [ testCase "changing hlintOn configuration enables or disables hlint diagnostics" $ runHlintSession "" $ do let config = def { hlintOn = True } sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) doc <- openDoc "ApplyRefact2.hs" "haskell" testHlintDiagnostics doc let config' = def { hlintOn = False } sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config')) diags' <- waitForDiagnosticsFrom doc liftIO $ noHlintDiagnostics diags' , testCase "changing hlint plugin configuration enables or disables hlint diagnostics" $ runHlintSession "" $ do let config = def { hlintOn = True } sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) doc <- openDoc "ApplyRefact2.hs" "haskell" testHlintDiagnostics doc let config' = pluginGlobalOn config "hlint" False sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config')) diags' <- waitForDiagnosticsFrom doc liftIO $ noHlintDiagnostics diags' , testCase "adding hlint flags to plugin configuration removes hlint diagnostics" $ runHlintSession "" $ do let config = def { hlintOn = True } sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) doc <- openDoc "ApplyRefact2.hs" "haskell" testHlintDiagnostics doc let config' = hlintConfigWithFlags ["--ignore=Redundant id", "--hint=test-hlint-config.yaml"] sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config')) diags' <- waitForDiagnosticsFrom doc liftIO $ noHlintDiagnostics diags' , testCase "adding hlint flags to plugin configuration adds hlint diagnostics" $ runHlintSession "" $ do let config = def { hlintOn = True } sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) doc <- openDoc "ApplyRefact7.hs" "haskell" expectNoMoreDiagnostics 3 doc "hlint" let config' = hlintConfigWithFlags ["--with-group=generalise"] sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config')) diags' <- waitForDiagnosticsFromSource doc "hlint" d <- liftIO $ inspectDiagnostic diags' ["Use <>"] liftIO $ do length diags' @?= 1 d ^. L.range @?= Range (Position 1 10) (Position 1 21) d ^. L.severity @?= Just DsInfo ] where runHlintSession :: FilePath -> Session a -> IO a runHlintSession subdir = failIfSessionTimeout . runSession hlsCommand fullCaps ("test/testdata/hlint" subdir) noHlintDiagnostics :: [Diagnostic] -> Assertion noHlintDiagnostics diags = Just "hlint" `notElem` map (^. L.source) diags @? "There are no hlint diagnostics" testHlintDiagnostics doc = do diags <- waitForDiagnosticsFromSource doc "hlint" liftIO $ length diags > 0 @? "There are hlint diagnostics" configTests :: TestTree configTests = testGroup "config parsing" [ testCase "empty object as user configuration should not send error logMessage" $ runConfigSession "" $ do let config = object [] sendNotification SWorkspaceDidChangeConfiguration (DidChangeConfigurationParams (toJSON config)) -- Send custom request so server returns a response to prevent blocking void $ sendNotification (SCustomMethod "non-existent-method") Null logNot <- skipManyTill Test.anyMessage (message SWindowLogMessage) liftIO $ (logNot ^. L.params . L.xtype) > MtError || "non-existent-method" `T.isInfixOf` (logNot ^. L.params . L.message) @? "Server sends logMessage with MessageType = Error" ] where runConfigSession :: FilePath -> Session a -> IO a runConfigSession subdir = failIfSessionTimeout . runSession hlsCommand fullCaps ("test/testdata" subdir) pluginGlobalOn :: Config -> T.Text -> Bool -> Config pluginGlobalOn config pid state = config' where pluginConfig = def { plcGlobalOn = state } config' = def { plugins = Map.insert pid pluginConfig (plugins config) } hlintConfigWithFlags :: [T.Text] -> Config hlintConfigWithFlags flags = def { hlintOn = True , Plugin.plugins = Map.fromList [("hlint", def { Plugin.plcConfig = unObject $ object ["flags" .= flags] } )] } where unObject (Object obj) = obj unObject _ = undefined