@@ -19,10 +19,8 @@ import Colog.Core (
19
19
WithSeverity (.. ),
20
20
(<&) ,
21
21
)
22
- import Control.Concurrent.Async
23
22
import Control.Concurrent.Extra as C
24
23
import Control.Concurrent.STM
25
- import Control.Exception qualified as E
26
24
import Control.Lens (at , (^.) , (^?) , _Just )
27
25
import Control.Monad
28
26
import Control.Monad.Catch (
@@ -38,7 +36,6 @@ import Control.Monad.Trans.Identity
38
36
import Control.Monad.Trans.Reader
39
37
import Data.Aeson qualified as J
40
38
import Data.Default
41
- import Data.Foldable
42
39
import Data.Functor.Product
43
40
import Data.HashMap.Strict qualified as HM
44
41
import Data.IxMap
@@ -65,8 +62,6 @@ import Language.LSP.Protocol.Utils.SMethodMap qualified as SMethodMap
65
62
import Language.LSP.VFS hiding (end )
66
63
import Prettyprinter
67
64
import System.Random hiding (next )
68
- import UnliftIO qualified as U
69
- import UnliftIO.Exception qualified as UE
70
65
71
66
-- ---------------------------------------------------------------------
72
67
{-# ANN module ("HLint: ignore Eta reduce" :: String) #-}
@@ -323,29 +318,6 @@ instance Default Options where
323
318
defaultOptions :: Options
324
319
defaultOptions = def
325
320
326
- {- | A package indicating the percentage of progress complete and a
327
- an optional message to go with it during a 'withProgress'
328
-
329
- @since 0.10.0.0
330
- -}
331
- data ProgressAmount = ProgressAmount (Maybe UInt ) (Maybe Text )
332
-
333
- {- | Thrown if the user cancels a 'Cancellable' 'withProgress'/'withIndefiniteProgress'/ session
334
-
335
- @since 0.11.0.0
336
- -}
337
- data ProgressCancelledException = ProgressCancelledException
338
- deriving (Show )
339
-
340
- instance E. Exception ProgressCancelledException
341
-
342
- {- | Whether or not the user should be able to cancel a 'withProgress'/'withIndefiniteProgress'
343
- session
344
-
345
- @since 0.11.0.0
346
- -}
347
- data ProgressCancellable = Cancellable | NotCancellable
348
-
349
321
-- See Note [LSP configuration] for discussion of the configuration-related fields
350
322
351
323
{- | Contains all the callbacks to use for initialized the language server.
@@ -645,194 +617,6 @@ unregisterCapability (RegistrationToken m (RegistrationId uuid)) = do
645
617
params = L. UnregistrationParams [toUntypedUnregistration unregistration]
646
618
void $ sendRequest SMethod_ClientUnregisterCapability params $ \ _res -> pure ()
647
619
648
- --------------------------------------------------------------------------------
649
- -- PROGRESS
650
- --------------------------------------------------------------------------------
651
-
652
- -- Get a new id for the progress session and make a new one
653
- getNewProgressId :: MonadLsp config m => m ProgressToken
654
- getNewProgressId = do
655
- stateState (progressNextId . resProgressData) $ \ cur ->
656
- let ! next = cur + 1
657
- in (L. ProgressToken $ L. InL cur, next)
658
- {-# INLINE getNewProgressId #-}
659
-
660
- withProgressBase ::
661
- forall c m a .
662
- MonadLsp c m =>
663
- Bool ->
664
- Text ->
665
- Maybe ProgressToken ->
666
- ProgressCancellable ->
667
- ((ProgressAmount -> m () ) -> m a ) ->
668
- m a
669
- withProgressBase indefinite title clientToken cancellable f = do
670
- let initialProgress = ProgressAmount (if indefinite then Nothing else Just 0 ) Nothing
671
- LanguageContextEnv {resProgressStartDelay = startDelay, resProgressUpdateDelay = updateDelay} <- getLspEnv
672
-
673
- tokenVar <- liftIO newEmptyTMVarIO
674
- reportVar <- liftIO $ newTMVarIO initialProgress
675
- endBarrier <- liftIO newEmptyMVar
676
-
677
- let
678
- updater :: ProgressAmount -> m ()
679
- updater pa = liftIO $ atomically $ do
680
- -- I don't know of a way to do this with a normal MVar!
681
- -- That is: put something into it regardless of whether it is full or empty
682
- _ <- tryTakeTMVar reportVar
683
- putTMVar reportVar pa
684
-
685
- progressEnded :: IO ()
686
- progressEnded = readMVar endBarrier
687
-
688
- endProgress :: IO ()
689
- endProgress = void $ tryPutMVar endBarrier ()
690
-
691
- -- Once we have a 'ProgressToken', store it in the variable and also register the cancellation
692
- -- handler.
693
- registerToken :: ProgressToken -> m ()
694
- registerToken t = do
695
- handlers <- getProgressCancellationHandlers
696
- liftIO $ atomically $ do
697
- putTMVar tokenVar t
698
- modifyTVar handlers (Map. insert t endProgress)
699
-
700
- -- Deregister our 'ProgressToken', specifically its cancellation handler. It is important
701
- -- to do this reliably or else we will leak handlers.
702
- unregisterToken :: m ()
703
- unregisterToken = do
704
- handlers <- getProgressCancellationHandlers
705
- liftIO $ atomically $ do
706
- mt <- tryReadTMVar tokenVar
707
- for_ mt $ \ t -> modifyTVar handlers (Map. delete t)
708
-
709
- -- Find and register our 'ProgressToken', asking the client for it if necessary.
710
- -- Note that this computation may terminate before we get the token, we need to wait
711
- -- for the token var to be filled if we want to use it.
712
- createToken :: m ()
713
- createToken = do
714
- -- See Note [Delayed progress reporting]
715
- -- This delays the creation of the token as well as the 'begin' message. Creating
716
- -- the token shouldn't result in any visible action on the client side since
717
- -- the title/initial percentage aren't given until the 'begin' mesage. However,
718
- -- it's neater not to create tokens that we won't use, and clients may find it
719
- -- easier to clean them up if they receive begin/end reports for them.
720
- liftIO $ threadDelay startDelay
721
- case clientToken of
722
- -- See Note [Client- versus server-initiated progress]
723
- -- Client-initiated progress
724
- Just t -> registerToken t
725
- -- Try server-initiated progress
726
- Nothing -> do
727
- t <- getNewProgressId
728
- clientCaps <- getClientCapabilities
729
-
730
- -- If we don't have a progress token from the client and
731
- -- the client doesn't support server-initiated progress then
732
- -- there's nothing to do: we can't report progress.
733
- when (clientSupportsServerInitiatedProgress clientCaps)
734
- $ void
735
- $
736
- -- Server-initiated progress
737
- -- See Note [Client- versus server-initiated progress]
738
- sendRequest
739
- SMethod_WindowWorkDoneProgressCreate
740
- (WorkDoneProgressCreateParams t)
741
- $ \ case
742
- -- Successfully registered the token, we can now use it.
743
- -- So we go ahead and start. We do this as soon as we get the
744
- -- token back so the client gets feedback ASAP
745
- Right _ -> registerToken t
746
- -- The client sent us an error, we can't use the token.
747
- Left _err -> pure ()
748
-
749
- -- Actually send the progress reports.
750
- sendReports :: m ()
751
- sendReports = do
752
- t <- liftIO $ atomically $ readTMVar tokenVar
753
- begin t
754
- -- Once we are sending updates, if we get interrupted we should send
755
- -- the end notification
756
- update t `UE.finally` end t
757
- where
758
- cancellable' = case cancellable of
759
- Cancellable -> Just True
760
- NotCancellable -> Just False
761
- begin t = do
762
- (ProgressAmount pct msg) <- liftIO $ atomically $ takeTMVar reportVar
763
- sendProgressReport t $ WorkDoneProgressBegin L. AString title cancellable' msg pct
764
- update t =
765
- forever $ do
766
- -- See Note [Delayed progress reporting]
767
- liftIO $ threadDelay updateDelay
768
- (ProgressAmount pct msg) <- liftIO $ atomically $ takeTMVar reportVar
769
- sendProgressReport t $ WorkDoneProgressReport L. AString Nothing msg pct
770
- end t = sendProgressReport t (WorkDoneProgressEnd L. AString Nothing )
771
-
772
- -- Create the token and then start sending reports; all of which races with the check for the
773
- -- progress having ended. In all cases, make sure to unregister the token at the end.
774
- progressThreads :: m ()
775
- progressThreads =
776
- ((createToken >> sendReports) `UE.finally` unregisterToken) `U.race_` liftIO progressEnded
777
-
778
- withRunInIO $ \ runInBase -> do
779
- withAsync (runInBase $ f updater) $ \ mainAct ->
780
- -- If the progress gets cancelled then we need to get cancelled too
781
- withAsync (runInBase progressThreads) $ \ pthreads -> do
782
- r <- waitEither mainAct pthreads
783
- -- TODO: is this weird? I can't see how else to gracefully use the ending barrier
784
- -- as a guard to cancel the other async
785
- case r of
786
- Left a -> pure a
787
- Right _ -> cancelWith mainAct ProgressCancelledException >> wait mainAct
788
- where
789
- sendProgressReport :: (J. ToJSON r ) => ProgressToken -> r -> m ()
790
- sendProgressReport token report = sendNotification SMethod_Progress $ ProgressParams token $ J. toJSON report
791
-
792
- getProgressCancellationHandlers :: m (TVar (Map. Map ProgressToken (IO () )))
793
- getProgressCancellationHandlers = getStateVar (progressCancel . resProgressData)
794
-
795
- clientSupportsServerInitiatedProgress :: L. ClientCapabilities -> Bool
796
- clientSupportsServerInitiatedProgress caps = fromMaybe False $ caps ^? L. window . _Just . L. workDoneProgress . _Just
797
- {-# INLINE clientSupportsServerInitiatedProgress #-}
798
-
799
- {- |
800
- Wrapper for reporting progress to the client during a long running task.
801
- -}
802
- withProgress ::
803
- MonadLsp c m =>
804
- -- | The title of the progress operation
805
- Text ->
806
- -- | The progress token provided by the client in the method params, if any
807
- Maybe ProgressToken ->
808
- -- | Whether or not this operation is cancellable. If true, the user will be
809
- -- shown a button to allow cancellation. Note that requests can still be cancelled
810
- -- even if this is not set.
811
- ProgressCancellable ->
812
- -- | An update function to pass progress updates to
813
- ((ProgressAmount -> m () ) -> m a ) ->
814
- m a
815
- withProgress title clientToken cancellable f = withProgressBase False title clientToken cancellable f
816
-
817
- {- |
818
- Same as 'withProgress', but for processes that do not report the precentage complete.
819
- -}
820
- withIndefiniteProgress ::
821
- MonadLsp c m =>
822
- -- | The title of the progress operation
823
- Text ->
824
- -- | The progress token provided by the client in the method params, if any
825
- Maybe ProgressToken ->
826
- -- | Whether or not this operation is cancellable. If true, the user will be
827
- -- shown a button to allow cancellation. Note that requests can still be cancelled
828
- -- even if this is not set.
829
- ProgressCancellable ->
830
- -- | An update function to pass progress updates to
831
- ((Text -> m () ) -> m a ) ->
832
- m a
833
- withIndefiniteProgress title clientToken cancellable f =
834
- withProgressBase True title clientToken cancellable (\ update -> f (\ msg -> update (ProgressAmount Nothing (Just msg))))
835
-
836
620
-- ---------------------------------------------------------------------
837
621
838
622
{- | Aggregate all diagnostics pertaining to a particular version of a document,
0 commit comments