Skip to content

Better plugin error infrastructure #3717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8adb03e
WIP
fendor Jun 15, 2023
4e65cbe
Merge fendor/enhance/plugin-logger-structure
joyfulmantis Jul 13, 2023
d4a9d4e
Make compilable
joyfulmantis Jul 14, 2023
e1b62cb
merge upstream/master
joyfulmantis Jul 14, 2023
e34da52
Flatten error hierarchy and avoid name clashes
joyfulmantis Jul 18, 2023
ca81317
merge upstream/master
joyfulmantis Jul 18, 2023
1776bd8
Replace ResponseError with PluginError for plugins
joyfulmantis Jul 20, 2023
bc093c2
Further support for PluginError in HLS.hs among other enhancements
joyfulmantis Jul 21, 2023
9bc837a
Further improvements
joyfulmantis Jul 22, 2023
40d589c
Fix code-range test
joyfulmantis Jul 22, 2023
fd11649
Merge branch 'master' into plugin-logger
joyfulmantis Jul 22, 2023
15cf638
Fix build error
joyfulmantis Jul 22, 2023
cdc0364
Added note
joyfulmantis Jul 24, 2023
d78f2bc
merge upstream/master
joyfulmantis Jul 26, 2023
9b539d9
address michaelpj's suggestions (1/n)
joyfulmantis Jul 27, 2023
d415379
more improvements
joyfulmantis Jul 28, 2023
e618d7e
window build fix attempt
joyfulmantis Jul 28, 2023
6fee73f
Fix stack and windows builds
joyfulmantis Jul 28, 2023
6cbe6d9
Fix code-range test
joyfulmantis Jul 28, 2023
e0bbec1
refactor splice and eval to remove underscore func
joyfulmantis Jul 28, 2023
6102e6b
Fix hls-tactics-plugin test
joyfulmantis Jul 28, 2023
953003a
Broke up the ghcide test file
joyfulmantis Jul 29, 2023
9bbf421
have CommandFunction use ExceptT
joyfulmantis Jul 29, 2023
afcf19d
add tests for exceptions and PluginError order
joyfulmantis Jul 29, 2023
77d264f
fix tactics build
joyfulmantis Jul 29, 2023
1a22bcc
fix tactics try 2
joyfulmantis Jul 29, 2023
28bdecc
fix tactics build try 3
joyfulmantis Jul 29, 2023
1dd12d4
fix for real this time
joyfulmantis Jul 29, 2023
ba4fa79
Fix hlint rules
joyfulmantis Jul 29, 2023
89bba81
hlint rule fixes try 2
joyfulmantis Jul 29, 2023
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
1 change: 1 addition & 0 deletions ghcide/ghcide.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ library
Development.IDE.Core.FileUtils
Development.IDE.Core.IdeConfiguration
Development.IDE.Core.OfInterest
Development.IDE.Core.PluginUtils
Development.IDE.Core.PositionMapping
Development.IDE.Core.Preprocessor
Development.IDE.Core.ProgressReporting
Expand Down
6 changes: 2 additions & 4 deletions ghcide/src/Development/IDE.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ module Development.IDE

import Development.IDE.Core.Actions as X (getAtPoint,
getDefinition,
getTypeDefinition,
useE, useNoFileE,
usesE)
getTypeDefinition)
import Development.IDE.Core.FileExists as X (getFileExists)
import Development.IDE.Core.FileStore as X (getFileContents)
import Development.IDE.Core.IdeConfiguration as X (IdeConfiguration (..),
Expand Down Expand Up @@ -55,4 +53,4 @@ import Development.IDE.Types.HscEnvEq as X (HscEnvEq (..),
hscEnv,
hscEnvWithImportPaths)
import Development.IDE.Types.Location as X
import Ide.Logger as X
import Ide.Logger as X
33 changes: 10 additions & 23 deletions ghcide/src/Development/IDE/Core/Actions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ module Development.IDE.Core.Actions
, getTypeDefinition
, highlightAtPoint
, refsAtPoint
, useE
, useNoFileE
, usesE
, workspaceSymbols
, lookupMod
) where
Expand All @@ -21,6 +18,7 @@ import Data.Maybe
import qualified Data.Text as T
import Data.Tuple.Extra
import Development.IDE.Core.OfInterest
import Development.IDE.Core.PluginUtils
import Development.IDE.Core.PositionMapping
import Development.IDE.Core.RuleTypes
import Development.IDE.Core.Service
Expand Down Expand Up @@ -49,7 +47,7 @@ lookupMod
lookupMod _dbchan _hie_f _mod _uid _boot = MaybeT $ pure Nothing


-- IMPORTANT NOTE : make sure all rules `useE`d by these have a "Persistent Stale" rule defined,
-- IMPORTANT NOTE : make sure all rules `useWithStaleFastMT`d by these have a "Persistent Stale" rule defined,
-- so we can quickly answer as soon as the IDE is opened
-- Even if we don't have persistent information on disk for these rules, the persistent rule
-- should just return an empty result
Expand All @@ -62,9 +60,9 @@ getAtPoint file pos = runMaybeT $ do
ide <- ask
opts <- liftIO $ getIdeOptionsIO ide

(hf, mapping) <- useE GetHieAst file
env <- hscEnv . fst <$> useE GhcSession file
dkMap <- lift $ maybe (DKMap mempty mempty) fst <$> runMaybeT (useE GetDocMap file)
(hf, mapping) <- useWithStaleFastMT GetHieAst file
env <- hscEnv . fst <$> useWithStaleFastMT GhcSession file
dkMap <- lift $ maybe (DKMap mempty mempty) fst <$> runMaybeT (useWithStaleFastMT GetDocMap file)

!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
MaybeT $ pure $ first (toCurrentRange mapping =<<) <$> AtPoint.atPoint opts hf dkMap env pos'
Expand Down Expand Up @@ -94,30 +92,19 @@ toCurrentLocations mapping file = mapMaybeM go
else do
otherLocationMapping <- fmap (fmap snd) $ runMaybeT $ do
otherLocationFile <- MaybeT $ pure $ uriToNormalizedFilePath nUri
useE GetHieAst otherLocationFile
useWithStaleFastMT GetHieAst otherLocationFile
pure $ Location uri <$> (flip toCurrentRange range =<< otherLocationMapping)
where
nUri :: NormalizedUri
nUri = toNormalizedUri uri

-- | useE is useful to implement functions that aren’t rules but need shortcircuiting
-- e.g. getDefinition.
useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT IdeAction (v, PositionMapping)
useE k = MaybeT . useWithStaleFast k

useNoFileE :: IdeRule k v => IdeState -> k -> MaybeT IdeAction v
useNoFileE _ide k = fst <$> useE k emptyFilePath

usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT IdeAction [(v,PositionMapping)]
usesE k = MaybeT . fmap sequence . mapM (useWithStaleFast k)

-- | Goto Definition.
getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location])
getDefinition file pos = runMaybeT $ do
ide@ShakeExtras{ withHieDb, hiedbWriter } <- ask
opts <- liftIO $ getIdeOptionsIO ide
(HAR _ hf _ _ _, mapping) <- useE GetHieAst file
(ImportMap imports, _) <- useE GetImportMap file
(HAR _ hf _ _ _, mapping) <- useWithStaleFastMT GetHieAst file
(ImportMap imports, _) <- useWithStaleFastMT GetImportMap file
!pos' <- MaybeT (pure $ fromCurrentPosition mapping pos)
locations <- AtPoint.gotoDefinition withHieDb (lookupMod hiedbWriter) opts imports hf pos'
MaybeT $ Just <$> toCurrentLocations mapping file locations
Expand All @@ -126,14 +113,14 @@ getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Locatio
getTypeDefinition file pos = runMaybeT $ do
ide@ShakeExtras{ withHieDb, hiedbWriter } <- ask
opts <- liftIO $ getIdeOptionsIO ide
(hf, mapping) <- useE GetHieAst file
(hf, mapping) <- useWithStaleFastMT GetHieAst file
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
locations <- AtPoint.gotoTypeDefinition withHieDb (lookupMod hiedbWriter) opts hf pos'
MaybeT $ Just <$> toCurrentLocations mapping file locations

highlightAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe [DocumentHighlight])
highlightAtPoint file pos = runMaybeT $ do
(HAR _ hf rf _ _,mapping) <- useE GetHieAst file
(HAR _ hf rf _ _,mapping) <- useWithStaleFastMT GetHieAst file
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
let toCurrentHighlight (DocumentHighlight range t) = flip DocumentHighlight t <$> toCurrentRange mapping range
mapMaybe toCurrentHighlight <$>AtPoint.documentHighlight hf rf pos'
Expand Down
132 changes: 132 additions & 0 deletions ghcide/src/Development/IDE/Core/PluginUtils.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{-# LANGUAGE GADTs #-}
module Development.IDE.Core.PluginUtils where

import Control.Monad.Extra
import Control.Monad.IO.Class
import Control.Monad.Reader (runReaderT)
import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe
import Data.Functor.Identity
import qualified Data.Text as T
import Development.IDE.Core.PositionMapping
import Development.IDE.Core.Shake (IdeAction, IdeRule,
IdeState (shakeExtras),
mkDelayedAction,
shakeEnqueue)
import qualified Development.IDE.Core.Shake as Shake
import Development.IDE.GHC.Orphans ()
import Development.IDE.Graph hiding (ShakeValue)
import Development.IDE.Types.Location (NormalizedFilePath)
import qualified Development.IDE.Types.Location as Location
import qualified Ide.Logger as Logger
import Ide.Plugin.Error
import qualified Language.LSP.Protocol.Types as LSP

-- ----------------------------------------------------------------------------
-- Action wrappers
-- ----------------------------------------------------------------------------

-- |ExceptT version of `runAction`, takes a ExceptT Action
runActionE :: MonadIO m => String -> IdeState -> ExceptT e Action a -> ExceptT e m a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could consider generalizing these functions to MonadError rather than ExceptT. Not sure that buys us much, I probably would instinctively do it, but I'm used to programming in a very mtl-y way!

runActionE herald ide act =
mapExceptT liftIO . ExceptT $
join $ shakeEnqueue (shakeExtras ide) (mkDelayedAction herald Logger.Debug $ runExceptT act)

-- |MaybeT version of `runAction`, takes a MaybeT Action
runActionMT :: MonadIO m => String -> IdeState -> MaybeT Action a -> MaybeT m a
runActionMT herald ide act =
mapMaybeT liftIO . MaybeT $
join $ shakeEnqueue (shakeExtras ide) (mkDelayedAction herald Logger.Debug $ runMaybeT act)

-- |ExceptT version of `use` that throws a PluginRuleFailed upon failure
useE :: IdeRule k v => k -> NormalizedFilePath -> ExceptT PluginError Action v
useE k = maybeToExceptT (PluginRuleFailed (T.pack $ show k)) . useMT k

-- |MaybeT version of `use`
useMT :: IdeRule k v => k -> NormalizedFilePath -> MaybeT Action v
useMT k = MaybeT . Shake.use k

-- |ExceptT version of `useWithStale` that throws a PluginRuleFailed upon
-- failure
useWithStaleE :: IdeRule k v
=> k -> NormalizedFilePath -> ExceptT PluginError Action (v, PositionMapping)
useWithStaleE key = maybeToExceptT (PluginRuleFailed (T.pack $ show key)) . useWithStaleMT key

-- |MaybeT version of `useWithStale`
useWithStaleMT :: IdeRule k v
=> k -> NormalizedFilePath -> MaybeT Action (v, PositionMapping)
useWithStaleMT key file = MaybeT $ runIdentity <$> Shake.usesWithStale key (Identity file)

-- ----------------------------------------------------------------------------
-- IdeAction wrappers
-- ----------------------------------------------------------------------------

-- |ExceptT version of `runIdeAction`, takes a ExceptT IdeAction
runIdeActionE :: MonadIO m => String -> Shake.ShakeExtras -> ExceptT e IdeAction a -> ExceptT e m a
runIdeActionE _herald s i = ExceptT $ liftIO $ runReaderT (Shake.runIdeActionT $ runExceptT i) s

-- |MaybeT version of `runIdeAction`, takes a MaybeT IdeAction
runIdeActionMT :: MonadIO m => String -> Shake.ShakeExtras -> MaybeT IdeAction a -> MaybeT m a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really need to remind myself what the difference between IdeAction and Action is :/

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IdeAction are read-only while Action can produce results, iirc.

runIdeActionMT _herald s i = MaybeT $ liftIO $ runReaderT (Shake.runIdeActionT $ runMaybeT i) s

-- |ExceptT version of `useWithStaleFast` that throws a PluginRuleFailed upon
-- failure
useWithStaleFastE :: IdeRule k v => k -> NormalizedFilePath -> ExceptT PluginError IdeAction (v, PositionMapping)
useWithStaleFastE k = maybeToExceptT (PluginRuleFailed (T.pack $ show k)) . useWithStaleFastMT k

-- |MaybeT version of `useWithStaleFast`
useWithStaleFastMT :: IdeRule k v => k -> NormalizedFilePath -> MaybeT IdeAction (v, PositionMapping)
useWithStaleFastMT k = MaybeT . Shake.useWithStaleFast k

-- ----------------------------------------------------------------------------
-- Location wrappers
-- ----------------------------------------------------------------------------

-- |ExceptT version of `uriToFilePath` that throws a PluginInvalidParams upon
-- failure
uriToFilePathE :: Monad m => LSP.Uri -> ExceptT PluginError m FilePath
uriToFilePathE uri = maybeToExceptT (PluginInvalidParams (T.pack $ "uriToFilePath' failed. Uri:" <> show uri)) $ uriToFilePathMT uri

-- |MaybeT version of `uriToFilePath`
uriToFilePathMT :: Monad m => LSP.Uri -> MaybeT m FilePath
uriToFilePathMT = MaybeT . pure . Location.uriToFilePath'

-- ----------------------------------------------------------------------------
-- PositionMapping wrappers
-- ----------------------------------------------------------------------------

-- |ExceptT version of `toCurrentPosition` that throws a PluginDependencyFailed
-- upon failure
toCurrentPositionE :: Monad m => PositionMapping -> LSP.Position -> ExceptT PluginError m LSP.Position
toCurrentPositionE mapping = maybeToExceptT (PluginDependencyFailed "toCurrentPosition"). toCurrentPositionMT mapping

-- |MaybeT version of `toCurrentPosition`
toCurrentPositionMT :: Monad m => PositionMapping -> LSP.Position -> MaybeT m LSP.Position
toCurrentPositionMT mapping = MaybeT . pure . toCurrentPosition mapping

-- |ExceptT version of `fromCurrentPosition` that throws a PluginDependencyFailed
-- upon failure
fromCurrentPositionE :: Monad m => PositionMapping -> LSP.Position -> ExceptT PluginError m LSP.Position
fromCurrentPositionE mapping = maybeToExceptT (PluginDependencyFailed "fromCurrentPosition") . fromCurrentPositionMT mapping

-- |MaybeT version of `fromCurrentPosition`
fromCurrentPositionMT :: Monad m => PositionMapping -> LSP.Position -> MaybeT m LSP.Position
fromCurrentPositionMT mapping = MaybeT . pure . fromCurrentPosition mapping

-- |ExceptT version of `toCurrentRange` that throws a PluginDependencyFailed
-- upon failure
toCurrentRangeE :: Monad m => PositionMapping -> LSP.Range -> ExceptT PluginError m LSP.Range
toCurrentRangeE mapping = maybeToExceptT (PluginDependencyFailed "toCurrentRange") . toCurrentRangeMT mapping

-- |MaybeT version of `toCurrentRange`
toCurrentRangeMT :: Monad m => PositionMapping -> LSP.Range -> MaybeT m LSP.Range
toCurrentRangeMT mapping = MaybeT . pure . toCurrentRange mapping

-- |ExceptT version of `fromCurrentRange` that throws a PluginDependencyFailed
-- upon failure
fromCurrentRangeE :: Monad m => PositionMapping -> LSP.Range -> ExceptT PluginError m LSP.Range
fromCurrentRangeE mapping = maybeToExceptT (PluginDependencyFailed "fromCurrentRange") . fromCurrentRangeMT mapping

-- |MaybeT version of `fromCurrentRange`
fromCurrentRangeMT :: Monad m => PositionMapping -> LSP.Range -> MaybeT m LSP.Range
fromCurrentRangeMT mapping = MaybeT . pure . fromCurrentRange mapping
10 changes: 7 additions & 3 deletions ghcide/src/Development/IDE/Core/Shake.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ module Development.IDE.Core.Shake(
garbageCollectDirtyKeys,
garbageCollectDirtyKeysOlderThan,
Log(..),
VFSModified(..), getClientConfigAction
VFSModified(..), getClientConfigAction,
) where

import Control.Concurrent.Async
Expand Down Expand Up @@ -152,15 +152,15 @@ import Development.IDE.Types.Exports
import qualified Development.IDE.Types.Exports as ExportsMap
import Development.IDE.Types.KnownTargets
import Development.IDE.Types.Location
import Ide.Logger hiding (Priority)
import qualified Ide.Logger as Logger
import Development.IDE.Types.Monitoring (Monitoring (..))
import Development.IDE.Types.Options
import Development.IDE.Types.Shake
import qualified Focus
import GHC.Fingerprint
import GHC.Stack (HasCallStack)
import HieDb.Types
import Ide.Logger hiding (Priority)
import qualified Ide.Logger as Logger
import Ide.Plugin.Config
import qualified Ide.PluginUtils as HLS
import Ide.Types (IdePlugins (IdePlugins),
Expand Down Expand Up @@ -963,11 +963,15 @@ useWithStale key file = runIdentity <$> usesWithStale key (Identity file)

-- | Request a Rule result, it not available return the last computed result which may be stale.
-- Errors out if none available.
--
-- The thrown error is a 'BadDependency' error which is caught by the rule system.
useWithStale_ :: IdeRule k v
=> k -> NormalizedFilePath -> Action (v, PositionMapping)
useWithStale_ key file = runIdentity <$> usesWithStale_ key (Identity file)

-- | Plural version of 'useWithStale_'
--
-- The thrown error is a 'BadDependency' error which is caught by the rule system.
usesWithStale_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (v, PositionMapping))
usesWithStale_ key files = do
res <- usesWithStale key files
Expand Down
1 change: 1 addition & 0 deletions ghcide/src/Development/IDE/Core/Tracing.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PatternSynonyms #-}
{-# HLINT ignore #-}

module Development.IDE.Core.Tracing
( otTracedHandler
, otTracedAction
Expand Down
36 changes: 18 additions & 18 deletions ghcide/src/Development/IDE/LSP/HoverDefinition.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,43 @@ module Development.IDE.LSP.HoverDefinition
, wsSymbols
) where

import Control.Monad.Except (ExceptT)
import Control.Monad.IO.Class
import Data.Maybe (fromMaybe)
import Development.IDE.Core.Actions
import Development.IDE.Core.Rules
import Development.IDE.Core.Shake
import Development.IDE.Types.Location
import Ide.Logger
import Ide.Plugin.Error
import Ide.Types
import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types
import qualified Language.LSP.Server as LSP

import qualified Data.Text as T

gotoDefinition :: IdeState -> TextDocumentPositionParams -> LSP.LspM c (Either ResponseError (MessageResult Method_TextDocumentDefinition))
hover :: IdeState -> TextDocumentPositionParams -> LSP.LspM c (Either ResponseError (Hover |? Null))
gotoTypeDefinition :: IdeState -> TextDocumentPositionParams -> LSP.LspM c (Either ResponseError (MessageResult Method_TextDocumentTypeDefinition))
documentHighlight :: IdeState -> TextDocumentPositionParams -> LSP.LspM c (Either ResponseError ([DocumentHighlight] |? Null))
gotoDefinition :: IdeState -> TextDocumentPositionParams -> ExceptT PluginError (LSP.LspM c) (MessageResult Method_TextDocumentDefinition)
hover :: IdeState -> TextDocumentPositionParams -> ExceptT PluginError (LSP.LspM c) (Hover |? Null)
gotoTypeDefinition :: IdeState -> TextDocumentPositionParams -> ExceptT PluginError (LSP.LspM c) (MessageResult Method_TextDocumentTypeDefinition)
documentHighlight :: IdeState -> TextDocumentPositionParams -> ExceptT PluginError (LSP.LspM c) ([DocumentHighlight] |? Null)
gotoDefinition = request "Definition" getDefinition (InR $ InR Null) (InL . Definition. InR)
gotoTypeDefinition = request "TypeDefinition" getTypeDefinition (InR $ InR Null) (InL . Definition. InR)
hover = request "Hover" getAtPoint (InR Null) foundHover
documentHighlight = request "DocumentHighlight" highlightAtPoint (InR Null) InL

references :: IdeState -> ReferenceParams -> LSP.LspM c (Either ResponseError ([Location] |? Null))
references ide (ReferenceParams (TextDocumentIdentifier uri) pos _ _ _) = liftIO $
case uriToFilePath' uri of
Just path -> do
let filePath = toNormalizedFilePath' path
logDebug (ideLogger ide) $
references :: PluginMethodHandler IdeState 'Method_TextDocumentReferences
references ide _ (ReferenceParams (TextDocumentIdentifier uri) pos _ _ _) = do
nfp <- getNormalizedFilePathE uri
liftIO $ logDebug (ideLogger ide) $
"References request at position " <> T.pack (showPosition pos) <>
" in file: " <> T.pack path
Right . InL <$> (runAction "references" ide $ refsAtPoint filePath pos)
Nothing -> pure $ Left $ ResponseError (InR ErrorCodes_InvalidParams) ("Invalid URI " <> T.pack (show uri)) Nothing
" in file: " <> T.pack (show nfp)
InL <$> (liftIO $ runAction "references" ide $ refsAtPoint nfp pos)

wsSymbols :: IdeState -> WorkspaceSymbolParams -> LSP.LspM c (Either ResponseError [SymbolInformation])
wsSymbols ide (WorkspaceSymbolParams _ _ query) = liftIO $ do
wsSymbols :: PluginMethodHandler IdeState 'Method_WorkspaceSymbol
wsSymbols ide _ (WorkspaceSymbolParams _ _ query) = liftIO $ do
logDebug (ideLogger ide) $ "Workspace symbols request: " <> query
runIdeAction "WorkspaceSymbols" (shakeExtras ide) $ Right . fromMaybe [] <$> workspaceSymbols query
runIdeAction "WorkspaceSymbols" (shakeExtras ide) $ InL . fromMaybe [] <$> workspaceSymbols query

foundHover :: (Maybe Range, [T.Text]) -> Hover |? Null
foundHover (mbRange, contents) =
Expand All @@ -65,12 +65,12 @@ request
-> (a -> b)
-> IdeState
-> TextDocumentPositionParams
-> LSP.LspM c (Either ResponseError b)
-> ExceptT PluginError (LSP.LspM c) b
request label getResults notFound found ide (TextDocumentPositionParams (TextDocumentIdentifier uri) pos) = liftIO $ do
mbResult <- case uriToFilePath' uri of
Just path -> logAndRunRequest label getResults ide pos path
Nothing -> pure Nothing
pure $ Right $ maybe notFound found mbResult
pure $ maybe notFound found mbResult

logAndRunRequest :: T.Text -> (NormalizedFilePath -> Position -> IdeAction b) -> IdeState -> Position -> String -> IO b
logAndRunRequest label getResults ide pos path = do
Expand Down
Loading