Skip to content

Commit 1778cab

Browse files
authored
Parse config from initializeOptions and pass in the old value of config to onConfigurationChange (#285)
* Parse config from initializeOptions and pass in the old value of config to onConfigurationChange
1 parent 508461b commit 1778cab

File tree

6 files changed

+38
-22
lines changed

6 files changed

+38
-22
lines changed

example/Reactor.hs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ main = do
5959
-- ---------------------------------------------------------------------
6060

6161
data Config = Config { fooTheBar :: Bool, wibbleFactor :: Int }
62-
deriving (Generic, J.ToJSON, J.FromJSON)
62+
deriving (Generic, J.ToJSON, J.FromJSON, Show)
6363

6464
run :: IO Int
6565
run = flip E.catches handlers $ do
@@ -68,12 +68,11 @@ run = flip E.catches handlers $ do
6868

6969
let
7070
serverDefinition = ServerDefinition
71-
{ onConfigurationChange = \v -> case J.fromJSON v of
72-
J.Error e -> pure $ Left (T.pack e)
73-
J.Success cfg -> do
74-
sendNotification J.SWindowShowMessage $
75-
J.ShowMessageParams J.MtInfo $ "Wibble factor set to " <> T.pack (show (wibbleFactor cfg))
76-
pure $ Right cfg
71+
{ defaultConfig = Config {fooTheBar = False, wibbleFactor = 0 }
72+
, onConfigurationChange = \_old v -> do
73+
case J.fromJSON v of
74+
J.Error e -> Left (T.pack e)
75+
J.Success cfg -> Right cfg
7776
, doInitialize = \env _ -> forkIO (reactor rin) >> pure (Right env)
7877
, staticHandlers = lspHandlers rin
7978
, interpretHandler = \env -> Iso (runLspT env) liftIO
@@ -196,6 +195,12 @@ handle = mconcat
196195
liftIO $ debugM "reactor.handle" $ "Processing DidOpenTextDocument for: " ++ show fileName
197196
sendDiagnostics (J.toNormalizedUri doc) (Just 0)
198197

198+
, notificationHandler J.SWorkspaceDidChangeConfiguration $ \msg -> do
199+
cfg <- getConfig
200+
liftIO $ debugM "configuration changed: " (show (msg,cfg))
201+
sendNotification J.SWindowShowMessage $
202+
J.ShowMessageParams J.MtInfo $ "Wibble factor set to " <> T.pack (show (wibbleFactor cfg))
203+
199204
, notificationHandler J.STextDocumentDidChange $ \msg -> do
200205
let doc = msg ^. J.params
201206
. J.textDocument

example/Simple.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ handlers = mconcat
3636

3737
main :: IO Int
3838
main = runServer $ ServerDefinition
39-
{ onConfigurationChange = const $ pure $ Right ()
39+
{ onConfigurationChange = const $ const $ Right ()
40+
, defaultConfig = ()
4041
, doInitialize = \env _req -> pure $ Right env
4142
, staticHandlers = handlers
4243
, interpretHandler = \env -> Iso (runLspT env) liftIO

func-test/FuncTest.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ main = hspec $ do
2929
killVar <- newEmptyMVar
3030

3131
let definition = ServerDefinition
32-
{ onConfigurationChange = const $ pure $ Right ()
32+
{ onConfigurationChange = const $ const $ Right ()
33+
, defaultConfig = ()
3334
, doInitialize = \env _req -> pure $ Right env
3435
, staticHandlers = handlers killVar
3536
, interpretHandler = \env -> Iso (runLspT env) liftIO
@@ -79,7 +80,8 @@ main = hspec $ do
7980
wf2 = WorkspaceFolder "/foo/baz" "My other workspace"
8081

8182
definition = ServerDefinition
82-
{ onConfigurationChange = const $ pure $ Right ()
83+
{ onConfigurationChange = const $ const $ Right ()
84+
, defaultConfig = ()
8385
, doInitialize = \env _req -> pure $ Right env
8486
, staticHandlers = handlers
8587
, interpretHandler = \env -> Iso (runLspT env) liftIO

lsp-types/src/Language/LSP/Types/Lens.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
{-# LANGUAGE UndecidableInstances #-}
88
{-# LANGUAGE RankNTypes #-}
99
{-# LANGUAGE FlexibleContexts #-}
10+
{-# LANGUAGE DataKinds #-}
11+
{-# LANGUAGE TypeInType #-}
1012

1113
module Language.LSP.Types.Lens where
1214

src/Language/LSP/Server/Core.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ instance MonadLsp c m => MonadLsp c (IdentityT m) where
9797
data LanguageContextEnv config =
9898
LanguageContextEnv
9999
{ resHandlers :: !(Handlers IO)
100-
, resParseConfig :: !(J.Value -> IO (Either T.Text config))
100+
, resParseConfig :: !(config -> J.Value -> (Either T.Text config))
101101
, resSendMessage :: !(FromServerMessage -> IO ())
102102
-- We keep the state in a TVar to be thread safe
103103
, resState :: !(TVar (LanguageContextState config))
@@ -168,7 +168,7 @@ data LanguageContextState config =
168168
LanguageContextState
169169
{ resVFS :: !VFSData
170170
, resDiagnostics :: !DiagnosticStore
171-
, resConfig :: !(Maybe config)
171+
, resConfig :: !config
172172
, resWorkspaceFolders :: ![WorkspaceFolder]
173173
, resProgressData :: !ProgressData
174174
, resPendingResponses :: !ResponseMap
@@ -274,12 +274,15 @@ data ProgressCancellable = Cancellable | NotCancellable
274274
-- specific configuration data the language server needs to use.
275275
data ServerDefinition config = forall m a.
276276
ServerDefinition
277-
{ onConfigurationChange :: J.Value -> m (Either T.Text config)
278-
-- ^ @onConfigurationChange newConfig@ is called whenever the
277+
{ defaultConfig :: config
278+
-- ^ The default value we initialize the config variable to.
279+
, onConfigurationChange :: config -> J.Value -> Either T.Text config
280+
-- ^ @onConfigurationChange oldConfig newConfig@ is called whenever the
279281
-- clients sends a message with a changed client configuration. This
280282
-- callback should return either the parsed configuration data or an error
281283
-- indicating what went wrong. The parsed configuration object will be
282284
-- stored internally and can be accessed via 'config'.
285+
-- It is also called on the `initializationOptions` field of the InitializeParams
283286
, doInitialize :: LanguageContextEnv config -> Message Initialize -> IO (Either ResponseError a)
284287
-- ^ Called *after* receiving the @initialize@ request and *before*
285288
-- returning the response. This callback will be invoked to offer the
@@ -427,7 +430,7 @@ freshLspId = do
427430

428431
-- | The current configuration from the client as set via the @initialize@ and
429432
-- @workspace/didChangeConfiguration@ requests.
430-
getConfig :: MonadLsp config m => m (Maybe config)
433+
getConfig :: MonadLsp config m => m config
431434
getConfig = getsState resConfig
432435

433436
getClientCapabilities :: MonadLsp config m => m J.ClientCapabilities

src/Language/LSP/Server/Processing.hs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,15 @@ initializeRequestHandler ServerDefinition{..} vfs sendFunc req = do
9696
Just (List xs) -> xs
9797
Nothing -> []
9898

99+
initialConfig = case onConfigurationChange defaultConfig <$> (req ^. LSP.params . LSP.initializationOptions) of
100+
Just (Right newConfig) -> newConfig
101+
_ -> defaultConfig
102+
99103
tvarCtx <- liftIO $ newTVarIO $
100104
LanguageContextState
101105
(VFSData vfs mempty)
102106
mempty
103-
Nothing
107+
initialConfig
104108
initialWfs
105109
defaultProgressData
106110
emptyIxMap
@@ -109,7 +113,7 @@ initializeRequestHandler ServerDefinition{..} vfs sendFunc req = do
109113
0
110114

111115
-- Call the 'duringInitialization' callback to let the server kick stuff up
112-
let env = LanguageContextEnv handlers (forward interpreter . onConfigurationChange) sendFunc tvarCtx (params ^. LSP.capabilities) rootDir
116+
let env = LanguageContextEnv handlers onConfigurationChange sendFunc tvarCtx (params ^. LSP.capabilities) rootDir
113117
handlers = transmuteHandlers interpreter staticHandlers
114118
interpreter = interpretHandler initializationResult
115119
initializationResult <- ExceptT $ doInitialize env req
@@ -357,19 +361,18 @@ shutdownRequestHandler :: Handler IO Shutdown
357361
shutdownRequestHandler = \_req k -> do
358362
k $ Right Empty
359363

360-
361-
362364
handleConfigChange :: Message WorkspaceDidChangeConfiguration -> LspM config ()
363365
handleConfigChange req = do
364366
parseConfig <- LspT $ asks resParseConfig
365-
res <- liftIO $ parseConfig (req ^. LSP.params . LSP.settings)
367+
res <- stateState $ \ctx -> case parseConfig (resConfig ctx) (req ^. LSP.params . LSP.settings) of
368+
Left err -> (Left err, ctx)
369+
Right newConfig -> (Right (), ctx { resConfig = newConfig })
366370
case res of
367371
Left err -> do
368372
let msg = T.pack $ unwords
369373
["haskell-lsp:configuration parse error.", show req, show err]
370374
sendErrorLog msg
371-
Right newConfig ->
372-
modifyState $ \ctx -> ctx { resConfig = Just newConfig }
375+
Right () -> pure ()
373376

374377
vfsFunc :: (VFS -> b -> (VFS, [String])) -> b -> LspM config ()
375378
vfsFunc modifyVfs req = do

0 commit comments

Comments
 (0)