-
-
Notifications
You must be signed in to change notification settings - Fork 391
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
Changes from all commits
8adb03e
4e65cbe
d4a9d4e
e1b62cb
e34da52
ca81317
1776bd8
bc093c2
9bc837a
40d589c
fd11649
15cf638
cdc0364
d78f2bc
9b539d9
d415379
e618d7e
6fee73f
6cbe6d9
e0bbec1
6102e6b
953003a
9bbf421
afcf19d
77d264f
1a22bcc
28bdecc
1dd12d4
ba4fa79
89bba81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
{-# 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could consider generalizing these functions to |
||
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 | ||
joyfulmantis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 `uses` that throws a PluginRuleFailed upon failure | ||
usesE :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> ExceptT PluginError Action (f v) | ||
usesE k = maybeToExceptT (PluginRuleFailed (T.pack $ show k)) . usesMT k | ||
|
||
-- |MaybeT version of `uses` | ||
usesMT :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> MaybeT Action (f v) | ||
usesMT k xs = MaybeT $ sequence <$> Shake.uses k xs | ||
|
||
-- |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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 :/ There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 PluginInvalidUserState | ||
-- upon failure | ||
toCurrentPositionE :: Monad m => PositionMapping -> LSP.Position -> ExceptT PluginError m LSP.Position | ||
toCurrentPositionE mapping = maybeToExceptT (PluginInvalidUserState "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 | ||
-- PluginInvalidUserState upon failure | ||
fromCurrentPositionE :: Monad m => PositionMapping -> LSP.Position -> ExceptT PluginError m LSP.Position | ||
fromCurrentPositionE mapping = maybeToExceptT (PluginInvalidUserState "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 PluginInvalidUserState | ||
-- upon failure | ||
toCurrentRangeE :: Monad m => PositionMapping -> LSP.Range -> ExceptT PluginError m LSP.Range | ||
toCurrentRangeE mapping = maybeToExceptT (PluginInvalidUserState "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 PluginInvalidUserState | ||
-- upon failure | ||
fromCurrentRangeE :: Monad m => PositionMapping -> LSP.Range -> ExceptT PluginError m LSP.Range | ||
fromCurrentRangeE mapping = maybeToExceptT (PluginInvalidUserState "fromCurrentRange") . fromCurrentRangeMT mapping | ||
|
||
-- |MaybeT version of `fromCurrentRange` | ||
fromCurrentRangeMT :: Monad m => PositionMapping -> LSP.Range -> MaybeT m LSP.Range | ||
fromCurrentRangeMT mapping = MaybeT . pure . fromCurrentRange mapping |
Uh oh!
There was an error while loading. Please reload this page.