From beb182dc4e722930ed6624177ff4e49baf1e473a Mon Sep 17 00:00:00 2001 From: VeryMilkyJoe Date: Sun, 8 Jun 2025 16:17:55 +0200 Subject: [PATCH] Change tracking of file types to language kinds The plugin descriptor now tracks the language kinds it is responsible for instead of the file endings. We get the language kinds of any file from the VFS. Currently we are using a source repository to be able to use the lsp changes needed, but once lsp is released this can be removed. --- cabal.project | 19 ++-- ghcide-test/exe/InitializeResponseTests.hs | 9 +- ghcide/ghcide.cabal | 6 +- ghcide/src/Development/IDE/Core/FileStore.hs | 4 +- ghcide/src/Development/IDE/Core/Rules.hs | 4 +- ghcide/src/Development/IDE/Core/Shake.hs | 4 +- .../IDE/Plugin/Completions/Logic.hs | 2 +- ghcide/src/Development/IDE/Plugin/HLS.hs | 10 +- haskell-language-server.cabal | 18 ++-- hls-plugin-api/hls-plugin-api.cabal | 2 +- hls-plugin-api/src/Ide/Types.hs | 97 +++++++++++-------- hls-test-utils/hls-test-utils.cabal | 4 +- .../test/SemanticTokensTest.hs | 3 +- .../hls-signature-help-plugin/test/Main.hs | 19 +--- stack-lts22.yaml | 9 +- stack.yaml | 6 +- 16 files changed, 116 insertions(+), 100 deletions(-) diff --git a/cabal.project b/cabal.project index cff8c4cd62..fdf9ae3d79 100644 --- a/cabal.project +++ b/cabal.project @@ -6,8 +6,7 @@ packages: ./hls-plugin-api ./hls-test-utils - -index-state: 2026-02-02T09:03:26Z +index-state: 2026-02-24T00:00:00Z tests: True test-show-details: direct @@ -41,6 +40,7 @@ constraints: -- We want to be able to benefit from the performance optimisations -- in the future, thus: TODO: remove this flag. bitvec -simd, + monad-control >=1.0.3, -- Some of the formatters need the latest Cabal-syntax version, @@ -59,15 +59,11 @@ if impl(ghc >= 9.11) if impl(ghc >= 9.14) allow-newer: - lsp-types:containers, - lsp:containers, indexed-traversable:containers, quickcheck-instances:containers, dependent-map:containers, aeson:containers, semialign:containers, - lsp-test:containers, - hie-bios:ghc, string-interpolate:template-haskell, tasty-hspec:base, tagged:template-haskell, @@ -79,19 +75,20 @@ if impl(ghc >= 9.14) some:base, boring:base, indexed-traversable-instances:base, - lsp-types:template-haskell, uuid-types:template-haskell, hie-compat:base, - hie-bios:time, - hie-bios:template-haskell, ghc-trace-events:base, constraints-extras:template-haskell, aeson:time, text-iso8601:time, semialign:base, aeson:template-haskell, - lsp-test:time, lukko:base, binary-instances:base, binary-orphans:base, - cabal-install-parsers:containers + cabal-install-parsers:containers, + haddock-library:base, + websockets:containers, + monad-control:transformers, + mmorph:transformers-compat, + binary-instances:tagged, diff --git a/ghcide-test/exe/InitializeResponseTests.hs b/ghcide-test/exe/InitializeResponseTests.hs index f13344e368..c32d1ee800 100644 --- a/ghcide-test/exe/InitializeResponseTests.hs +++ b/ghcide-test/exe/InitializeResponseTests.hs @@ -55,7 +55,14 @@ tests = withResource acquire release tests where { _supported = Just True , _changeNotifications = Just (InR True) } - , _fileOperations = Nothing + , _fileOperations = Just $ FileOperationOptions + { _didCreate = Nothing + , _willCreate = Nothing + , _didRename = Nothing + , _willRename = Nothing + , _didDelete = Nothing + , _willDelete = Nothing + } }) , chk "NO experimental" (^. L.experimental) Nothing ] where diff --git a/ghcide/ghcide.cabal b/ghcide/ghcide.cabal index 903f25aa50..118612fb14 100644 --- a/ghcide/ghcide.cabal +++ b/ghcide/ghcide.cabal @@ -74,7 +74,7 @@ library , Glob , haddock-library >=1.8 && <1.12 , hashable - , hie-bios ^>=0.17.0 + , hie-bios ^>= 0.18.0 , hiedb ^>= 0.8.0.0 , hls-graph == 2.13.0.0 , hls-plugin-api == 2.13.0.0 @@ -82,8 +82,8 @@ library , lens , lens-aeson , list-t - , lsp ^>=2.7 - , lsp-types ^>=2.3 + , lsp ^>=2.8 + , lsp-types ^>=2.4 , mtl , opentelemetry >=0.6.1 , optparse-applicative diff --git a/ghcide/src/Development/IDE/Core/FileStore.hs b/ghcide/src/Development/IDE/Core/FileStore.hs index e545ec7b14..714d991201 100644 --- a/ghcide/src/Development/IDE/Core/FileStore.hs +++ b/ghcide/src/Development/IDE/Core/FileStore.hs @@ -252,8 +252,8 @@ getVersionedTextDoc doc = do maybe (pure Nothing) getVirtualFile $ uriToNormalizedFilePath $ toNormalizedUri uri let ver = case mvf of - Just (VirtualFile lspver _ _) -> lspver - Nothing -> 0 + Just (VirtualFile lspver _ _ _) -> lspver + Nothing -> 0 return (VersionedTextDocumentIdentifier uri ver) fileStoreRules :: Recorder (WithPriority Log) -> (NormalizedFilePath -> Action Bool) -> Rules () diff --git a/ghcide/src/Development/IDE/Core/Rules.hs b/ghcide/src/Development/IDE/Core/Rules.hs index 8f3ff35fff..b31b161eed 100644 --- a/ghcide/src/Development/IDE/Core/Rules.hs +++ b/ghcide/src/Development/IDE/Core/Rules.hs @@ -167,7 +167,7 @@ import Ide.Plugin.Properties (HasProperty, useProperty, usePropertyByPath) import Ide.Types (DynFlagsModifications (dynFlagsModifyGlobal, dynFlagsModifyParser), - PluginId) + PluginId, getVirtualFileFromVFS) import qualified Language.LSP.Protocol.Lens as JL import Language.LSP.Protocol.Message (SMethod (SMethod_CustomMethod, SMethod_WindowShowMessage)) import Language.LSP.Protocol.Types (MessageType (MessageType_Info), @@ -525,7 +525,7 @@ persistentHieFileRule recorder = addPersistentRule GetHieAst $ \file -> runMaybe res <- readHieFileForSrcFromDisk recorder file vfsRef <- asks vfsVar vfsData <- liftIO $ _vfsMap <$> readTVarIO vfsRef - (currentSource, ver) <- liftIO $ case M.lookup (filePathToUri' file) vfsData of + (currentSource, ver) <- liftIO $ case getVirtualFileFromVFS (VFS vfsData) (filePathToUri' file) of Nothing -> (,Nothing) . T.decodeUtf8 <$> BS.readFile (fromNormalizedFilePath file) Just vf -> pure (virtualFileText vf, Just $ virtualFileVersion vf) let refmap = generateReferencesMap . getAsts . Compat.hie_asts $ res diff --git a/ghcide/src/Development/IDE/Core/Shake.hs b/ghcide/src/Development/IDE/Core/Shake.hs index c5a0a49134..3e142e8db4 100644 --- a/ghcide/src/Development/IDE/Core/Shake.hs +++ b/ghcide/src/Development/IDE/Core/Shake.hs @@ -130,6 +130,7 @@ import Development.IDE.Core.RuleTypes import Development.IDE.Types.Options as Options import qualified Language.LSP.Protocol.Message as LSP import qualified Language.LSP.Server as LSP +import qualified Language.LSP.VFS as VFS import Development.IDE.Core.Tracing import Development.IDE.Core.WorkerThread @@ -401,7 +402,8 @@ class Typeable a => IsIdeGlobal a where getVirtualFile :: NormalizedFilePath -> Action (Maybe VirtualFile) getVirtualFile nf = do vfs <- fmap _vfsMap . liftIO . readTVarIO . vfsVar =<< getShakeExtras - pure $! Map.lookup (filePathToUri' nf) vfs -- Don't leak a reference to the entire map + pure $! -- Don't leak a reference to the entire map + getVirtualFileFromVFS (VFS vfs) $ filePathToUri' nf -- Take a snapshot of the current LSP VFS vfsSnapshot :: Maybe (LSP.LanguageContextEnv a) -> IO VFS diff --git a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs index 55ea002fc6..3fe20d24b9 100644 --- a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs +++ b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs @@ -867,7 +867,7 @@ mergeListsBy cmp all_lists = merge_lists all_lists -- |From the given cursor position, gets the prefix module or record for autocompletion getCompletionPrefix :: Position -> VFS.VirtualFile -> PosPrefixInfo -getCompletionPrefix pos (VFS.VirtualFile _ _ ropetext) = getCompletionPrefixFromRope pos ropetext +getCompletionPrefix pos (VFS.VirtualFile _ _ ropetext _) = getCompletionPrefixFromRope pos ropetext getCompletionPrefixFromRope :: Position -> Rope.Rope -> PosPrefixInfo getCompletionPrefixFromRope pos@(Position l c) ropetext = diff --git a/ghcide/src/Development/IDE/Plugin/HLS.hs b/ghcide/src/Development/IDE/Plugin/HLS.hs index f5190e9274..f7bf1cadf5 100644 --- a/ghcide/src/Development/IDE/Plugin/HLS.hs +++ b/ghcide/src/Development/IDE/Plugin/HLS.hs @@ -49,7 +49,8 @@ import qualified Language.LSP.Server as LSP import Language.LSP.VFS import Prettyprinter.Render.String (renderString) import Text.Regex.TDFA.Text () -import UnliftIO (MonadUnliftIO, liftIO) +import UnliftIO (MonadUnliftIO, liftIO, + readTVarIO) import UnliftIO.Async (forConcurrently) import UnliftIO.Exception (catchAny) @@ -251,11 +252,12 @@ extensiblePlugins recorder plugins = mempty { P.pluginHandlers = handlers } handlers = mconcat $ do (IdeMethod m :=> IdeHandler fs') <- DMap.assocs handlers' pure $ requestHandler m $ \ide params -> do + vfs <- readTVarIO $ vfsVar $ shakeExtras ide config <- Ide.PluginUtils.getClientConfig -- Only run plugins that are allowed to run on this request, save the -- list of disabled plugins incase that's all we have - let (fs, dfs) = List.partition (\(_, desc, _) -> handlesRequest m params desc config == HandlesRequest) fs' - let disabledPluginsReason = (\(x, desc, _) -> (x, handlesRequest m params desc config)) <$> dfs + let (fs, dfs) = List.partition (\(_, desc, _) -> handlesRequest vfs m params desc config == HandlesRequest) fs' + let disabledPluginsReason = (\(x, desc, _) -> (x, handlesRequest vfs m params desc config)) <$> dfs -- Clients generally don't display ResponseErrors so instead we log any that we come across -- However, some clients do display ResponseErrors! See for example the issues: -- https://github.com/haskell/haskell-language-server/issues/4467 @@ -370,7 +372,7 @@ extensibleNotificationPlugins recorder xs = mempty { P.pluginHandlers = handlers pure $ notificationHandler m $ \ide vfs params -> do config <- Ide.PluginUtils.getClientConfig -- Only run plugins that are enabled for this request - let fs = filter (\(_, desc, _) -> handlesRequest m params desc config == HandlesRequest) fs' + let fs = filter (\(_, desc, _) -> handlesRequest vfs m params desc config == HandlesRequest) fs' case nonEmpty fs of Nothing -> do logWith recorder Warning (LogNoPluginForMethod $ Some m) diff --git a/haskell-language-server.cabal b/haskell-language-server.cabal index 3f1dfddfd4..e2d50ad69e 100644 --- a/haskell-language-server.cabal +++ b/haskell-language-server.cabal @@ -279,8 +279,8 @@ library hls-cabal-plugin , hls-plugin-api == 2.13.0.0 , hls-graph == 2.13.0.0 , lens - , lsp ^>=2.7 - , lsp-types ^>=2.3 + , lsp ^>=2.8 + , lsp-types ^>=2.4 , mtl , regex-tdfa ^>=1.3.1 , text @@ -415,7 +415,7 @@ library hls-call-hierarchy-plugin , hiedb ^>= 0.8.0.0 , hls-plugin-api == 2.13.0.0 , lens - , lsp >=2.7 + , lsp >=2.8 , sqlite-simple , text @@ -1040,7 +1040,7 @@ library hls-alternate-number-format-plugin , hls-graph , hls-plugin-api == 2.13.0.0 , lens - , lsp ^>=2.7 + , lsp ^>=2.8 , mtl , syb , text @@ -1268,7 +1268,7 @@ library hls-gadt-plugin , hls-plugin-api == 2.13.0.0 , haskell-language-server:hls-refactor-plugin , lens - , lsp >=2.7 + , lsp >=2.8 , mtl , text , transformers @@ -1315,7 +1315,7 @@ library hls-explicit-fixity-plugin , ghcide == 2.13.0.0 , hashable , hls-plugin-api == 2.13.0.0 - , lsp >=2.7 + , lsp >=2.8 , text default-extensions: DataKinds @@ -1799,7 +1799,7 @@ library hls-notes-plugin , hls-graph == 2.13.0.0 , hls-plugin-api == 2.13.0.0 , lens - , lsp >=2.7 + , lsp >=2.8 , mtl >= 2.2 , regex-tdfa >= 1.3.1 , text @@ -2104,7 +2104,7 @@ test-suite ghcide-tests , lens , list-t , lsp - , lsp-test ^>=0.17.1 + , lsp-test ^>=0.18.0 , lsp-types , mtl , network-uri @@ -2261,7 +2261,7 @@ test-suite ghcide-bench-test build-depends: extra, haskell-language-server:ghcide-bench-lib, - lsp-test ^>= 0.17, + lsp-test ^>= 0.18, tasty, tasty-hunit >= 0.10, tasty-rerun diff --git a/hls-plugin-api/hls-plugin-api.cabal b/hls-plugin-api/hls-plugin-api.cabal index d7b53f1e68..d2a8596eae 100644 --- a/hls-plugin-api/hls-plugin-api.cabal +++ b/hls-plugin-api/hls-plugin-api.cabal @@ -69,7 +69,7 @@ library , hls-graph == 2.13.0.0 , lens , lens-aeson - , lsp ^>=2.7 + , lsp ^>=2.8 , megaparsec >=9.0 , mtl , opentelemetry >=0.4 diff --git a/hls-plugin-api/src/Ide/Types.hs b/hls-plugin-api/src/Ide/Types.hs index f4c111f45d..96edee141c 100644 --- a/hls-plugin-api/src/Ide/Types.hs +++ b/hls-plugin-api/src/Ide/Types.hs @@ -39,6 +39,7 @@ module Ide.Types , PluginNotificationHandlers(..) , PluginRequestMethod(..) , getProcessID, getPid +, getVirtualFileFromVFS , installSigUsr1Handler , lookupCommandProvider , ResolveFunction @@ -94,13 +95,13 @@ import Ide.Plugin.Properties import qualified Language.LSP.Protocol.Lens as L import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types +import qualified Language.LSP.Protocol.Types as J import Language.LSP.Server import Language.LSP.VFS import Numeric.Natural import OpenTelemetry.Eventlog import Options.Applicative (ParserInfo) import Prettyprinter as PP -import System.FilePath import System.IO.Unsafe import Text.Regex.TDFA.Text () import UnliftIO (MonadUnliftIO) @@ -325,7 +326,7 @@ data PluginDescriptor (ideState :: Type) = , pluginNotificationHandlers :: PluginNotificationHandlers ideState , pluginModifyDynflags :: DynFlagsModifications , pluginCli :: Maybe (ParserInfo (IdeCommand ideState)) - , pluginFileType :: [T.Text] + , pluginLanguageIds :: [J.LanguageKind] -- ^ File extension of the files the plugin is responsible for. -- The plugin is only allowed to handle files with these extensions. -- When writing handlers, etc. for this plugin it can be assumed that all handled files are of this type. @@ -418,14 +419,18 @@ pluginResolverResponsible _ _ = DoesNotHandleRequest $ NotResolveOwner "(unable -- We are passing the msgParams here even though we only need the URI URI here. -- If in the future we need to be able to provide only an URI it can be -- separated again. -pluginSupportsFileType :: (L.HasTextDocument m doc, L.HasUri doc Uri) => m -> PluginDescriptor c -> HandleRequestResult -pluginSupportsFileType msgParams pluginDesc = - case mfp of - Just fp | T.pack (takeExtension fp) `elem` pluginFileType pluginDesc -> HandlesRequest - _ -> DoesNotHandleRequest $ DoesNotSupportFileType (maybe "(unable to determine file type)" (T.pack . takeExtension) mfp) +pluginSupportsFileType :: (L.HasTextDocument m doc, L.HasUri doc Uri) => VFS -> m -> PluginDescriptor c -> HandleRequestResult +pluginSupportsFileType (VFS vfs) msgParams pluginDesc = + case languageKindM of + Just languageKind | languageKind `elem` pluginLanguageIds pluginDesc -> HandlesRequest + _ -> DoesNotHandleRequest $ DoesNotSupportFileType (maybe "(unable to determine file type)" (T.pack . show) languageKindM) where - mfp = uriToFilePath uri - uri = msgParams ^. L.textDocument . L.uri + mVFE = getVirtualFileFromVFSIncludingClosed (VFS vfs) uri + uri = toNormalizedUri $ msgParams ^. L.textDocument . L.uri + languageKindM = + case mVFE of + Just x -> virtualFileEntryLanguageKind x + _ -> Nothing -- | Methods that can be handled by plugins. -- 'ExtraParams' captures any extra data the IDE passes to the handlers for this method @@ -454,7 +459,9 @@ class HasTracing (MessageParams m) => PluginMethod (k :: MessageKind) (m :: Meth -- -- But there is no use to split it up into two different methods for now. handlesRequest - :: SMethod m + :: VFS + -- ^ The virtual file system, contains the language kind of the file. + -> SMethod m -- ^ Method type. -> MessageParams m -- ^ Whether a plugin is enabled might depend on the message parameters @@ -470,24 +477,24 @@ class HasTracing (MessageParams m) => PluginMethod (k :: MessageKind) (m :: Meth -- with the given parameters? default handlesRequest :: (L.HasTextDocument (MessageParams m) doc, L.HasUri doc Uri) - => SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult - handlesRequest _ params desc conf = - pluginEnabledGlobally desc conf <> pluginSupportsFileType params desc + => VFS -> SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult + handlesRequest vfs _ params desc conf = + pluginEnabledGlobally desc conf <> pluginSupportsFileType vfs params desc -- | Check if a plugin is enabled, if one of it's specific config's is enabled, -- and if it supports the file pluginEnabledWithFeature :: (L.HasTextDocument (MessageParams m) doc, L.HasUri doc Uri) - => (PluginConfig -> Bool) -> SMethod m -> MessageParams m + => (PluginConfig -> Bool) -> VFS -> SMethod m -> MessageParams m -> PluginDescriptor c -> Config -> HandleRequestResult -pluginEnabledWithFeature feature _ msgParams pluginDesc config = +pluginEnabledWithFeature feature vfs _ msgParams pluginDesc config = pluginEnabledGlobally pluginDesc config <> pluginFeatureEnabled feature pluginDesc config - <> pluginSupportsFileType msgParams pluginDesc + <> pluginSupportsFileType vfs msgParams pluginDesc -- | Check if a plugin is enabled, if one of it's specific configs is enabled, -- and if it's the plugin responsible for a resolve request. -pluginEnabledResolve :: L.HasData_ s (Maybe Value) => (PluginConfig -> Bool) -> p -> s -> PluginDescriptor c -> Config -> HandleRequestResult -pluginEnabledResolve feature _ msgParams pluginDesc config = +pluginEnabledResolve :: L.HasData_ s (Maybe Value) => (PluginConfig -> Bool) -> VFS -> p -> s -> PluginDescriptor c -> Config -> HandleRequestResult +pluginEnabledResolve feature _ _ msgParams pluginDesc config = pluginEnabledGlobally pluginDesc config <> pluginFeatureEnabled feature pluginDesc config <> pluginResolverResponsible msgParams pluginDesc @@ -500,23 +507,23 @@ instance PluginMethod Request Method_CodeActionResolve where handlesRequest = pluginEnabledResolve plcCodeActionsOn instance PluginMethod Request Method_TextDocumentDefinition where - handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc + handlesRequest vfs _ msgParams pluginDesc _ = pluginSupportsFileType vfs msgParams pluginDesc instance PluginMethod Request Method_TextDocumentTypeDefinition where - handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc + handlesRequest vfs _ msgParams pluginDesc _ = pluginSupportsFileType vfs msgParams pluginDesc instance PluginMethod Request Method_TextDocumentImplementation where - handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc + handlesRequest vfs _ msgParams pluginDesc _ = pluginSupportsFileType vfs msgParams pluginDesc instance PluginMethod Request Method_TextDocumentDocumentHighlight where - handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc + handlesRequest vfs _ msgParams pluginDesc _ = pluginSupportsFileType vfs msgParams pluginDesc instance PluginMethod Request Method_TextDocumentReferences where - handlesRequest _ msgParams pluginDesc _ = pluginSupportsFileType msgParams pluginDesc + handlesRequest vfs _ msgParams pluginDesc _ = pluginSupportsFileType vfs msgParams pluginDesc instance PluginMethod Request Method_WorkspaceSymbol where -- Unconditionally enabled, but should it really be? - handlesRequest _ _ _ _ = HandlesRequest + handlesRequest _ _ _ _ _ = HandlesRequest instance PluginMethod Request Method_TextDocumentInlayHint where handlesRequest = pluginEnabledWithFeature plcInlayHintsOn @@ -554,22 +561,22 @@ instance PluginMethod Request Method_TextDocumentCompletion where handlesRequest = pluginEnabledWithFeature plcCompletionOn instance PluginMethod Request Method_TextDocumentFormatting where - handlesRequest _ msgParams pluginDesc conf = + handlesRequest vfs _ msgParams pluginDesc conf = (if PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid then HandlesRequest else DoesNotHandleRequest (NotFormattingProvider (formattingProvider conf)) ) - <> pluginSupportsFileType msgParams pluginDesc + <> pluginSupportsFileType vfs msgParams pluginDesc where pid = pluginId pluginDesc instance PluginMethod Request Method_TextDocumentRangeFormatting where - handlesRequest _ msgParams pluginDesc conf = + handlesRequest vfs _ msgParams pluginDesc conf = (if PluginId (formattingProvider conf) == pid || PluginId (cabalFormattingProvider conf) == pid then HandlesRequest else DoesNotHandleRequest (NotFormattingProvider (formattingProvider conf))) - <> pluginSupportsFileType msgParams pluginDesc + <> pluginSupportsFileType vfs msgParams pluginDesc where pid = pluginId pluginDesc @@ -590,21 +597,21 @@ instance PluginMethod Request Method_TextDocumentFoldingRange where instance PluginMethod Request Method_CallHierarchyIncomingCalls where -- This method has no URI parameter, thus no call to 'pluginResponsible' - handlesRequest _ _ pluginDesc conf = + handlesRequest _ _ _ pluginDesc conf = pluginEnabledGlobally pluginDesc conf <> pluginFeatureEnabled plcCallHierarchyOn pluginDesc conf instance PluginMethod Request Method_CallHierarchyOutgoingCalls where -- This method has no URI parameter, thus no call to 'pluginResponsible' - handlesRequest _ _ pluginDesc conf = + handlesRequest _ _ _ pluginDesc conf = pluginEnabledGlobally pluginDesc conf <> pluginFeatureEnabled plcCallHierarchyOn pluginDesc conf instance PluginMethod Request Method_WorkspaceExecuteCommand where - handlesRequest _ _ _ _= HandlesRequest + handlesRequest _ _ _ _ _ = HandlesRequest instance PluginMethod Request (Method_CustomMethod m) where - handlesRequest _ _ _ _ = HandlesRequest + handlesRequest _ _ _ _ _ = HandlesRequest -- Plugin Notifications @@ -618,19 +625,19 @@ instance PluginMethod Notification Method_TextDocumentDidClose where instance PluginMethod Notification Method_WorkspaceDidChangeWatchedFiles where -- This method has no URI parameter, thus no call to 'pluginResponsible'. - handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf + handlesRequest _ _ _ desc conf = pluginEnabledGlobally desc conf instance PluginMethod Notification Method_WorkspaceDidChangeWorkspaceFolders where -- This method has no URI parameter, thus no call to 'pluginResponsible'. - handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf + handlesRequest _ _ _ desc conf = pluginEnabledGlobally desc conf instance PluginMethod Notification Method_WorkspaceDidChangeConfiguration where -- This method has no URI parameter, thus no call to 'pluginResponsible'. - handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf + handlesRequest _ _ _ desc conf = pluginEnabledGlobally desc conf instance PluginMethod Notification Method_Initialized where -- This method has no URI parameter, thus no call to 'pluginResponsible'. - handlesRequest _ _ desc conf = pluginEnabledGlobally desc conf + handlesRequest _ _ _ desc conf = pluginEnabledGlobally desc conf -- --------------------------------------------------------------------- @@ -1062,7 +1069,7 @@ defaultPluginDescriptor plId desc = mempty mempty Nothing - [".hs", ".lhs", ".hs-boot"] + [J.LanguageKind_Haskell, J.LanguageKind_Custom "literate haskell"] -- | Set up a plugin descriptor, initialized with default values. -- This plugin descriptor is prepared for @.cabal@ files and as such, @@ -1083,7 +1090,7 @@ defaultCabalPluginDescriptor plId desc = mempty mempty Nothing - [".cabal"] + [J.LanguageKind_Custom "cabal"] newtype CommandId = CommandId T.Text deriving (Show, Read, Eq, Ord) @@ -1259,6 +1266,20 @@ mkLspCmdId pid (PluginId plid) (CommandId cid) getPid :: IO T.Text getPid = T.pack . show <$> getProcessID +getVirtualFileFromVFS :: VFS -> NormalizedUri -> Maybe VirtualFile +getVirtualFileFromVFS (VFS vfs) uri = + case Map.lookup uri vfs of + Just (Open x) -> Just x + Just (Closed _) -> Nothing + Nothing -> Nothing + +getVirtualFileFromVFSIncludingClosed :: VFS -> NormalizedUri -> Maybe VirtualFileEntry +getVirtualFileFromVFSIncludingClosed (VFS vfs) uri = + case Map.lookup uri vfs of + Just x -> Just x + Nothing -> Nothing + + getProcessID :: IO Int installSigUsr1Handler :: IO () -> IO () diff --git a/hls-test-utils/hls-test-utils.cabal b/hls-test-utils/hls-test-utils.cabal index 978641fe0c..cbe167ba1c 100644 --- a/hls-test-utils/hls-test-utils.cabal +++ b/hls-test-utils/hls-test-utils.cabal @@ -48,8 +48,8 @@ library , hls-plugin-api == 2.13.0.0 , lens , lsp - , lsp-test ^>=0.17 - , lsp-types ^>=2.3 + , lsp-test ^>=0.18 + , lsp-types ^>=2.4 , safe-exceptions , string-interpolate >= 0.3.1 , tasty diff --git a/plugins/hls-semantic-tokens-plugin/test/SemanticTokensTest.hs b/plugins/hls-semantic-tokens-plugin/test/SemanticTokensTest.hs index a0d1648fb3..4cc3ae8ae1 100644 --- a/plugins/hls-semantic-tokens-plugin/test/SemanticTokensTest.hs +++ b/plugins/hls-semantic-tokens-plugin/test/SemanticTokensTest.hs @@ -22,6 +22,7 @@ import Ide.Plugin.SemanticTokens.Types import Ide.Types import qualified Language.LSP.Protocol.Lens as L import Language.LSP.Protocol.Types +import qualified Language.LSP.Protocol.Types as J import qualified Language.LSP.Test as Test import Language.LSP.VFS (VirtualFile (..)) import System.FilePath @@ -90,7 +91,7 @@ docLspSemanticTokensString :: (HasCallStack) => TextDocumentIdentifier -> Sessio docLspSemanticTokensString doc = do res <- Test.getSemanticTokens doc textContent <- documentContents doc - let vfs = VirtualFile 0 0 (Rope.fromText textContent) + let vfs = VirtualFile 0 0 (Rope.fromText textContent) $ Just J.LanguageKind_Haskell case res ^? Language.LSP.Protocol.Types._L of Just tokens -> do either (error . show) pure $ recoverLspSemanticTokens vfs tokens diff --git a/plugins/hls-signature-help-plugin/test/Main.hs b/plugins/hls-signature-help-plugin/test/Main.hs index 466a336621..9e3b0c0ea3 100644 --- a/plugins/hls-signature-help-plugin/test/Main.hs +++ b/plugins/hls-signature-help-plugin/test/Main.hs @@ -2,14 +2,10 @@ {-# LANGUAGE QuasiQuotes #-} import Control.Arrow ((>>>)) -import Control.Exception (throw) -import Control.Lens ((^.)) -import Data.Maybe (fromJust) import Data.Text (Text) import qualified Data.Text as T import Development.IDE.Plugin.Completions.Types (PosPrefixInfo (PosPrefixInfo)) import Ide.Plugin.SignatureHelp (descriptor) -import qualified Language.LSP.Protocol.Lens as L import Test.Hls import Test.Hls.FileSystem (VirtualFileTree, directCradle, file, @@ -411,7 +407,7 @@ getSignatureHelpFromSession sourceCode (PosPrefixInfo _ _ _ position) = virtualFileTree = mkVirtualFileTreeWithSingleFile fileName sourceCode in runSessionWithServerInTmpDir def plugin virtualFileTree $ do doc <- openDoc fileName "haskell" - (fmap . fmap) SimilarSignatureHelp (getSignatureHelp doc position) + (fmap . fmap) SimilarSignatureHelp (getSignatureHelp doc position Nothing) mkVirtualFileTreeWithSingleFile :: FilePath -> Text -> VirtualFileTree mkVirtualFileTreeWithSingleFile fileName sourceCode = @@ -499,16 +495,3 @@ instance (IsSimilar a, IsSimilar b) => IsSimilar (a |? b) where InL x ~= InL y = x ~= y InR x ~= InR y = x ~= y _ ~= _ = False - --- TODO use the one from lsp-test when we have https://github.com/haskell/lsp/pull/621 - --- | Returns the signature help at the specified position. -getSignatureHelp :: TextDocumentIdentifier -> Position -> Session (Maybe SignatureHelp) -getSignatureHelp doc pos = - let params = SignatureHelpParams doc pos Nothing Nothing - in nullToMaybe . getResponseResult <$> request SMethod_TextDocumentSignatureHelp params - where - getResponseResult rsp = - case rsp ^. L.result of - Right x -> x - Left err -> throw $ UnexpectedResponseError (fromJust $ rsp ^. L.id) err diff --git a/stack-lts22.yaml b/stack-lts22.yaml index 781ab7b032..c21edfd924 100644 --- a/stack-lts22.yaml +++ b/stack-lts22.yaml @@ -19,12 +19,13 @@ allow-newer-deps: extra-deps: - Diff-0.5 - hiedb-0.8.0.0 - - hie-bios-0.17.0 + - hie-bios-0.18.0 - hie-compat-0.3.1.2 - implicit-hie-0.1.4.0 - - lsp-2.7.0.0 - - lsp-test-0.17.1.0 - - lsp-types-2.3.0.0 + - lsp-2.8.0.0 + - lsp-test-0.18.0.0 + - lsp-types-2.4.0.0 + - websockets-0.13.0.0@sha256:9b3680ba5055e0b34ab29c341b21d70084bf067519fc059af0e597cd90a4a05a,7567 - monad-dijkstra-0.1.1.4 # 5 - retrie-1.2.3 - unordered-containers-0.2.21 diff --git a/stack.yaml b/stack.yaml index 7fa7f029f4..969cbd9ad1 100644 --- a/stack.yaml +++ b/stack.yaml @@ -22,12 +22,14 @@ extra-deps: - hiedb-0.8.0.0 - hie-compat-0.3.1.2 - implicit-hie-0.1.4.0 - - hie-bios-0.17.0 + - hie-bios-0.18.0 - hw-fingertree-0.1.2.1 - monad-dijkstra-0.1.1.5 - retrie-1.2.3 - unordered-containers-0.2.21 - + - lsp-2.8.0.0 + - lsp-test-0.18.0.0 + - lsp-types-2.4.0.0 # stan dependencies not found in the stackage snapshot - stan-0.2.1.0 - dir-traverse-0.2.3.0