@@ -26,6 +26,7 @@ import Control.Monad.STM
26
26
import Control.Monad.Reader
27
27
import qualified Data.Aeson as J
28
28
import Data.Aeson ( (.=) , (.:) , (.:?) , (.!=) )
29
+ import qualified Data.Bimap as BM
29
30
import qualified Data.ByteString.Lazy as BL
30
31
import Data.Char (isUpper , isAlphaNum )
31
32
import Data.Default
@@ -38,6 +39,7 @@ import qualified Data.Set as S
38
39
import qualified Data.SortedList as SL
39
40
import qualified Data.Text as T
40
41
import Data.Text.Encoding
42
+ import Data.UUID
41
43
import qualified Data.Vector as V
42
44
import qualified GhcModCore as GM
43
45
import qualified GhcMod.Monad.Types as GM
@@ -47,6 +49,7 @@ import Haskell.Ide.Engine.MonadTypes
47
49
import Haskell.Ide.Engine.Dispatcher
48
50
import Haskell.Ide.Engine.PluginUtils
49
51
import Haskell.Ide.Engine.Types
52
+ import Haskell.Ide.Engine.Compat
50
53
import qualified Haskell.Ide.Engine.Plugin.HaRe as HaRe
51
54
import qualified Haskell.Ide.Engine.Plugin.GhcMod as GhcMod
52
55
import qualified Haskell.Ide.Engine.Plugin.ApplyRefact as ApplyRefact
@@ -64,6 +67,7 @@ import qualified Language.Haskell.LSP.Types as J
64
67
import qualified Language.Haskell.LSP.Utility as U
65
68
import System.Exit
66
69
import qualified System.Log.Logger as L
70
+ import System.Random
67
71
import qualified Yi.Rope as Yi
68
72
69
73
import Name
95
99
-> IO Int
96
100
run dispatcherProc cin _origDir captureFp = flip E. catches handlers $ do
97
101
102
+ -- TODO: Figure out how to test with random seeds
103
+ commandUUIDs <- getCommandUUIDs
104
+
98
105
rin <- atomically newTChan :: IO (TChan ReactorInput )
106
+
99
107
let dp lf = do
100
108
cancelTVar <- atomically $ newTVar S. empty
101
109
wipTVar <- atomically $ newTVar S. empty
@@ -105,7 +113,7 @@ run dispatcherProc cin _origDir captureFp = flip E.catches handlers $ do
105
113
, wipReqsTVar = wipTVar
106
114
, docVersionTVar = versionTVar
107
115
}
108
- let reactorFunc = flip runReaderT lf $ reactor dispatcherEnv cin rin
116
+ let reactorFunc = flip runReaderT lf $ reactor dispatcherEnv cin rin commandUUIDs
109
117
110
118
let errorHandler :: ErrorHandler
111
119
errorHandler lid code e =
@@ -120,12 +128,17 @@ run dispatcherProc cin _origDir captureFp = flip E.catches handlers $ do
120
128
return Nothing
121
129
122
130
flip E. finally finalProc $ do
123
- CTRL. run (getConfig, dp) (hieHandlers rin) hieOptions captureFp
131
+ CTRL. run (getConfig, dp) (hieHandlers rin) ( hieOptions ( BM. elems commandUUIDs)) captureFp
124
132
where
125
133
handlers = [E. Handler ioExcept, E. Handler someExcept]
126
134
finalProc = L. removeAllHandlers
127
135
ioExcept (e :: E. IOException ) = print e >> return 1
128
136
someExcept (e :: E. SomeException ) = print e >> return 1
137
+ getCommandUUIDs = do
138
+ uuid <- toText . fst . random . mkStdGen <$> getProcessID
139
+ let commands = [" hare:demote" , " applyrefact:applyOne" ]
140
+ uuids = map (T. append uuid . T. append " :" ) commands
141
+ return $ BM. fromList (zip commands uuids)
129
142
130
143
-- ---------------------------------------------------------------------
131
144
@@ -135,7 +148,6 @@ type ReactorInput
135
148
136
149
-- ---------------------------------------------------------------------
137
150
138
-
139
151
-- ---------------------------------------------------------------------
140
152
141
153
-- | Callback from haskell-lsp core to convert the generic message to the
@@ -333,8 +345,8 @@ sendErrorLog msg = reactorSend' (`Core.sendErrorLogS` msg)
333
345
-- | The single point that all events flow through, allowing management of state
334
346
-- to stitch replies and requests together from the two asynchronous sides: lsp
335
347
-- server and hie dispatcher
336
- reactor :: forall void . DispatcherEnv -> TChan (PluginRequest R ) -> TChan ReactorInput -> R void
337
- reactor (DispatcherEnv cancelReqTVar wipTVar versionTVar) cin inp = do
348
+ reactor :: forall void . DispatcherEnv -> TChan (PluginRequest R ) -> TChan ReactorInput -> BM. Bimap T. Text T. Text -> R void
349
+ reactor (DispatcherEnv cancelReqTVar wipTVar versionTVar) cin inp commandUUIDs = do
338
350
let
339
351
makeRequest req@ (GReq _ _ Nothing (Just lid) _ _) = liftIO $ atomically $ do
340
352
modifyTVar wipTVar (S. insert lid)
@@ -387,7 +399,7 @@ reactor (DispatcherEnv cancelReqTVar wipTVar versionTVar) cin inp = do
387
399
let
388
400
options = J. object [" documentSelector" .= J. object [ " language" .= J. String " haskell" ]]
389
401
registrationsList =
390
- [ J. Registration " hare:demote" J. WorkspaceExecuteCommand (Just options)
402
+ [ J. Registration (commandUUIDs BM. ! " hare:demote" ) J. WorkspaceExecuteCommand (Just options)
391
403
]
392
404
let registrations = J. RegistrationParams (J. List registrationsList)
393
405
@@ -573,7 +585,7 @@ reactor (DispatcherEnv cancelReqTVar wipTVar versionTVar) cin inp = do
573
585
title :: T. Text
574
586
title = " Apply hint:" <> head (T. lines m)
575
587
-- NOTE: the cmd needs to be registered via the InitializeResponse message. See hieOptions above
576
- cmd = " applyrefact:applyOne"
588
+ cmd = commandUUIDs BM. ! " applyrefact:applyOne"
577
589
-- need 'file', 'start_pos' and hint title (to distinguish between alternative suggestions at the same location)
578
590
args = J. Array $ V. singleton $ J. toJSON $ ApplyRefact. AOP doc start code
579
591
cmdparams = Just args
@@ -589,9 +601,12 @@ reactor (DispatcherEnv cancelReqTVar wipTVar versionTVar) cin inp = do
589
601
ReqExecuteCommand req -> do
590
602
liftIO $ U. logs $ " reactor:got ExecuteCommandRequest:" ++ show req
591
603
let params = req ^. J. params
592
- command = params ^. J. command
604
+ command' = params ^. J. command
605
+ -- if this is a UUID then use the mapping for it
606
+ command = fromMaybe command' (BM. lookupR command' commandUUIDs)
593
607
margs = params ^. J. arguments
594
608
609
+ liftIO $ U. logs $ " ExecuteCommand mapped command " ++ show command' ++ " to " ++ show command
595
610
596
611
-- liftIO $ U.logs $ "reactor:ExecuteCommandRequest:margs=" ++ show margs
597
612
let cmdparams = case margs of
@@ -804,7 +819,6 @@ requestDiagnostics tn cin file ver = do
804
819
sendEmpty = publishDiagnostics maxToSend file Nothing (Map. fromList [(Just " ghcmod" ,SL. toSortedList [] )])
805
820
maxToSend = maybe 50 maxNumberOfProblems mc
806
821
807
- -- mc <- asks Core.config
808
822
let sendHlint = maybe True hlintOn mc
809
823
when sendHlint $ do
810
824
-- get hlint diagnostics
@@ -840,8 +854,8 @@ syncOptions = J.TextDocumentSyncOptions
840
854
, J. _save = Just $ J. SaveOptions $ Just False
841
855
}
842
856
843
- hieOptions :: Core. Options
844
- hieOptions =
857
+ hieOptions :: [ T. Text ] -> Core. Options
858
+ hieOptions commandUUIDs =
845
859
def { Core. textDocumentSync = Just syncOptions
846
860
, Core. completionProvider = Just (J. CompletionOptions (Just True ) (Just [" ." ]))
847
861
-- As of 2018-05-24, vscode needs the commands to be registered
@@ -850,7 +864,7 @@ hieOptions =
850
864
--
851
865
-- Hopefully the end May 2018 vscode release will stabilise
852
866
-- this, it is a major rework of the machinery anyway.
853
- , Core. executeCommandProvider = Just (J. ExecuteCommandOptions (J. List [ " applyrefact:applyOne " , " hare:demote " ] ))
867
+ , Core. executeCommandProvider = Just (J. ExecuteCommandOptions (J. List commandUUIDs ))
854
868
}
855
869
856
870
0 commit comments