From fb93528b35992aef3ebe0a8b497cdd70aee21a12 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 27 Jul 2020 13:19:07 +0100 Subject: [PATCH] Fix formatting requests sending misversioned didChange notifications Inside updateState, if a WorkspaceEdit with just the changes field was set then it would send back didChange notifications where all the document versions started from 0. This fixes it to actually take the current version inside the VFS before sending it back --- lsp-test.cabal | 2 +- src/Language/Haskell/LSP/Test.hs | 1 + src/Language/Haskell/LSP/Test/Session.hs | 22 +++++++++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lsp-test.cabal b/lsp-test.cabal index ecc0534..25154d0 100644 --- a/lsp-test.cabal +++ b/lsp-test.cabal @@ -1,5 +1,5 @@ name: lsp-test -version: 0.11.0.2 +version: 0.11.0.3 synopsis: Functional test framework for LSP servers. description: A test framework for writing tests against diff --git a/src/Language/Haskell/LSP/Test.hs b/src/Language/Haskell/LSP/Test.hs index 200dbb8..dbfc801 100644 --- a/src/Language/Haskell/LSP/Test.hs +++ b/src/Language/Haskell/LSP/Test.hs @@ -664,6 +664,7 @@ formatRange doc opts range = do applyTextEdits :: TextDocumentIdentifier -> List TextEdit -> Session () applyTextEdits doc edits = let wEdit = WorkspaceEdit (Just (HashMap.singleton (doc ^. uri) edits)) Nothing + -- Send a dummy message to updateState so it can do bookkeeping req = RequestMessage "" (IdInt 0) WorkspaceApplyEdit (ApplyWorkspaceEditParams wEdit) in updateState (ReqApplyWorkspaceEdit req) diff --git a/src/Language/Haskell/LSP/Test/Session.hs b/src/Language/Haskell/LSP/Test/Session.hs index 2a0eb08..4b1793f 100644 --- a/src/Language/Haskell/LSP/Test/Session.hs +++ b/src/Language/Haskell/LSP/Test/Session.hs @@ -308,15 +308,18 @@ updateState (NotPublishDiagnostics n) = do updateState (ReqApplyWorkspaceEdit r) = do + -- First, prefer the versioned documentChanges field allChangeParams <- case r ^. params . edit . documentChanges of Just (List cs) -> do mapM_ (checkIfNeedsOpened . (^. textDocument . uri)) cs return $ map getParams cs + -- Then fall back to the changes field Nothing -> case r ^. params . edit . changes of Just cs -> do mapM_ checkIfNeedsOpened (HashMap.keys cs) - return $ concatMap (uncurry getChangeParams) (HashMap.toList cs) - Nothing -> error "No changes!" + concat <$> mapM (uncurry getChangeParams) (HashMap.toList cs) + Nothing -> + error "WorkspaceEdit contains neither documentChanges nor changes!" modifyM $ \s -> do newVFS <- liftIO $ changeFromServerVFS (vfs s) r @@ -360,11 +363,20 @@ updateState (ReqApplyWorkspaceEdit r) = do let changeEvents = map (\e -> TextDocumentContentChangeEvent (Just (e ^. range)) Nothing (e ^. newText)) edits in DidChangeTextDocumentParams docId (List changeEvents) - textDocumentVersions uri = map (VersionedTextDocumentIdentifier uri . Just) [0..] + -- For a uri returns an infinite list of versions [n,n+1,n+2,...] + -- where n is the current version + textDocumentVersions uri = do + m <- vfsMap . vfs <$> get + let curVer = fromMaybe 0 $ + _lsp_version <$> m Map.!? (toNormalizedUri uri) + pure $ map (VersionedTextDocumentIdentifier uri . Just) [curVer..] - textDocumentEdits uri edits = map (\(v, e) -> TextDocumentEdit v (List [e])) $ zip (textDocumentVersions uri) edits + textDocumentEdits uri edits = do + vers <- textDocumentVersions uri + pure $ map (\(v, e) -> TextDocumentEdit v (List [e])) $ zip vers edits - getChangeParams uri (List edits) = map getParams (textDocumentEdits uri (reverse edits)) + getChangeParams uri (List edits) = + map <$> pure getParams <*> textDocumentEdits uri (reverse edits) mergeParams :: [DidChangeTextDocumentParams] -> DidChangeTextDocumentParams mergeParams params = let events = concat (toList (map (toList . (^. contentChanges)) params)) -- 2.30.2