haskell-language-server 2.5.0.0 → 2.6.0.0
raw patch · 14 files changed
+259/−87 lines, 14 filesdep +hls-semantic-tokens-plugindep −hspec-expectationsdep ~ghcidedep ~hls-alternate-number-format-plugindep ~hls-cabal-fmt-pluginPVP ok
version bump matches the API change (PVP)
Dependencies added: hls-semantic-tokens-plugin
Dependencies removed: hspec-expectations
Dependency ranges changed: ghcide, hls-alternate-number-format-plugin, hls-cabal-fmt-plugin, hls-cabal-plugin, hls-call-hierarchy-plugin, hls-change-type-signature-plugin, hls-class-plugin, hls-code-range-plugin, hls-eval-plugin, hls-explicit-fixity-plugin, hls-explicit-imports-plugin, hls-explicit-record-fields-plugin, hls-floskell-plugin, hls-fourmolu-plugin, hls-gadt-plugin, hls-hlint-plugin, hls-module-name-plugin, hls-ormolu-plugin, hls-overloaded-record-dot-plugin, hls-plugin-api, hls-pragmas-plugin, hls-qualify-imported-names-plugin, hls-refactor-plugin, hls-rename-plugin, hls-retrie-plugin, hls-splice-plugin, hls-stan-plugin, hls-stylish-haskell-plugin, hls-test-utils
API changes (from Hackage documentation)
Files
- ChangeLog.md +82/−0
- exe/Main.hs +7/−7
- exe/Wrapper.hs +19/−20
- haskell-language-server.cabal +47/−35
- src/HlsPlugins.hs +8/−0
- src/Ide/Main.hs +13/−8
- test/functional/Config.hs +1/−1
- test/functional/ConfigSchema.hs +49/−0
- test/functional/Format.hs +3/−3
- test/functional/FunctionalBadProject.hs +3/−3
- test/functional/HieBios.hs +1/−1
- test/functional/Main.hs +2/−0
- test/functional/Progress.hs +4/−4
- test/utils/Test/Hls/Command.hs +20/−5
@@ -1,5 +1,87 @@ # Changelog for haskell-language-server +## 2.6.0.0++- Bindists for GHC 9.6.4+- A new semantic tokens plugin (#3892, @soulomoon).+- Improvements to multiple home unit support with GHC 9.4. Using cabal 3.11+ will+ load proper multiple home unit sessions by default, fixing a lot of issues with+ loading and reloading projects that have more than one component (#3462, @wz1000).+- Removed implicit-hie, resulting in better behaviour for projects without cradles.+- Don't produce diagnostics for disabled plugins (#3941, @fendor).+- Many other bug fixes.++### Pull Requests++- fix: semantic token omitting record field in `{-# LANGUAGE DuplicateRecordFields #-}` #3950+ ([#3951](https://github.com/haskell/haskell-language-server/pull/3951)) by @soulomoon+- Properties API: Remove unsafe coerce in favor of type class based method in + ([#3947](https://github.com/haskell/haskell-language-server/pull/3947)) by @soulomoon+- Bump to hiedb 0.5.0.0 to fix #3542+ ([#3943](https://github.com/haskell/haskell-language-server/pull/3943)) by @wz1000+- Don't produce diagnostics if plugin is turned off+ ([#3941](https://github.com/haskell/haskell-language-server/pull/3941)) by @fendor+- add config for semantic-tokens-plugin for mapping from hs token type to LSP default token type+ ([#3940](https://github.com/haskell/haskell-language-server/pull/3940)) by @soulomoon+- add doc and ci test for semantic tokens+ ([#3938](https://github.com/haskell/haskell-language-server/pull/3938)) by @soulomoon+- update Floskell to 0.11.*+ ([#3933](https://github.com/haskell/haskell-language-server/pull/3933)) by @peterbecich+- Remove some people from CODEOWNERS+ ([#3930](https://github.com/haskell/haskell-language-server/pull/3930)) by @michaelpj+- Adapt to minor API change for 9.6.4 compatibility+ ([#3929](https://github.com/haskell/haskell-language-server/pull/3929)) by @wz1000+- Fix multi unit session when some packages have reexported modules.+ ([#3928](https://github.com/haskell/haskell-language-server/pull/3928)) by @wz1000+- Switch to haskell-actions/setup since haskell/actions is deprecated+ ([#3926](https://github.com/haskell/haskell-language-server/pull/3926)) by @fendor+- Make vscode-extension-schema honour default values+ ([#3925](https://github.com/haskell/haskell-language-server/pull/3925)) by @fendor+- Add golden tests for public configs+ ([#3922](https://github.com/haskell/haskell-language-server/pull/3922)) by @fendor+- Bump geekyeggo/delete-artifact from 2 to 4+ ([#3921](https://github.com/haskell/haskell-language-server/pull/3921)) by @dependabot[bot]+- Fix positionMapping in stale data+ ([#3920](https://github.com/haskell/haskell-language-server/pull/3920)) by @soulomoon+- Disable stan plugin by default+ ([#3917](https://github.com/haskell/haskell-language-server/pull/3917)) by @fendor+- Use stan config files for stan plugin (#3904)+ ([#3914](https://github.com/haskell/haskell-language-server/pull/3914)) by @0rphee+- Bump both upload and download artifact+ ([#3913](https://github.com/haskell/haskell-language-server/pull/3913)) by @michaelpj+- Update ghc-version-support.md for 2.5.0+ ([#3909](https://github.com/haskell/haskell-language-server/pull/3909)) by @lehmacdj+- Give plugins descriptions, include versions of key dependencies + ([#3903](https://github.com/haskell/haskell-language-server/pull/3903)) by @michaelpj+- Remove some buildability blockers that aren't needed+ ([#3899](https://github.com/haskell/haskell-language-server/pull/3899)) by @michaelpj+- Bump actions/setup-python from 4 to 5+ ([#3895](https://github.com/haskell/haskell-language-server/pull/3895)) by @dependabot[bot]+- Update index-state to get latest stan version+ ([#3894](https://github.com/haskell/haskell-language-server/pull/3894)) by @0rphee+- Generate FileTarget for all possible targetLocations+ ([#3893](https://github.com/haskell/haskell-language-server/pull/3893)) by @fendor+- Implement semantic tokens plugin to support semantic highlighting(textDocument/semanticTokens/full)+ ([#3892](https://github.com/haskell/haskell-language-server/pull/3892)) by @soulomoon+- session-loader: Set working directory on GHC 9.4++ ([#3891](https://github.com/haskell/haskell-language-server/pull/3891)) by @wz1000+- Demote home unit closure errors to warnings.+ ([#3890](https://github.com/haskell/haskell-language-server/pull/3890)) by @wz1000+- Bump cachix/install-nix-action from 23 to 24+ ([#3889](https://github.com/haskell/haskell-language-server/pull/3889)) by @dependabot[bot]+- Bump cachix/cachix-action from 12 to 13+ ([#3888](https://github.com/haskell/haskell-language-server/pull/3888)) by @dependabot[bot]+- Add more docs for implicit discovery+ ([#3887](https://github.com/haskell/haskell-language-server/pull/3887)) by @fendor+- Prepare release 2.5.0.0+ ([#3879](https://github.com/haskell/haskell-language-server/pull/3879)) by @wz1000+- Improve no plugin messages+ ([#3864](https://github.com/haskell/haskell-language-server/pull/3864)) by @joyfulmantis+- Add support for multi unit argument syntax+ ([#3462](https://github.com/haskell/haskell-language-server/pull/3462)) by @wz1000+- Fix completion for qualified import+ ([#2838](https://github.com/haskell/haskell-language-server/pull/2838)) by @xsebek+ ## 2.5.0.0 - Bindists for GHC 9.4.8
@@ -13,7 +13,11 @@ import Data.Functor ((<&>)) import Data.Maybe (catMaybes) import Data.Text (Text)-import Ide.Logger (Doc, Priority (Error, Info),+import qualified HlsPlugins as Plugins+import Ide.Arguments (Arguments (..),+ GhcideArguments (..),+ getArguments)+import Ide.Logger (Doc, Priority (Error, Info), Recorder, WithPriority (WithPriority, priority), cfilter, cmapWithPrio,@@ -21,11 +25,7 @@ layoutPretty, logWith, makeDefaultStderrRecorder, renderStrict, withFileRecorder)-import qualified Ide.Logger as Logger-import qualified HlsPlugins as Plugins-import Ide.Arguments (Arguments (..),- GhcideArguments (..),- getArguments)+import qualified Ide.Logger as Logger import Ide.Main (defaultMain) import qualified Ide.Main as IdeMain import Ide.PluginUtils (pluginDescToIdePlugins)@@ -70,7 +70,7 @@ ]) -- This plugin just installs a handler for the `initialized` notification, which then -- picks up the LSP environment and feeds it to our recorders- let lspRecorderPlugin = (defaultPluginDescriptor "LSPRecorderCallback")+ let lspRecorderPlugin = (defaultPluginDescriptor "LSPRecorderCallback" "Internal plugin") { pluginNotificationHandlers = mkPluginNotificationHandler LSP.SMethod_Initialized $ \_ _ _ _ -> do env <- LSP.getLspEnv liftIO $ (cb1 <> cb2) env
@@ -51,8 +51,7 @@ Recorder (logger_), WithPriority (WithPriority), cmapWithPrio,- makeDefaultStderrRecorder,- toCologActionWithPrio)+ makeDefaultStderrRecorder) import Ide.Plugin.Config (Config) import Ide.Types (IdePlugins (IdePlugins)) import Language.LSP.Protocol.Message (Method (Method_Initialize),@@ -83,8 +82,8 @@ putStrLn "Tool versions found on the $PATH" putStrLn $ showProgramVersionOfInterest programsOfInterest putStrLn "Tool versions in your project"- cradle <- findProjectCradle' False- ghcVersion <- runExceptT $ getRuntimeGhcVersion' recorder cradle+ cradle <- findProjectCradle' recorder False+ ghcVersion <- runExceptT $ getRuntimeGhcVersion' cradle putStrLn $ showProgramVersion "ghc" $ mkVersion =<< eitherToMaybe ghcVersion VersionMode PrintVersion ->@@ -94,10 +93,10 @@ putStrLn haskellLanguageServerNumericVersion BiosMode PrintCradleType ->- print =<< findProjectCradle+ print =<< findProjectCradle recorder PrintLibDir -> do- cradle <- findProjectCradle' False- (CradleSuccess libdir) <- HieBios.getRuntimeGhcLibDir (toCologActionWithPrio (cmapWithPrio pretty recorder)) cradle+ cradle <- findProjectCradle' recorder False+ (CradleSuccess libdir) <- HieBios.getRuntimeGhcLibDir cradle putStr libdir _ -> launchHaskellLanguageServer recorder args >>= \case Right () -> pure ()@@ -116,7 +115,7 @@ d <- getCurrentDirectory -- search for the project cradle type- cradle <- findProjectCradle+ cradle <- findProjectCradle recorder -- Get the root directory from the cradle setCurrentDirectory $ cradleRootDir cradle@@ -124,7 +123,7 @@ case parsedArgs of Ghcide GhcideArguments{..} -> when argsProjectGhcVersion $ do- runExceptT (getRuntimeGhcVersion' recorder cradle) >>= \case+ runExceptT (getRuntimeGhcVersion' cradle) >>= \case Right ghcVersion -> putStrLn ghcVersion >> exitSuccess Left err -> T.putStrLn (prettyError err NoShorten) >> exitFailure _ -> pure ()@@ -147,7 +146,7 @@ hPutStrLn stderr "Consulting the cradle to get project GHC version..." runExceptT $ do- ghcVersion <- getRuntimeGhcVersion' recorder cradle+ ghcVersion <- getRuntimeGhcVersion' cradle liftIO $ hPutStrLn stderr $ "Project GHC version: " ++ ghcVersion let@@ -172,10 +171,10 @@ let cradleName = actionName (cradleOptsProg cradle) -- we need to be compatible with NoImplicitPrelude- ghcBinary <- liftIO (fmap trim <$> runGhcCmd (toCologActionWithPrio (cmapWithPrio pretty recorder)) ["-v0", "-package-env=-", "-ignore-dot-ghci", "-e", "Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)"])+ ghcBinary <- liftIO (fmap trim <$> runGhcCmd ["-v0", "-package-env=-", "-ignore-dot-ghci", "-e", "Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)"]) >>= cradleResult cradleName - libdir <- liftIO (HieBios.getRuntimeGhcLibDir (toCologActionWithPrio (cmapWithPrio pretty recorder)) cradle)+ libdir <- liftIO (HieBios.getRuntimeGhcLibDir cradle) >>= cradleResult cradleName env <- Map.fromList <$> liftIO getEnvironment@@ -192,8 +191,8 @@ -- | Version of 'getRuntimeGhcVersion' that dies if we can't get it, and also -- checks to see if the tool is missing if it is one of-getRuntimeGhcVersion' :: Recorder (WithPriority (Doc ())) -> Cradle Void -> ExceptT WrapperSetupError IO String-getRuntimeGhcVersion' recorder cradle = do+getRuntimeGhcVersion' :: Cradle Void -> ExceptT WrapperSetupError IO String+getRuntimeGhcVersion' cradle = do let cradleName = actionName (cradleOptsProg cradle) -- See if the tool is installed@@ -204,7 +203,7 @@ Direct -> checkToolExists "ghc" _ -> pure () - ghcVersionRes <- liftIO $ HieBios.getRuntimeGhcVersion (toCologActionWithPrio (cmapWithPrio pretty recorder)) cradle+ ghcVersionRes <- liftIO $ HieBios.getRuntimeGhcVersion cradle cradleResult cradleName ghcVersionRes where@@ -214,11 +213,11 @@ Just _ -> pure () Nothing -> throwE $ ToolRequirementMissing exe (actionName (cradleOptsProg cradle)) -findProjectCradle :: IO (Cradle Void)-findProjectCradle = findProjectCradle' True+findProjectCradle :: Recorder (WithPriority (Doc ())) -> IO (Cradle Void)+findProjectCradle recorder = findProjectCradle' recorder True -findProjectCradle' :: Bool -> IO (Cradle Void)-findProjectCradle' log = do+findProjectCradle' :: Recorder (WithPriority (Doc ())) -> Bool -> IO (Cradle Void)+findProjectCradle' recorder log = do d <- getCurrentDirectory let initialFp = d </> "a"@@ -230,7 +229,7 @@ Just yaml -> hPutStrLn stderr $ "Found \"" ++ yaml ++ "\" for \"" ++ initialFp ++ "\"" Nothing -> hPutStrLn stderr "No 'hie.yaml' found. Try to discover the project type!" - Session.loadCradle def hieYaml d+ Session.loadCradle def (cmapWithPrio pretty recorder) hieYaml d trim :: String -> String trim s = case lines s of
@@ -1,7 +1,7 @@ cabal-version: 3.0 category: Development name: haskell-language-server-version: 2.5.0.0+version: 2.6.0.0 synopsis: LSP server for GHC description: Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>@@ -164,6 +164,11 @@ default: True manual: True +flag semanticTokens+ description: Enable semantic tokens plugin+ default: True+ manual: True+ -- formatters flag floskell@@ -203,136 +208,142 @@ common cabalfmt if flag(cabalfmt)- build-depends: hls-cabal-fmt-plugin == 2.5.0.0+ build-depends: hls-cabal-fmt-plugin == 2.6.0.0 cpp-options: -Dhls_cabalfmt common cabal if flag(cabal)- build-depends: hls-cabal-plugin == 2.5.0.0+ build-depends: hls-cabal-plugin == 2.6.0.0 cpp-options: -Dhls_cabal common class if flag(class) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-class-plugin == 2.5.0.0+ build-depends: hls-class-plugin == 2.6.0.0 cpp-options: -Dhls_class common callHierarchy if flag(callHierarchy)- build-depends: hls-call-hierarchy-plugin == 2.5.0.0+ build-depends: hls-call-hierarchy-plugin == 2.6.0.0 cpp-options: -Dhls_callHierarchy common eval if flag(eval)- build-depends: hls-eval-plugin == 2.5.0.0+ build-depends: hls-eval-plugin == 2.6.0.0 cpp-options: -Dhls_eval common importLens if flag(importLens)- build-depends: hls-explicit-imports-plugin == 2.5.0.0+ build-depends: hls-explicit-imports-plugin == 2.6.0.0 cpp-options: -Dhls_importLens common rename if flag(rename) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-rename-plugin == 2.5.0.0+ build-depends: hls-rename-plugin == 2.6.0.0 cpp-options: -Dhls_rename common retrie if flag(retrie) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-retrie-plugin == 2.5.0.0+ build-depends: hls-retrie-plugin == 2.6.0.0 cpp-options: -Dhls_retrie common hlint if flag(hlint) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-hlint-plugin == 2.5.0.0+ build-depends: hls-hlint-plugin == 2.6.0.0 cpp-options: -Dhls_hlint common stan if flag(stan) && (impl(ghc > 8.8.1) && impl(ghc <= 9.2.3) || impl(ghc >= 9.4.0) && impl(ghc < 9.10.0))- build-depends: hls-stan-plugin == 2.5.0.0+ build-depends: hls-stan-plugin == 2.6.0.0 cpp-options: -Dhls_stan common moduleName if flag(moduleName)- build-depends: hls-module-name-plugin == 2.5.0.0+ build-depends: hls-module-name-plugin == 2.6.0.0 cpp-options: -Dhls_moduleName common pragmas if flag(pragmas)- build-depends: hls-pragmas-plugin == 2.5.0.0+ build-depends: hls-pragmas-plugin == 2.6.0.0 cpp-options: -Dhls_pragmas common splice if flag(splice) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-splice-plugin == 2.5.0.0+ build-depends: hls-splice-plugin == 2.6.0.0 cpp-options: -Dhls_splice common alternateNumberFormat if flag(alternateNumberFormat)- build-depends: hls-alternate-number-format-plugin == 2.5.0.0+ build-depends: hls-alternate-number-format-plugin == 2.6.0.0 cpp-options: -Dhls_alternateNumberFormat common qualifyImportedNames if flag(qualifyImportedNames)- build-depends: hls-qualify-imported-names-plugin == 2.5.0.0+ build-depends: hls-qualify-imported-names-plugin == 2.6.0.0 cpp-options: -Dhls_qualifyImportedNames common codeRange if flag(codeRange)- build-depends: hls-code-range-plugin == 2.5.0.0+ build-depends: hls-code-range-plugin == 2.6.0.0 cpp-options: -Dhls_codeRange common changeTypeSignature if flag(changeTypeSignature)- build-depends: hls-change-type-signature-plugin == 2.5.0.0+ build-depends: hls-change-type-signature-plugin == 2.6.0.0 cpp-options: -Dhls_changeTypeSignature common gadt if flag(gadt) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-gadt-plugin == 2.5.0.0+ build-depends: hls-gadt-plugin == 2.6.0.0 cpp-options: -Dhls_gadt common explicitFixity if flag(explicitFixity)- build-depends: hls-explicit-fixity-plugin == 2.5.0.0+ build-depends: hls-explicit-fixity-plugin == 2.6.0.0 cpp-options: -DexplicitFixity common explicitFields if flag(explicitFields)- build-depends: hls-explicit-record-fields-plugin == 2.5.0.0+ build-depends: hls-explicit-record-fields-plugin == 2.6.0.0 cpp-options: -DexplicitFields common overloadedRecordDot if flag(overloadedRecordDot) && (impl(ghc >= 9.2.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-overloaded-record-dot-plugin == 2.5.0.0+ build-depends: hls-overloaded-record-dot-plugin == 2.6.0.0 cpp-options: -Dhls_overloaded_record_dot -- formatters common floskell- if flag(floskell) && impl(ghc < 9.5)- build-depends: hls-floskell-plugin == 2.5.0.0+ if flag(floskell) && (impl(ghc < 9.7) || flag(ignore-plugins-ghc-bounds))+ build-depends: hls-floskell-plugin == 2.6.0.0 cpp-options: -Dhls_floskell common fourmolu- if flag(fourmolu) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-fourmolu-plugin == 2.5.0.0+ if flag(fourmolu)+ build-depends: hls-fourmolu-plugin == 2.6.0.0 cpp-options: -Dhls_fourmolu common ormolu- if flag(ormolu) && impl(ghc < 9.7)- build-depends: hls-ormolu-plugin == 2.5.0.0+ if flag(ormolu)+ build-depends: hls-ormolu-plugin == 2.6.0.0 cpp-options: -Dhls_ormolu common stylishHaskell if flag(stylishHaskell) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-stylish-haskell-plugin == 2.5.0.0+ build-depends: hls-stylish-haskell-plugin == 2.6.0.0 cpp-options: -Dhls_stylishHaskell common refactor if flag(refactor) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))- build-depends: hls-refactor-plugin == 2.5.0.0+ build-depends: hls-refactor-plugin == 2.6.0.0 cpp-options: -Dhls_refactor +common semanticTokens+ if flag(semanticTokens)+ build-depends: hls-semantic-tokens-plugin == 2.6.0.0+ cpp-options: -Dhls_semanticTokens++ library import: common-deps -- configuration@@ -365,6 +376,7 @@ , stylishHaskell , refactor , overloadedRecordDot+ , semanticTokens exposed-modules: Ide.Arguments@@ -383,12 +395,12 @@ , cryptohash-sha1 , data-default , ghc- , ghcide == 2.5.0.0+ , ghcide == 2.6.0.0 , githash >=0.1.6.1 , lsp >= 2.3.0.0 , hie-bios , hiedb- , hls-plugin-api == 2.5.0.0+ , hls-plugin-api == 2.6.0.0 , optparse-applicative , optparse-simple , process@@ -522,12 +534,11 @@ , data-default , deepseq , hashable- , hspec-expectations , lens , lens-aeson , ghcide , ghcide-test-utils- , hls-test-utils == 2.5.0.0+ , hls-test-utils == 2.6.0.0 , lsp-types , aeson , hls-plugin-api@@ -541,6 +552,7 @@ main-is: Main.hs other-modules: Config+ ConfigSchema Format FunctionalBadProject HieBios@@ -556,7 +568,7 @@ if flag(eval) cpp-options: -Dhls_eval -- formatters- if flag(floskell) && (impl(ghc < 9.2.1) || flag(ignore-plugins-ghc-bounds))+ if flag(floskell) cpp-options: -Dhls_floskell if flag(fourmolu) cpp-options: -Dhls_fourmolu
@@ -120,6 +120,11 @@ import qualified Development.IDE.Plugin.CodeAction as Refactor #endif +#if hls_semanticTokens+import qualified Ide.Plugin.SemanticTokens as SemanticTokens+#endif++ data Log = forall a. (Pretty a) => Log PluginId a instance Pretty Log where@@ -171,6 +176,9 @@ #endif #if hls_callHierarchy CallHierarchy.descriptor "callHierarchy" :+#endif+#if hls_semanticTokens+ let pId = "semanticTokens" in SemanticTokens.descriptor (pluginRecorder pId) pId: #endif #if hls_class let pId = "class" in Class.descriptor (pluginRecorder pId) pId:
@@ -14,7 +14,7 @@ import qualified Data.Aeson.Encode.Pretty as A import Data.Coerce (coerce) import Data.Default-import Data.List (sort)+import Data.List (sortOn) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Lazy.Encoding (decodeUtf8)@@ -34,8 +34,9 @@ import Ide.Plugin.ConfigUtils (pluginsToDefaultConfig, pluginsToVSCodeExtensionSchema) import Ide.Types (IdePlugins, PluginId (PluginId),- ipMap, pluginId)+ describePlugin, ipMap, pluginId) import Ide.Version+import Prettyprinter as PP import System.Directory import qualified System.Directory.Extra as IO import System.FilePath@@ -46,6 +47,7 @@ | LogLspStart !GhcideArguments ![PluginId] | LogIDEMain IDEMain.Log | LogHieBios HieBios.Log+ | LogSession Session.Log | LogOther T.Text deriving Show @@ -61,6 +63,7 @@ , "PluginIds:" <+> pretty (coerce @_ @[Text] pluginIds) ] LogIDEMain iDEMainLog -> pretty iDEMainLog LogHieBios hieBiosLog -> pretty hieBiosLog+ LogSession sessionLog -> pretty sessionLog LogOther t -> pretty t defaultMain :: Recorder (WithPriority Log) -> Arguments -> IdePlugins IdeState -> IO ()@@ -83,15 +86,17 @@ putStrLn haskellLanguageServerNumericVersion ListPluginsMode -> do- let pluginNames = sort- $ map ((\(PluginId t) -> T.unpack t) . pluginId)+ let pluginSummary =+ PP.vsep+ $ map describePlugin+ $ sortOn pluginId $ ipMap idePlugins- mapM_ putStrLn pluginNames+ putStrLn $ show pluginSummary BiosMode PrintCradleType -> do dir <- IO.getCurrentDirectory hieYaml <- Session.findCradle def (dir </> "a")- cradle <- Session.loadCradle def hieYaml dir+ cradle <- Session.loadCradle def (cmapWithPrio LogSession recorder) hieYaml dir print cradle Ghcide ghcideArgs -> do@@ -107,8 +112,8 @@ d <- getCurrentDirectory let initialFp = d </> "a" hieYaml <- Session.findCradle def initialFp- cradle <- Session.loadCradle def hieYaml d- (CradleSuccess libdir) <- HieBios.getRuntimeGhcLibDir (toCologActionWithPrio (cmapWithPrio LogHieBios recorder)) cradle+ cradle <- Session.loadCradle def (cmapWithPrio LogSession recorder) hieYaml d+ (CradleSuccess libdir) <- HieBios.getRuntimeGhcLibDir cradle putStr libdir where encodePrettySorted = A.encodePretty' A.defConfig
@@ -76,7 +76,7 @@ testPluginId = "testplugin" -- A disabled-by-default plugin that creates diagnostics plugin = mkPluginTestDescriptor' @() pd testPluginId- pd plId = (defaultPluginDescriptor plId)+ pd plId = (defaultPluginDescriptor plId "") { pluginConfigDescriptor = configDisabled , pluginRules = do
@@ -0,0 +1,49 @@+module ConfigSchema where+++import qualified Data.ByteString.Lazy.Char8 as BS+import Data.Char (toLower)+import System.FilePath ((</>))+import System.Process.Extra+import Test.Hls+import Test.Hls.Command++-- | Integration test to capture changes to the generated default config and the vscode schema.+--+-- Changes to the vscode schema need to be communicated to vscode-haskell plugin maintainers,+-- otherwise users can't make use of the new configurations.+--+-- In general, changes to the schema need to be done consciously when new plugin or features are added.+-- To fix a failing of these tests, review the change. If it is expected, accept the change via:+--+-- @+-- TASTY_PATTERN="generate schema" cabal test func-test --test-options=--accept+-- @+--+-- As changes need to be applied for all GHC version specific configs, you either need to run this command for each+-- GHC version that is affected by the config change, or manually add the change to all other golden config files.+-- Likely, the easiest way is to run CI and apply the generated diffs manually.+tests :: TestTree+tests = testGroup "generate schema"+ [ goldenGitDiff "vscode-extension-schema" (vscodeSchemaFp ghcVersion) $ do+ stdout <- readProcess hlsExeCommand ["vscode-extension-schema"] ""+ pure $ BS.pack stdout+ , goldenGitDiff "generate-default-config" (defaultConfigFp ghcVersion) $ do+ stdout <- readProcess hlsExeCommand ["generate-default-config"] ""+ pure $ BS.pack stdout+ ]++vscodeSchemaFp :: GhcVersion -> FilePath+vscodeSchemaFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion ghcVer </> vscodeSchemaJson++defaultConfigFp :: GhcVersion -> FilePath+defaultConfigFp ghcVer = "test" </> "testdata" </> "schema" </> prettyGhcVersion ghcVer </> generateDefaultConfigJson++vscodeSchemaJson :: FilePath+vscodeSchemaJson = "vscode-extension-schema.golden.json"++generateDefaultConfigJson :: FilePath+generateDefaultConfigJson = "default-config.golden.json"++prettyGhcVersion :: GhcVersion -> String+prettyGhcVersion ghcVer = map toLower (show ghcVer)
@@ -23,18 +23,18 @@ providerTests :: TestTree providerTests = testGroup "lsp formatting provider"- [ testCase "respects none" $ runSessionWithConfig (formatConfig "none") hlsCommand fullCaps "test/testdata/format" $ do+ [ testCase "respects none" $ runSessionWithConfig (formatConfig "none") hlsLspCommand fullCaps "test/testdata/format" $ do void configurationRequest doc <- openDoc "Format.hs" "haskell" resp <- request SMethod_TextDocumentFormatting $ DocumentFormattingParams Nothing doc (FormattingOptions 2 True Nothing Nothing Nothing) liftIO $ case resp ^. L.result of result@(Left (ResponseError reason message Nothing)) -> case reason of (InR ErrorCodes_MethodNotFound) -> pure () -- No formatter- (InR ErrorCodes_InvalidRequest) | "No plugin enabled for SMethod_TextDocumentFormatting" `T.isPrefixOf` message -> pure ()+ (InR ErrorCodes_InvalidRequest) | "No plugin" `T.isPrefixOf` message -> pure () _ -> assertFailure $ "strange response from formatting provider:" ++ show result result -> assertFailure $ "strange response from formatting provider:" ++ show result - , requiresOrmoluPlugin . requiresFloskellPlugin $ testCase "can change on the fly" $ runSessionWithConfig (formatConfig "none") hlsCommand fullCaps "test/testdata/format" $ do+ , requiresOrmoluPlugin . requiresFloskellPlugin $ testCase "can change on the fly" $ runSessionWithConfig (formatConfig "none") hlsLspCommand fullCaps "test/testdata/format" $ do void configurationRequest formattedOrmolu <- liftIO $ T.readFile "test/testdata/format/Format.ormolu.formatted.hs" formattedFloskell <- liftIO $ T.readFile "test/testdata/format/Format.floskell.formatted.hs"
@@ -12,17 +12,17 @@ tests :: TestTree tests = testGroup "behaviour on malformed projects" [ testCase "Missing module diagnostic" $ do- runSession hlsCommand fullCaps "test/testdata/missingModuleTest/missingModule/" $ do+ runSession hlsLspCommand fullCaps "test/testdata/missingModuleTest/missingModule/" $ do doc <- openDoc "src/MyLib.hs" "haskell" [diag] <- waitForDiagnosticsFrom doc liftIO $ assertBool "missing module name" $ "MyLib" `T.isInfixOf` (diag ^. L.message) liftIO $ assertBool "module missing context" $ "may not be listed" `T.isInfixOf` (diag ^. L.message) , testCase "Missing module diagnostic - no matching prefix" $ do- runSession hlsCommand fullCaps "test/testdata/missingModuleTest/noPrefixMatch/" $ do+ runSession hlsLspCommand fullCaps "test/testdata/missingModuleTest/noPrefixMatch/" $ do doc <- openDoc "app/Other.hs" "haskell" [diag] <- waitForDiagnosticsFrom doc liftIO $ assertBool "missing module name" $ "Other" `T.isInfixOf` (diag ^. L.message) liftIO $ assertBool "hie-bios message" $- "Cabal {component = Just \"exe:testExe\"}" `T.isInfixOf` (diag ^. L.message)+ "Cabal" `T.isInfixOf` (diag ^. L.message) ]
@@ -11,7 +11,7 @@ tests :: TestTree tests = testGroup "hie-bios" [ testCase "loads main-is module" $ do- runSession hlsCommand fullCaps "test/testdata/hieBiosMainIs" $ do+ runSession hlsLspCommand fullCaps "test/testdata/hieBiosMainIs" $ do _ <- openDoc "Main.hs" "haskell" (diag:_) <- waitForDiagnostics liftIO $ "Top-level binding with no type signature:" `T.isInfixOf` (diag ^. L.message)
@@ -1,6 +1,7 @@ module Main where import Config+import ConfigSchema import Format import FunctionalBadProject import HieBios@@ -10,6 +11,7 @@ main :: IO () main = defaultTestRunner $ testGroup "haskell-language-server" [ Config.tests+ , ConfigSchema.tests , ignoreInEnv [HostOS Windows, GhcVer GHC90, GhcVer GHC92] "Tests gets stuck in ci" $ Format.tests , FunctionalBadProject.tests , HieBios.tests
@@ -28,12 +28,12 @@ testGroup "window/workDoneProgress" [ testCase "sends indefinite progress notifications" $- runSession hlsCommand progressCaps "test/testdata/diagnostics" $ do+ runSession hlsLspCommand progressCaps "test/testdata/diagnostics" $ do let path = "Foo.hs" _ <- openDoc path "haskell" expectProgressMessages [pack ("Setting up diagnostics (for " ++ path ++ ")"), "Processing", "Indexing"] [] , requiresEvalPlugin $ testCase "eval plugin sends progress reports" $- runSession hlsCommand progressCaps "plugins/hls-eval-plugin/test/testdata" $ do+ runSession hlsLspCommand progressCaps "plugins/hls-eval-plugin/test/testdata" $ do doc <- openDoc "T1.hs" "haskell" lspId <- sendRequest SMethod_TextDocumentCodeLens (CodeLensParams Nothing Nothing doc) @@ -57,7 +57,7 @@ expectProgressMessages ["Evaluating"] activeProgressTokens _ -> error $ "Unexpected response result: " ++ show response , requiresOrmoluPlugin $ testCase "ormolu plugin sends progress notifications" $ do- runSessionWithConfig (def { ignoreConfigurationRequests = False }) hlsCommand progressCaps "test/testdata/format" $ do+ runSessionWithConfig (def { ignoreConfigurationRequests = False }) hlsLspCommand progressCaps "test/testdata/format" $ do void configurationRequest setHlsConfig (formatLspConfig "ormolu") doc <- openDoc "Format.hs" "haskell"@@ -65,7 +65,7 @@ _ <- sendRequest SMethod_TextDocumentFormatting $ DocumentFormattingParams Nothing doc (FormattingOptions 2 True Nothing Nothing Nothing) expectProgressMessages ["Formatting Format.hs"] [] , requiresFourmoluPlugin $ testCase "fourmolu plugin sends progress notifications" $ do- runSessionWithConfig (def { ignoreConfigurationRequests = False }) hlsCommand progressCaps "test/testdata/format" $ do+ runSessionWithConfig (def { ignoreConfigurationRequests = False }) hlsLspCommand progressCaps "test/testdata/format" $ do void configurationRequest setHlsConfig (formatLspConfig "fourmolu") doc <- openDoc "Format.hs" "haskell"
@@ -1,5 +1,8 @@ module Test.Hls.Command- ( hlsCommand+ ( hlsExeCommand+ , hlsLspCommand+ , hlsWrapperLspCommand+ , hlsWrapperExeCommand ) where @@ -12,8 +15,20 @@ -- Both @stack test@ and @cabal new-test@ setup the environment so @hls@ is -- on PATH. Cabal seems to respond to @build-tool-depends@ specifically while -- stack just puts all project executables on PATH.-hlsCommand :: String-{-# NOINLINE hlsCommand #-}-hlsCommand = unsafePerformIO $ do+hlsExeCommand :: String+{-# NOINLINE hlsExeCommand #-}+hlsExeCommand = unsafePerformIO $ do testExe <- fromMaybe "haskell-language-server" <$> lookupEnv "HLS_TEST_EXE"- pure $ testExe ++ " --lsp -d -j4"+ pure testExe++hlsLspCommand :: String+hlsLspCommand = hlsExeCommand ++ " --lsp -d -j4"++hlsWrapperLspCommand :: String+hlsWrapperLspCommand = hlsWrapperExeCommand ++ " --lsp -d -j4"++hlsWrapperExeCommand :: String+{-# NOINLINE hlsWrapperExeCommand #-}+hlsWrapperExeCommand = unsafePerformIO $ do+ testExe <- fromMaybe "haskell-language-server-wrapper" <$> lookupEnv "HLS_WRAPPER_TEST_EXE"+ pure testExe