packages feed

haskell-lsp 0.10.0.0 → 0.11.0.0

raw patch · 5 files changed

+99/−44 lines, 5 filesdep +asyncdep ~haskell-lsp-typesPVP ok

version bump matches the API change (PVP)

Dependencies added: async

Dependency ranges changed: haskell-lsp-types

API changes (from Hackage documentation)

- Language.Haskell.LSP.Core: [resNextProgressId] :: LanguageContextData a -> !Int
+ Language.Haskell.LSP.Core: Cancellable :: ProgressCancellable
+ Language.Haskell.LSP.Core: NotCancellable :: ProgressCancellable
+ Language.Haskell.LSP.Core: [resProgressData] :: LanguageContextData a -> !ProgressData
+ Language.Haskell.LSP.Core: [reverseMap] :: LanguageContextData a -> !Map FilePath FilePath
+ Language.Haskell.LSP.Core: data ProgressCancellable
+ Language.Haskell.LSP.Core: data ProgressCancelledException
+ Language.Haskell.LSP.Core: instance GHC.Exception.Type.Exception Language.Haskell.LSP.Core.ProgressCancelledException
+ Language.Haskell.LSP.Core: instance GHC.Show.Show Language.Haskell.LSP.Core.ProgressCancelledException
- Language.Haskell.LSP.Core: LanguageContextData :: !Int -> !Handlers -> !Options -> !SendFunc -> !VFS -> !DiagnosticStore -> !Maybe a -> !TVar Int -> LspFuncs a -> !Maybe FilePath -> ![WorkspaceFolder] -> !Int -> LanguageContextData a
+ Language.Haskell.LSP.Core: LanguageContextData :: !Int -> !Handlers -> !Options -> !SendFunc -> !VFS -> !Map FilePath FilePath -> !DiagnosticStore -> !Maybe a -> !TVar Int -> LspFuncs a -> !Maybe FilePath -> ![WorkspaceFolder] -> !ProgressData -> LanguageContextData a
- Language.Haskell.LSP.Core: LspFuncs :: !ClientCapabilities -> !IO (Maybe c) -> !SendFunc -> !Uri -> IO (Maybe VirtualFile) -> !PublishDiagnosticsFunc -> !FlushDiagnosticsBySourceFunc -> !IO LspId -> !Maybe FilePath -> !IO (Maybe [WorkspaceFolder]) -> !forall m a. MonadIO m => Text -> ((Progress -> m ()) -> m a) -> m a -> !forall m a. MonadIO m => Text -> m a -> m a -> LspFuncs c
+ Language.Haskell.LSP.Core: LspFuncs :: !ClientCapabilities -> !IO (Maybe c) -> !SendFunc -> !Uri -> IO (Maybe VirtualFile) -> !PublishDiagnosticsFunc -> !FlushDiagnosticsBySourceFunc -> !IO LspId -> !Maybe FilePath -> !IO (Maybe [WorkspaceFolder]) -> !forall a. Text -> ProgressCancellable -> ((Progress -> IO ()) -> IO a) -> IO a -> !forall a. Text -> ProgressCancellable -> IO a -> IO a -> LspFuncs c
- Language.Haskell.LSP.Core: [withIndefiniteProgress] :: LspFuncs c -> !forall m a. MonadIO m => Text -> m a -> m a
+ Language.Haskell.LSP.Core: [withIndefiniteProgress] :: LspFuncs c -> !forall a. Text -> ProgressCancellable -> IO a -> IO a
- Language.Haskell.LSP.Core: [withProgress] :: LspFuncs c -> !forall m a. MonadIO m => Text -> ((Progress -> m ()) -> m a) -> m a
+ Language.Haskell.LSP.Core: [withProgress] :: LspFuncs c -> !forall a. Text -> ProgressCancellable -> ((Progress -> IO ()) -> IO a) -> IO a
- Language.Haskell.LSP.Messages: NotProgressCancel :: ProgressCancelNotification -> FromServerMessage
+ Language.Haskell.LSP.Messages: NotProgressCancel :: ProgressCancelNotification -> FromClientMessage

Files

ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for haskell-lsp +## 0.11.0.0 -- 2019-04-28++* Add support for cancellable requests within `withProgress` and+  `withIndefiniteProgress`+* Align `withProgress` and `withIndefiniteProgress` types to be in `IO`+  like the rest of the library. (Look at using `monad-control` and+  `unliftio` if you need to use them with a Monad transformer stack)+ ## 0.10.0.0 -- 2019-04-22  * Add `withProgress` and `withIndefiniteProgress` functions for sending
example/Main.hs view
@@ -238,7 +238,7 @@          let           ht = Just $ J.Hover ms (Just range)-          ms = J.HoverContentsMS $ J.List [J.CodeString $ J.LanguageString "lsp-hello" "TYPE INFO" ]+          ms = J.HoverContents $ J.markedUpContent "lsp-hello" "TYPE INFO"           range = J.Range pos pos         reactorSend $ RspHover $ Core.makeResponseMessage req ht 
haskell-lsp.cabal view
@@ -1,5 +1,5 @@ name:                haskell-lsp-version:             0.10.0.0+version:             0.11.0.0 synopsis:            Haskell library for the Microsoft Language Server Protocol  description:         An implementation of the types, and basic message server to@@ -36,6 +36,7 @@  -- other-extensions:   ghc-options:         -Wall   build-depends:       base >=4.9 && <4.13+                     , async                      , aeson >=1.0.0.0                      , bytestring                      , containers@@ -44,7 +45,7 @@                      , filepath                      , hslogger                      , hashable-                     , haskell-lsp-types >= 0.10.0+                     , haskell-lsp-types == 0.11.*                      , lens >= 4.15.2                      , mtl                      , network-uri
src/Language/Haskell/LSP/Core.hs view
@@ -12,6 +12,8 @@   , InitializeCallback   , LspFuncs(..)   , Progress(..)+  , ProgressCancellable(..)+  , ProgressCancelledException   , SendFunc   , Handlers(..)   , Options(..)@@ -26,6 +28,7 @@   ) where  import           Control.Concurrent.STM+import           Control.Concurrent.Async import qualified Control.Exception as E import           Control.Monad import           Control.Monad.IO.Class@@ -76,15 +79,19 @@   , resOptions             :: !Options   , resSendResponse        :: !SendFunc   , resVFS                 :: !VFS+  , reverseMap             :: !(Map.Map FilePath FilePath)   , resDiagnostics         :: !DiagnosticStore   , resConfig              :: !(Maybe a)   , resLspId               :: !(TVar Int)   , resLspFuncs            :: LspFuncs a -- NOTE: Cannot be strict, lazy initialization   , resCaptureFile         :: !(Maybe FilePath)   , resWorkspaceFolders    :: ![J.WorkspaceFolder]-  , resNextProgressId      :: !Int+  , resProgressData        :: !ProgressData   } +data ProgressData = ProgressData { progressNextId :: !Int+                                 , progressCancel :: !(Map.Map Text (IO ())) }+ -- ---------------------------------------------------------------------  -- | Language Server Protocol options supported by the given language server.@@ -123,8 +130,23 @@  -- | A package indicating the perecentage of progress complete and a -- an optional message to go with it during a 'withProgress'+--+-- @since 0.10.0.0 data Progress = Progress (Maybe Double) (Maybe Text) +-- | Thrown if the user cancels a 'Cancellable' 'withProgress'/'withIndefiniteProgress'/ session+--+-- @since 0.11.0.0+data ProgressCancelledException = ProgressCancelledException+  deriving Show+instance E.Exception ProgressCancelledException++-- | Whether or not the user should be able to cancel a 'withProgress'/'withIndefiniteProgress'+-- session+--+-- @since 0.11.0.0+data ProgressCancellable = Cancellable | NotCancellable+ -- | Returned to the server on startup, providing ways to interact with the client. data LspFuncs c =   LspFuncs@@ -139,19 +161,24 @@     , getNextReqId                 :: !(IO J.LspId)     , rootPath                     :: !(Maybe FilePath)     , getWorkspaceFolders          :: !(IO (Maybe [J.WorkspaceFolder]))-    , withProgress                 :: !(forall m a. MonadIO m => Text -> ((Progress -> m ()) -> m a) -> m a)+    , withProgress                 :: !(forall a . Text -> ProgressCancellable+                                        -> ((Progress -> IO ()) -> IO a) -> IO a)       -- ^ Wrapper for reporting progress to the client during a long running       -- task.-      -- 'withProgress' @title f@ starts a new progress reporting session, and-      -- finishes it once f is completed.+      -- 'withProgress' @title cancellable f@ starts a new progress reporting+      -- session, and finishes it once f is completed.       -- f is provided with an update function that allows it to report on       -- the progress during the session.-      -- +      -- If @cancellable@ is 'Cancellable', @f@ will be thrown a+      -- 'ProgressCancelledException' if the user cancels the action in+      -- progress.+      --       -- @since 0.10.0.0-    , withIndefiniteProgress       :: !(forall m a. MonadIO m => Text -> m a -> m a)-    -- ^ Same as 'withProgress' but for processes that do not report the-    -- precentage complete-    -- +    , withIndefiniteProgress       :: !(forall a . Text -> ProgressCancellable+                                        -> IO a -> IO a)+    -- ^ Same as 'withProgress', but for processes that do not report the+    -- precentage complete.+    --     -- @since 0.10.0.0     } @@ -306,7 +333,8 @@ handlerMap _ h J.TextDocumentDocumentLink        = hh nop ReqDocumentLink $ documentLinkHandler h handlerMap _ h J.DocumentLinkResolve             = hh nop ReqDocumentLinkResolve $ documentLinkResolveHandler h handlerMap _ h J.TextDocumentRename              = hh nop ReqRename $ renameHandler h-handlerMap _ h J.TextDocumentFoldingRanges       = hh nop ReqFoldingRange $ foldingRangeHandler h+handlerMap _ h J.TextDocumentFoldingRange        = hh nop ReqFoldingRange $ foldingRangeHandler h+handlerMap _ _ J.WindowProgressCancel            = helper progressCancelHandler handlerMap _ _ (J.Misc x)   = helper f   where f ::  TVar (LanguageContextData c) -> J.Value -> IO ()         f tvarDat n = do@@ -428,8 +456,12 @@ -- defaultLanguageContextData :: Handlers -> Options -> LspFuncs c -> TVar Int -> SendFunc -> Maybe FilePath -> LanguageContextData c defaultLanguageContextData h o lf tv sf cf =-  LanguageContextData _INITIAL_RESPONSE_SEQUENCE h o sf mempty mempty Nothing tv lf cf mempty 0+  LanguageContextData _INITIAL_RESPONSE_SEQUENCE h o sf mempty mempty mempty+                      Nothing tv lf cf mempty defaultProgressData +defaultProgressData :: ProgressData+defaultProgressData = ProgressData 0 Map.empty+ -- ---------------------------------------------------------------------  handleMessage :: (Show c) => InitializeCallback c@@ -597,56 +629,62 @@         let (C.ClientCapabilities _ _ wc _) = params ^. J.capabilities         (C.WindowClientCapabilities mProgress) <- wc         mProgress-      ++      storeProgress :: Text -> Async a -> IO ()+      storeProgress n a = atomically $ do+        pd <- resProgressData <$> readTVar tvarCtx+        let pc = progressCancel pd+            pc' = Map.insert n (cancelWith a ProgressCancelledException) pc+        modifyTVar tvarCtx (\ctx -> ctx { resProgressData = pd { progressCancel = pc' }})+       -- Get a new id for the progress session and make a new one-      getNewProgressId :: MonadIO m => m Text+      getNewProgressId :: IO Text       getNewProgressId = fmap (T.pack . show) $ liftIO $ atomically $ do-        x <- resNextProgressId <$> readTVar tvarCtx-        modifyTVar tvarCtx (\ctx -> ctx { resNextProgressId = x + 1})+        pd <- resProgressData <$> readTVar tvarCtx+        let x = progressNextId pd+        modifyTVar tvarCtx (\ctx -> ctx { resProgressData = pd { progressNextId = x + 1 }})         return x-      -      withProgress' :: (forall m. MonadIO m => Text -> ((Progress -> m ()) -> m a) -> m a)-      withProgress' title f++      withProgressBase :: Bool -> (Text -> ProgressCancellable+                    -> ((Progress -> IO ()) -> IO a) -> IO a)+      withProgressBase indefinite title cancellable f         | clientSupportsProgress = do           sf <- liftIO $ resSendResponse <$> readTVarIO tvarCtx            progId <- getNewProgressId +          let initialPercentage+                | indefinite = Nothing+                | otherwise = Just 0+              cancellable' = case cancellable of+                              Cancellable -> True+                              NotCancellable -> False+           -- Send initial notification           liftIO $ sf $ NotProgressStart $ fmServerProgressStartNotification $-            J.ProgressStartParams progId title (Just False) Nothing (Just 0)+            J.ProgressStartParams progId title (Just cancellable')+              Nothing initialPercentage -          res <- f (updater progId sf)+          aid <- async $ f (updater progId sf)+          storeProgress progId aid+          res <- wait aid            -- Send done notification           liftIO $ sf $ NotProgressDone $ fmServerProgressDoneNotification $             J.ProgressDoneParams progId-          +           return res         | otherwise = f (const $ return ())-          where updater progId sf (Progress percentage msg) = liftIO $+          where updater progId sf (Progress percentage msg) =                   sf $ NotProgressReport $ fmServerProgressReportNotification $                     J.ProgressReportParams progId msg percentage-        -      withIndefiniteProgress' :: (forall m. MonadIO m => Text -> m a -> m a)-      withIndefiniteProgress' title f-        | clientSupportsProgress = do-          sf <- liftIO $ resSendResponse <$> readTVarIO tvarCtx -          progId <- getNewProgressId--          -- Send initial notification-          liftIO $ sf $ NotProgressStart $ fmServerProgressStartNotification $-            J.ProgressStartParams progId title (Just False) Nothing Nothing--          res <- f+      withProgress' :: Text -> ProgressCancellable -> ((Progress -> IO ()) -> IO a) -> IO a+      withProgress' = withProgressBase False -          -- Send done notification-          liftIO $ sf $ NotProgressDone $ fmServerProgressDoneNotification $-            J.ProgressDoneParams progId-          -          return res-        | otherwise = f+      withIndefiniteProgress' :: Text -> ProgressCancellable -> IO a -> IO a+      withIndefiniteProgress' title cancellable f =+        withProgressBase True title cancellable (const f)      -- Launch the given process once the project root directory has been set     let lspFuncs = LspFuncs (getCapabilities params)@@ -727,6 +765,14 @@           res  = J.ResponseMessage "2.0" (J.responseId origId) (Just $ J.InitializeResponseCapabilities capa) Nothing          sendResponse tvarCtx $ RspInitialize res++progressCancelHandler :: TVar (LanguageContextData c) -> J.ProgressCancelNotification -> IO ()+progressCancelHandler tvarCtx (J.NotificationMessage _ _ (J.ProgressCancelParams tid)) = do+  mact <- Map.lookup tid . progressCancel . resProgressData <$> readTVarIO tvarCtx+  case mact of+    Nothing -> return ()+    Just cancelAction -> cancelAction+  -- | --
src/Language/Haskell/LSP/Messages.hs view
@@ -60,6 +60,7 @@                        | NotDidSaveTextDocument          DidSaveTextDocumentNotification                        | NotDidChangeWatchedFiles        DidChangeWatchedFilesNotification                        | NotDidChangeWorkspaceFolders    DidChangeWorkspaceFoldersNotification+                       | NotProgressCancel               ProgressCancelNotification                        -- Unknown (The client sends something we don't understand)                        | UnknownFromClientMessage        Value   deriving (Eq,Read,Show,Generic,ToJSON,FromJSON)@@ -106,7 +107,6 @@                        | NotProgressStart            ProgressStartNotification                        | NotProgressReport           ProgressReportNotification                        | NotProgressDone             ProgressDoneNotification-                       | NotProgressCancel           ProgressCancelNotification                        | NotTelemetry                TelemetryNotification                        -- A cancel request notification is duplex!                        | NotCancelRequestFromServer  CancelNotificationServer