From fb8363a6576071ae1d721baf20255e14aae3e658 Mon Sep 17 00:00:00 2001 From: Michael Peyton Jones Date: Sat, 25 May 2024 21:12:42 +0100 Subject: [PATCH] Mappings for capabilities (#581) * Add golden tests for client cap generation * Add mappings for capabilities * Fix commment --- .gitignore | 1 + lsp-test/README.md | 4 +- lsp-test/bench/SimpleBench.hs | 2 +- lsp-test/example/Test.hs | 2 +- lsp-test/func-test/FuncTest.hs | 10 +- lsp-test/src/Language/LSP/Test.hs | 6 +- lsp-test/src/Language/LSP/Test/Replay.hs | 2 +- lsp-test/test/Test.hs | 90 +- lsp-types/.golden/fullCaps/golden | 303 +++++ lsp-types/.golden/oldCaps/golden | 175 +++ lsp-types/ChangeLog.md | 4 + lsp-types/lsp-types.cabal | 2 + .../src/Language/LSP/Protocol/Capabilities.hs | 1127 +++++++++++++---- .../LSP/Protocol/Message/Registration.hs | 5 +- lsp-types/test/CapabilitiesSpec.hs | 16 +- 15 files changed, 1416 insertions(+), 333 deletions(-) create mode 100644 lsp-types/.golden/fullCaps/golden create mode 100644 lsp-types/.golden/oldCaps/golden diff --git a/.gitignore b/.gitignore index bd6d87e91..2994f9306 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ hie .hie hie.yaml .envrc +**/.golden/*/actual diff --git a/lsp-test/README.md b/lsp-test/README.md index e4c42563a..aff7be20e 100644 --- a/lsp-test/README.md +++ b/lsp-test/README.md @@ -8,7 +8,7 @@ and [lsp-types](https://hackage.haskell.org/package/lsp-types) ```haskell import Language.LSP.Test -main = runSession "hie" fullCaps "proj/dir" $ do +main = runSession "hie" fullLatestClientCaps "proj/dir" $ do doc <- openDoc "Foo.hs" "haskell" skipMany anyNotification symbols <- getDocumentSymbols doc @@ -19,7 +19,7 @@ main = runSession "hie" fullCaps "proj/dir" $ do ### Unit tests with HSpec ```haskell describe "diagnostics" $ - it "report errors" $ runSession "hie" fullCaps "test/data" $ do + it "report errors" $ runSession "hie" fullLatestClientCaps "test/data" $ do openDoc "Error.hs" "haskell" [diag] <- waitForDiagnosticsSource "ghcmod" liftIO $ do diff --git a/lsp-test/bench/SimpleBench.hs b/lsp-test/bench/SimpleBench.hs index ffa89bd5d..056d3e906 100644 --- a/lsp-test/bench/SimpleBench.hs +++ b/lsp-test/bench/SimpleBench.hs @@ -56,7 +56,7 @@ main = do i <- newIORef (0 :: Integer) - Test.runSessionWithHandles hinWrite houtRead Test.defaultConfig Test.fullCaps "." $ do + Test.runSessionWithHandles hinWrite houtRead Test.defaultConfig Test.fullLatestClientCaps "." $ do start <- liftIO offsetTime replicateM_ n $ do v <- liftIO $ readIORef i diff --git a/lsp-test/example/Test.hs b/lsp-test/example/Test.hs index 103d9639a..8961e498d 100644 --- a/lsp-test/example/Test.hs +++ b/lsp-test/example/Test.hs @@ -7,7 +7,7 @@ import Language.LSP.Protocol.Types import Language.LSP.Test main :: IO () -main = runSession "lsp-demo-reactor-server" fullCaps "test/data/" $ do +main = runSession "lsp-demo-reactor-server" fullLatestClientCaps "test/data/" $ do doc <- openDoc "Rename.hs" "haskell" -- Use your favourite favourite combinators. diff --git a/lsp-test/func-test/FuncTest.hs b/lsp-test/func-test/FuncTest.hs index f0c6a179b..818b1696b 100644 --- a/lsp-test/func-test/FuncTest.hs +++ b/lsp-test/func-test/FuncTest.hs @@ -83,7 +83,7 @@ spec = do updater $ ProgressAmount (Just 75) (Just "step3") liftIO $ waitBarrier b3 - runSessionWithServer logger definition Test.defaultConfig Test.fullCaps "." $ do + runSessionWithServer logger definition Test.defaultConfig Test.fullLatestClientCaps "." $ do Test.sendRequest (SMethod_CustomMethod (Proxy @"something")) J.Null -- Wait until we have seen a begin messsage. This means that the token setup @@ -144,7 +144,7 @@ spec = do -- Wait around to be cancelled, set the MVar only if we are liftIO $ threadDelay (5 * 1000000) `Control.Exception.catch` (\(e :: ProgressCancelledException) -> modifyMVar_ wasCancelled (\_ -> pure True)) - runSessionWithServer logger definition Test.defaultConfig Test.fullCaps "." $ do + runSessionWithServer logger definition Test.defaultConfig Test.fullLatestClientCaps "." $ do Test.sendRequest (SMethod_CustomMethod (Proxy @"something")) J.Null -- Wait until we have created the progress so the updates will be sent individually @@ -190,7 +190,7 @@ spec = do takeMVar killVar Control.Exception.throwIO AsyncCancelled - runSessionWithServer logger definition Test.defaultConfig Test.fullCaps "." $ do + runSessionWithServer logger definition Test.defaultConfig Test.fullLatestClientCaps "." $ do -- First make sure that we get a $/progress begin notification skipManyTill Test.anyMessage $ do x <- Test.message SMethod_Progress @@ -235,7 +235,7 @@ spec = do updater $ ProgressAmount (Just 75) (Just "step3") liftIO $ waitBarrier b3 - runSessionWithServer logger definition Test.defaultConfig Test.fullCaps "." $ do + runSessionWithServer logger definition Test.defaultConfig Test.fullLatestClientCaps "." $ do Test.sendRequest SMethod_TextDocumentCodeLens (CodeLensParams (Just $ ProgressToken $ InR "hello") Nothing (TextDocumentIdentifier $ Uri ".")) -- First make sure that we get a $/progress begin notification @@ -318,7 +318,7 @@ spec = do ps = DidChangeWorkspaceFoldersParams ev in Test.sendNotification SMethod_WorkspaceDidChangeWorkspaceFolders ps - runSessionWithServer logger definition config Test.fullCaps "." $ do + runSessionWithServer logger definition config Test.fullLatestClientCaps "." $ do changeFolders [wf1] [] changeFolders [wf2] [wf1] diff --git a/lsp-test/src/Language/LSP/Test.hs b/lsp-test/src/Language/LSP/Test.hs index a2e905702..b9b29297b 100644 --- a/lsp-test/src/Language/LSP/Test.hs +++ b/lsp-test/src/Language/LSP/Test.hs @@ -30,7 +30,7 @@ module Language.LSP.Test ( -- ** Config SessionConfig (..), defaultConfig, - C.fullCaps, + C.fullLatestClientCaps, -- ** Exceptions module Language.LSP.Test.Exceptions, @@ -181,7 +181,7 @@ import System.Process (CreateProcess, ProcessHandle) {- | Starts a new session. - > runSession "hie" fullCaps "path/to/root/dir" $ do + > runSession "hie" fullLatestClientCaps "path/to/root/dir" $ do > doc <- openDoc "Desktop/simple.hs" "haskell" > diags <- waitForDiagnostics > let pos = Position 12 5 @@ -243,7 +243,7 @@ runSessionWithConfigCustomProcess modifyCreateProcess config' serverExe caps roo > (houtRead, houtWrite) <- createPipe > > forkIO $ void $ runServerWithHandles hinRead houtWrite serverDefinition - > runSessionWithHandles hinWrite houtRead defaultConfig fullCaps "." $ do + > runSessionWithHandles hinWrite houtRead defaultConfig fullLatestClientCaps "." $ do > -- ... -} runSessionWithHandles :: diff --git a/lsp-test/src/Language/LSP/Test/Replay.hs b/lsp-test/src/Language/LSP/Test/Replay.hs index 3d6b33225..9f231dfba 100644 --- a/lsp-test/src/Language/LSP/Test/Replay.hs +++ b/lsp-test/src/Language/LSP/Test/Replay.hs @@ -67,7 +67,7 @@ replaySession serverExe sessionDir = do runSessionWithHandles serverIn serverOut serverProc (listenServer serverMsgs requestMap reqSema rspSema passSema mainThread) def - fullCaps + fullLatestClientCaps sessionDir (return ()) -- No finalizer cleanup (sendMessages clientMsgs reqSema rspSema) diff --git a/lsp-test/test/Test.hs b/lsp-test/test/Test.hs index d2f8176a1..00b512124 100644 --- a/lsp-test/test/Test.hs +++ b/lsp-test/test/Test.hs @@ -33,20 +33,20 @@ import Test.Hspec main = hspec $ around withDummyServer $ do describe "Session" $ do it "fails a test" $ \(hin, hout) -> - let session = runSessionWithHandles hin hout def fullCaps "." $ do + let session = runSessionWithHandles hin hout def fullLatestClientCaps "." $ do openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" anyRequest in session `shouldThrow` anySessionException - it "initializeResponse" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "initializeResponse" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do rsp <- initializeResponse liftIO $ rsp ^. L.result `shouldSatisfy` isRight it "runSessionWithConfig" $ \(hin, hout) -> - runSessionWithHandles hin hout def fullCaps "." $ return () + runSessionWithHandles hin hout def fullLatestClientCaps "." $ return () describe "withTimeout" $ do it "times out" $ \(hin, hout) -> - let sesh = runSessionWithHandles hin hout def fullCaps "." $ do + let sesh = runSessionWithHandles hin hout def fullLatestClientCaps "." $ do openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- won't receive a request - will timeout -- incoming logging requests shouldn't increase the @@ -57,13 +57,13 @@ main = hspec $ around withDummyServer $ do timeout 6000000 sesh `shouldThrow` anySessionException it "doesn't time out" $ \(hin, hout) -> - let sesh = runSessionWithHandles hin hout def fullCaps "." $ do + let sesh = runSessionWithHandles hin hout def fullLatestClientCaps "." $ do openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" withTimeout 5 $ skipManyTill anyMessage publishDiagnosticsNotification in void $ timeout 6000000 sesh it "further timeout messages are ignored" $ \(hin, hout) -> - runSessionWithHandles hin hout def fullCaps "." $ do + runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- shouldn't timeout withTimeout 3 $ getDocumentSymbols doc @@ -75,7 +75,7 @@ main = hspec $ around withDummyServer $ do it "overrides global message timeout" $ \(hin, hout) -> let sesh = - runSessionWithHandles hin hout (def{messageTimeout = 5}) fullCaps "." $ do + runSessionWithHandles hin hout (def{messageTimeout = 5}) fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- shouldn't time out in here since we are overriding it withTimeout 10 $ liftIO $ threadDelay 7000000 @@ -85,7 +85,7 @@ main = hspec $ around withDummyServer $ do it "unoverrides global message timeout" $ \(hin, hout) -> let sesh = - runSessionWithHandles hin hout (def{messageTimeout = 5}) fullCaps "." $ do + runSessionWithHandles hin hout (def{messageTimeout = 5}) fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- shouldn't time out in here since we are overriding it withTimeout 10 $ liftIO $ threadDelay 7000000 @@ -98,13 +98,13 @@ main = hspec $ around withDummyServer $ do describe "SessionException" $ do it "throw on time out" $ \(hin, hout) -> - let sesh = runSessionWithHandles hin hout (def{messageTimeout = 10}) fullCaps "." $ do + let sesh = runSessionWithHandles hin hout (def{messageTimeout = 10}) fullLatestClientCaps "." $ do _ <- message SMethod_WorkspaceApplyEdit return () in sesh `shouldThrow` anySessionException it "don't throw when no time out" $ \(hin, hout) -> - runSessionWithHandles hin hout (def{messageTimeout = 5}) fullCaps "." $ do + runSessionWithHandles hin hout (def{messageTimeout = 5}) fullLatestClientCaps "." $ do liftIO $ threadDelay $ 6 * 1000000 _ <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" return () @@ -113,7 +113,7 @@ main = hspec $ around withDummyServer $ do it "throws when there's an unexpected message" $ \(hin, hout) -> let selector (UnexpectedMessage "Publish diagnostics notification" (FromServerMess SMethod_WindowLogMessage _)) = True selector _ = False - in runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullCaps "." publishDiagnosticsNotification `shouldThrow` selector + in runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullLatestClientCaps "." publishDiagnosticsNotification `shouldThrow` selector it "provides the correct types that were expected and received" $ \(hin, hout) -> let selector (UnexpectedMessage "Response for: SMethod_TextDocumentRename" (FromServerRsp SMethod_TextDocumentDocumentSymbol _)) = True selector _ = False @@ -122,12 +122,12 @@ main = hspec $ around withDummyServer $ do sendRequest SMethod_TextDocumentDocumentSymbol (DocumentSymbolParams Nothing Nothing doc) skipMany anyNotification response SMethod_TextDocumentRename -- the wrong type - in runSessionWithHandles hin hout def fullCaps "." sesh + in runSessionWithHandles hin hout def fullLatestClientCaps "." sesh `shouldThrow` selector describe "config" $ do it "updates config correctly" $ \(hin, hout) -> - runSessionWithHandles hin hout (def{ignoreConfigurationRequests = False}) fullCaps "." $ do + runSessionWithHandles hin hout (def{ignoreConfigurationRequests = False}) fullLatestClientCaps "." $ do configurationRequest -- initialized configuration request let requestConfig = do resp <- request (SMethod_CustomMethod (Proxy @"getConfig")) J.Null @@ -150,7 +150,7 @@ main = hspec $ around withDummyServer $ do describe "text document VFS" $ do it "sends back didChange notifications (documentChanges)" $ \(hin, hout) -> - runSessionWithHandles hin hout def fullCaps "." $ do + runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/refactor/Main.hs" "haskell" VersionedTextDocumentIdentifier _ beforeVersion <- getVersionedDoc doc @@ -180,7 +180,7 @@ main = hspec $ around withDummyServer $ do liftIO $ reportedVersion `shouldNotBe` beforeVersion it "sends back didChange notifications" $ \(hin, hout) -> - runSessionWithHandles hin hout def fullCaps "." $ do + runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/refactor/Main.hs" "haskell" let args = toJSON (doc ^. L.uri) @@ -198,7 +198,7 @@ main = hspec $ around withDummyServer $ do describe "getDocumentEdit" $ it "automatically consumes applyedit requests" $ \(hin, hout) -> - runSessionWithHandles hin hout def fullCaps "." $ do + runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/refactor/Main.hs" "haskell" let args = toJSON (doc ^. L.uri) @@ -208,7 +208,7 @@ main = hspec $ around withDummyServer $ do liftIO $ contents `shouldBe` "howdy:: IO Int\nmain = return (42)\n" describe "getCodeActions" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/refactor/Main.hs" "haskell" waitForDiagnostics [InR action] <- getCodeActions doc (Range (Position 0 0) (Position 0 2)) @@ -217,7 +217,7 @@ main = hspec $ around withDummyServer $ do liftIO $ actions `shouldSatisfy` null describe "getAllCodeActions" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/refactor/Main.hs" "haskell" _ <- waitForDiagnostics actions <- getAllCodeActions doc @@ -227,7 +227,7 @@ main = hspec $ around withDummyServer $ do action ^. L.command . _Just . L.command `shouldBe` "deleteThis" describe "getDocumentSymbols" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" Right (mainSymbol : _) <- getDocumentSymbols doc @@ -238,13 +238,13 @@ main = hspec $ around withDummyServer $ do mainSymbol ^. L.range `shouldBe` mkRange 0 0 3 6 describe "applyEdit" $ do - it "increments the version" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "increments the version" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" VersionedTextDocumentIdentifier _ oldVersion <- getVersionedDoc doc let edit = TextEdit (Range (Position 1 1) (Position 1 3)) "foo" VersionedTextDocumentIdentifier _ newVersion <- applyEdit doc edit liftIO $ newVersion `shouldBe` oldVersion + 1 - it "changes the document contents" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "changes the document contents" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" let edit = TextEdit (Range (Position 0 0) (Position 0 2)) "foo" applyEdit doc edit @@ -252,7 +252,7 @@ main = hspec $ around withDummyServer $ do liftIO $ contents `shouldSatisfy` T.isPrefixOf "foodule" describe "getCompletions" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" comps <- getCompletions doc (Position 5 5) @@ -260,7 +260,7 @@ main = hspec $ around withDummyServer $ do liftIO $ item ^. L.label `shouldBe` "foo" -- describe "getReferences" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- let pos = Position 40 3 -- interactWithUser -- uri = doc ^. LSP.uri @@ -272,21 +272,21 @@ main = hspec $ around withDummyServer $ do -- ] -- describe "getDefinitions" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- let pos = Position 49 25 -- addItem -- defs <- getDefinitions doc pos -- liftIO $ defs `shouldBe` [Location (doc ^. uri) (mkRange 28 0 28 7)] -- describe "getTypeDefinitions" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- let pos = Position 20 23 -- Quit value -- defs <- getTypeDefinitions doc pos -- liftIO $ defs `shouldBe` [Location (doc ^. uri) (mkRange 10 0 14 19)] -- Type definition describe "waitForDiagnosticsSource" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do openDoc "test/data/Error.hs" "haskell" [diag] <- waitForDiagnosticsSource "dummy-server" liftIO $ do @@ -296,33 +296,33 @@ main = hspec $ around withDummyServer $ do -- describe "rename" $ do -- it "works" $ \(hin, hout) -> pendingWith "HaRe not in hie-bios yet" -- it "works on javascript" $ - -- runSessionWithHandles hin hout "javascript-typescript-stdio" fullCaps "test/data/javascriptPass" $ do + -- runSessionWithHandles hin hout "javascript-typescript-stdio" fullLatestClientCaps "test/data/javascriptPass" $ do -- doc <- openDoc "test.js" "javascript" -- rename doc (Position 2 11) "bar" -- documentContents doc >>= liftIO . (`shouldContain` "function bar()") . T.unpack describe "getHover" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" hover <- getHover doc (Position 45 9) liftIO $ hover `shouldSatisfy` isJust -- describe "getHighlights" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" -- skipManyTill loggingNotification $ count 2 noDiagnostics -- highlights <- getHighlights doc (Position 27 4) -- addItem -- liftIO $ length highlights `shouldBe` 4 -- describe "formatDoc" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/Format.hs" "haskell" -- oldContents <- documentContents doc -- formatDoc doc (FormattingOptions 4 True) -- documentContents doc >>= liftIO . (`shouldNotBe` oldContents) -- describe "formatRange" $ - -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + -- it "works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do -- doc <- openDoc "test/data/Format.hs" "haskell" -- oldContents <- documentContents doc -- formatRange doc (FormattingOptions 4 True) (Range (Position 1 10) (Position 2 10)) @@ -331,7 +331,7 @@ main = hspec $ around withDummyServer $ do describe "closeDoc" $ it "works" $ \(hin, hout) -> let sesh = - runSessionWithHandles hin hout def fullCaps "." $ do + runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/Format.hs" "haskell" closeDoc doc -- need to evaluate to throw @@ -339,21 +339,21 @@ main = hspec $ around withDummyServer $ do in sesh `shouldThrow` anyException describe "satisfy" $ - it "works" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullCaps "." $ do + it "works" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullLatestClientCaps "." $ do openDoc "test/data/Format.hs" "haskell" let pred (FromServerMess SMethod_WindowLogMessage _) = True pred _ = False void $ satisfy pred describe "satisfyMaybe" $ do - it "returns matched data on match" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullCaps "." $ do + it "returns matched data on match" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullLatestClientCaps "." $ do -- Wait for window/logMessage "initialized" from the server. let pred (FromServerMess SMethod_WindowLogMessage _) = Just "match" :: Maybe String pred _ = Nothing :: Maybe String result <- satisfyMaybe pred liftIO $ result `shouldBe` "match" - it "doesn't return if no match" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullCaps "." $ do + it "doesn't return if no match" $ \(hin, hout) -> runSessionWithHandles hin hout (def{ignoreLogNotifications = False}) fullLatestClientCaps "." $ do let pred (FromServerMess SMethod_TextDocumentPublishDiagnostics _) = Just "matched" :: Maybe String pred _ = Nothing :: Maybe String -- We expect a window/logMessage from the server, but @@ -363,13 +363,13 @@ main = hspec $ around withDummyServer $ do describe "ignoreLogNotifications" $ it "works" $ \(hin, hout) -> - runSessionWithHandles hin hout (def{ignoreLogNotifications = True}) fullCaps "." $ do + runSessionWithHandles hin hout (def{ignoreLogNotifications = True}) fullLatestClientCaps "." $ do openDoc "test/data/Format.hs" "haskell" void publishDiagnosticsNotification describe "dynamic capabilities" $ do let config = def{ignoreLogNotifications = False} - it "keeps track" $ \(hin, hout) -> runSessionWithHandles hin hout config fullCaps "." $ do + it "keeps track" $ \(hin, hout) -> runSessionWithHandles hin hout config fullLatestClientCaps "." $ do loggingNotification -- initialized log message createDoc ".register" "haskell" "" setIgnoringRegistrationRequests False @@ -402,7 +402,7 @@ main = hspec $ around withDummyServer $ do void $ sendRequest SMethod_TextDocumentHover $ HoverParams doc (Position 0 0) Nothing void $ anyResponse - it "handles absolute patterns" $ \(hin, hout) -> runSessionWithHandles hin hout config fullCaps "" $ do + it "handles absolute patterns" $ \(hin, hout) -> runSessionWithHandles hin hout config fullLatestClientCaps "" $ do loggingNotification -- initialized log message curDir <- liftIO $ getCurrentDirectory @@ -436,31 +436,31 @@ main = hspec $ around withDummyServer $ do (Range (Position 1 2) (Position 3 4)) (Range (Position 1 2) (Position 3 4)) Nothing - it "prepare works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "prepare works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do rsp <- prepareCallHierarchy (params workPos) liftIO $ head rsp ^. L.range `shouldBe` Range (Position 2 3) (Position 4 5) - it "prepare not works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "prepare not works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do rsp <- prepareCallHierarchy (params notWorkPos) liftIO $ rsp `shouldBe` [] - it "incoming calls" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "incoming calls" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do [CallHierarchyIncomingCall _ fromRanges] <- incomingCalls (CallHierarchyIncomingCallsParams Nothing Nothing item) liftIO $ head fromRanges `shouldBe` Range (Position 2 3) (Position 4 5) - it "outgoing calls" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "outgoing calls" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do [CallHierarchyOutgoingCall _ fromRanges] <- outgoingCalls (CallHierarchyOutgoingCallsParams Nothing Nothing item) liftIO $ head fromRanges `shouldBe` Range (Position 4 5) (Position 2 3) describe "semantic tokens" $ do - it "full works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "full works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do let doc = TextDocumentIdentifier (Uri "") InL toks <- getSemanticTokens doc liftIO $ toks ^. L.data_ `shouldBe` [0, 1, 2, 1, 0] describe "inlay hints" $ do - it "get works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "get works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" inlayHints <- getInlayHints doc (Range (Position 1 2) (Position 3 4)) liftIO $ head inlayHints ^. L.label `shouldBe` InL ":: Text" - it "resolve tooltip works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do + it "resolve tooltip works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullLatestClientCaps "." $ do doc <- openDoc "test/data/renamePass/Desktop/simple.hs" "haskell" inlayHints <- getAndResolveInlayHints doc (Range (Position 1 2) (Position 3 4)) liftIO $ head inlayHints ^. L.tooltip `shouldBe` Just (InL $ "start at " <> T.pack (show (Position 1 2))) diff --git a/lsp-types/.golden/fullCaps/golden b/lsp-types/.golden/fullCaps/golden new file mode 100644 index 000000000..957a63a22 --- /dev/null +++ b/lsp-types/.golden/fullCaps/golden @@ -0,0 +1,303 @@ +{ + "general": { + "markdown": { "allowedTags": [ ], "parser": "" }, + "positionEncodings": [ "utf-16" ], + "regularExpressions": { "engine": "" }, + "staleRequestSupport": { "cancel": true, "retryOnContentModified": [ ] } + }, + "notebookDocument": { + "synchronization": { + "dynamicRegistration": true, + "executionSummarySupport": true + } + }, + "textDocument": { + "callHierarchy": { "dynamicRegistration": true }, + "codeAction": { + "codeActionLiteralSupport": { + "codeActionKind": { + "valueSet": [ + "", + "quickfix", + "refactor", + "refactor.extract", + "refactor.inline", + "refactor.rewrite", + "source", + "source.organizeImports", + "source.fixAll", + "notebook" + ] + } + }, + "dataSupport": true, + "disabledSupport": true, + "dynamicRegistration": true, + "honorsChangeAnnotations": true, + "isPreferredSupport": true, + "resolveSupport": { "properties": [ ] } + }, + "codeLens": { "dynamicRegistration": true }, + "colorProvider": { "dynamicRegistration": true }, + "completion": { + "completionItem": { + "commitCharactersSupport": true, + "deprecatedSupport": true, + "documentationFormat": [ "plaintext", "markdown" ], + "insertReplaceSupport": true, + "insertTextModeSupport": { "valueSet": [ ] }, + "labelDetailsSupport": true, + "preselectSupport": true, + "resolveSupport": { "properties": [ "documentation", "details" ] }, + "snippetSupport": true, + "tagSupport": { "valueSet": [ ] } + }, + "completionItemKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + "completionList": { "itemDefaults": [ ] }, + "contextSupport": true, + "dynamicRegistration": true, + "insertTextMode": 1 + }, + "declaration": { "dynamicRegistration": true, "linkSupport": true }, + "definition": { "dynamicRegistration": true, "linkSupport": true }, + "diagnostic": { + "dynamicRegistration": true, + "relatedDocumentSupport": true + }, + "documentHighlight": { "dynamicRegistration": true }, + "documentLink": { "dynamicRegistration": true, "tooltipSupport": true }, + "documentSymbol": { + "dynamicRegistration": true, + "hierarchicalDocumentSymbolSupport": true, + "labelSupport": true, + "symbolKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ] + }, + "tagSupport": { "valueSet": [ 1 ] } + }, + "foldingRange": { + "dynamicRegistration": true, + "foldingRange": { "collapsedText": true }, + "foldingRangeKind": { "valueSet": [ ] } + }, + "formatting": { "dynamicRegistration": true }, + "hover": { + "contentFormat": [ "plaintext", "markdown" ], + "dynamicRegistration": true + }, + "implementation": { "dynamicRegistration": true, "linkSupport": true }, + "inlayHint": { + "dynamicRegistration": true, + "resolveSupport": { "properties": [ ] } + }, + "inlineValue": { "dynamicRegistration": true }, + "linkedEditingRange": { "dynamicRegistration": true }, + "moniker": { "dynamicRegistration": true }, + "onTypeFormatting": { "dynamicRegistration": true }, + "publishDiagnostics": { + "codeDescriptionSupport": true, + "dataSupport": true, + "relatedInformation": true, + "tagSupport": { "valueSet": [ 1, 2 ] }, + "versionSupport": true + }, + "rangeFormatting": { "dynamicRegistration": true }, + "references": { "dynamicRegistration": true }, + "rename": { + "dynamicRegistration": true, + "honorsChangeAnnotations": true, + "prepareSupport": true, + "prepareSupportDefaultBehavior": 1 + }, + "selectionRange": { "dynamicRegistration": true }, + "semanticTokens": { + "augmentsSyntaxTokens": true, + "dynamicRegistration": true, + "formats": [ "relative" ], + "multilineTokenSupport": true, + "overlappingTokenSupport": true, + "requests": { "full": { "delta": true }, "range": true }, + "serverCancelSupport": true, + "tokenModifiers": [ + "declaration", + "definition", + "readonly", + "static", + "deprecated", + "abstract", + "async", + "modification", + "documentation", + "defaultLibrary" + ], + "tokenTypes": [ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator" + ] + }, + "signatureHelp": { + "contextSupport": true, + "dynamicRegistration": true, + "signatureInformation": { + "activeParameterSupport": true, + "documentationFormat": [ "plaintext", "markdown" ], + "parameterInformation": { "labelOffsetSupport": true } + } + }, + "synchronization": { + "didSave": true, + "dynamicRegistration": true, + "willSave": true, + "willSaveWaitUntil": true + }, + "typeDefinition": { "dynamicRegistration": true, "linkSupport": true }, + "typeHierarchy": { "dynamicRegistration": true } + }, + "window": { + "showDocument": { "support": true }, + "showMessage": { }, + "workDoneProgress": true + }, + "workspace": { + "applyEdit": true, + "codeLens": { "refreshSupport": true }, + "configuration": true, + "diagnostics": { "refreshSupport": true }, + "didChangeConfiguration": { "dynamicRegistration": true }, + "didChangeWatchedFiles": { + "dynamicRegistration": true, + "relativePatternSupport": true + }, + "executeCommand": { "dynamicRegistration": true }, + "fileOperations": { + "didCreate": true, + "didDelete": true, + "didRename": true, + "dynamicRegistration": true, + "willCreate": true, + "willDelete": true, + "willRename": true + }, + "inlayHint": { "refreshSupport": true }, + "inlineValue": { "refreshSupport": true }, + "semanticTokens": { "refreshSupport": true }, + "symbol": { + "dynamicRegistration": true, + "resolveSupport": { "properties": [ ] }, + "symbolKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ] + }, + "tagSupport": { "valueSet": [ 1 ] } + }, + "workspaceEdit": { + "changeAnnotationSupport": { "groupsOnLabel": true }, + "documentChanges": true, + "normalizesLineEndings": true, + "resourceOperations": [ "create", "delete", "rename" ] + }, + "workspaceFolders": true + } +} \ No newline at end of file diff --git a/lsp-types/.golden/oldCaps/golden b/lsp-types/.golden/oldCaps/golden new file mode 100644 index 000000000..255e2f6d7 --- /dev/null +++ b/lsp-types/.golden/oldCaps/golden @@ -0,0 +1,175 @@ +{ + "textDocument": { + "codeAction": { + "codeActionLiteralSupport": { + "codeActionKind": { + "valueSet": [ + "", + "quickfix", + "refactor", + "refactor.extract", + "refactor.inline", + "refactor.rewrite", + "source", + "source.organizeImports", + "source.fixAll", + "notebook" + ] + } + }, + "dynamicRegistration": true + }, + "codeLens": { "dynamicRegistration": true }, + "colorProvider": { "dynamicRegistration": true }, + "completion": { + "completionItem": { + "commitCharactersSupport": true, + "deprecatedSupport": true, + "documentationFormat": [ "plaintext", "markdown" ], + "preselectSupport": true, + "snippetSupport": true + }, + "completionItemKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + "contextSupport": true, + "dynamicRegistration": true + }, + "definition": { "dynamicRegistration": true }, + "documentHighlight": { "dynamicRegistration": true }, + "documentLink": { "dynamicRegistration": true }, + "documentSymbol": { + "dynamicRegistration": true, + "symbolKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ] + } + }, + "formatting": { "dynamicRegistration": true }, + "hover": { + "contentFormat": [ "plaintext", "markdown" ], + "dynamicRegistration": true + }, + "implementation": { "dynamicRegistration": true }, + "onTypeFormatting": { "dynamicRegistration": true }, + "publishDiagnostics": { "relatedInformation": true }, + "rangeFormatting": { "dynamicRegistration": true }, + "references": { "dynamicRegistration": true }, + "rename": { "dynamicRegistration": true }, + "selectionRange": { "dynamicRegistration": true }, + "signatureHelp": { + "dynamicRegistration": true, + "signatureInformation": { + "activeParameterSupport": true, + "documentationFormat": [ "plaintext", "markdown" ], + "parameterInformation": { "labelOffsetSupport": true } + } + }, + "synchronization": { + "didSave": true, + "dynamicRegistration": true, + "willSave": true, + "willSaveWaitUntil": true + }, + "typeDefinition": { "dynamicRegistration": true } + }, + "window": { }, + "workspace": { + "applyEdit": true, + "codeLens": { "refreshSupport": true }, + "configuration": true, + "didChangeConfiguration": { "dynamicRegistration": true }, + "didChangeWatchedFiles": { + "dynamicRegistration": true, + "relativePatternSupport": true + }, + "executeCommand": { "dynamicRegistration": true }, + "symbol": { + "dynamicRegistration": true, + "symbolKind": { + "valueSet": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ] + } + }, + "workspaceEdit": { "documentChanges": true }, + "workspaceFolders": true + } +} \ No newline at end of file diff --git a/lsp-types/ChangeLog.md b/lsp-types/ChangeLog.md index 81ac5e48f..1190de8e9 100644 --- a/lsp-types/ChangeLog.md +++ b/lsp-types/ChangeLog.md @@ -1,5 +1,9 @@ # Revision history for lsp-types +## Unreleased + +- Add support for identifying client and server capabilities associated with a method. + ## 2.2.0.0 -- 2024-04-29 - Update the metamodel. This results in a number of breaking changes to the generated code, mostly replacing diff --git a/lsp-types/lsp-types.cabal b/lsp-types/lsp-types.cabal index a96d5b651..49af5cfb9 100644 --- a/lsp-types/lsp-types.cabal +++ b/lsp-types/lsp-types.cabal @@ -658,10 +658,12 @@ test-suite lsp-types-test , base , filepath , hspec + , hspec-golden , lens , lsp-types , lsp-types-quickcheck , network-uri + , prettyprinter , QuickCheck , quickcheck-instances , text diff --git a/lsp-types/src/Language/LSP/Protocol/Capabilities.hs b/lsp-types/src/Language/LSP/Protocol/Capabilities.hs index a04a88143..dc696f9f7 100644 --- a/lsp-types/src/Language/LSP/Protocol/Capabilities.hs +++ b/lsp-types/src/Language/LSP/Protocol/Capabilities.hs @@ -1,94 +1,673 @@ {-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Language.LSP.Protocol.Capabilities ( - fullCaps, LSPVersion (..), - capsForVersion, + + -- * Client capabilities + ClientCapability, + clientCapability, + fullLatestClientCaps, + fullClientCapsForVersion, + fullClientCapsForVersionAndMethod, dynamicRegistrationSupported, + + -- * Server capabilities + ServerCapability, + serverCapability, ) where import Control.Lens +import Data.Kind (Type) import Data.Maybe import Data.Set qualified as Set +import Data.Void import Language.LSP.Protocol.Lens qualified as L import Language.LSP.Protocol.Message import Language.LSP.Protocol.Types import Prelude hiding (min) -{- -TODO: this is out-of-date/needs an audit -TODO: can we generate this? process the 'since' annotations in the metamodel? +-- | A specific version of the LSP specification. +data LSPVersion = LSPVersion Int Int + +---- CLIENT CAPABILITIES + +type ClientCapability :: forall f t. Method f t -> Type + +-- See Note [Capability mappings] + +{- | The client capability associated with a given method. + +Where several methods are provided together (e.g. the three `callHierarchy` methods), we associate all of them +with the capaiblity, even if there is one "primary" method. +-} +type family ClientCapability (m :: Method f t) where + ClientCapability Method_TextDocumentDeclaration = DeclarationClientCapabilities + ClientCapability Method_TextDocumentImplementation = ImplementationClientCapabilities + ClientCapability Method_TextDocumentTypeDefinition = TypeDefinitionClientCapabilities + ClientCapability Method_TextDocumentHover = HoverClientCapabilities + ClientCapability Method_TextDocumentSignatureHelp = SignatureHelpClientCapabilities + ClientCapability Method_TextDocumentDefinition = DefinitionClientCapabilities + ClientCapability Method_TextDocumentReferences = ReferenceClientCapabilities + ClientCapability Method_TextDocumentDocumentHighlight = DocumentHighlightClientCapabilities + ClientCapability Method_TextDocumentDocumentSymbol = DocumentSymbolClientCapabilities + ClientCapability Method_TextDocumentFoldingRange = FoldingRangeClientCapabilities + ClientCapability Method_TextDocumentSelectionRange = SelectionRangeClientCapabilities + ClientCapability Method_WorkspaceExecuteCommand = ExecuteCommandClientCapabilities + ClientCapability Method_TextDocumentLinkedEditingRange = LinkedEditingRangeClientCapabilities + ClientCapability Method_TextDocumentMoniker = MonikerClientCapabilities + ClientCapability Method_WorkspaceWorkspaceFolders = Bool + ClientCapability Method_TextDocumentCompletion = CompletionClientCapabilities + ClientCapability Method_CompletionItemResolve = CompletionClientCapabilities + ClientCapability Method_TextDocumentCodeAction = CodeActionClientCapabilities + ClientCapability Method_CodeActionResolve = CodeActionClientCapabilities + ClientCapability Method_TextDocumentCodeLens = CodeLensClientCapabilities + ClientCapability Method_CodeLensResolve = CodeLensClientCapabilities + ClientCapability Method_WorkspaceCodeLensRefresh = CodeLensWorkspaceClientCapabilities + ClientCapability Method_TextDocumentDocumentLink = DocumentLinkClientCapabilities + ClientCapability Method_DocumentLinkResolve = DocumentLinkClientCapabilities + ClientCapability Method_WorkspaceSymbol = WorkspaceSymbolClientCapabilities + ClientCapability Method_WorkspaceSymbolResolve = WorkspaceSymbolClientCapabilities + ClientCapability Method_TextDocumentRename = RenameClientCapabilities + ClientCapability Method_TextDocumentPrepareRename = RenameClientCapabilities + ClientCapability Method_TextDocumentDocumentColor = DocumentColorClientCapabilities + ClientCapability Method_TextDocumentColorPresentation = DocumentColorClientCapabilities + ClientCapability Method_TextDocumentFormatting = DocumentFormattingClientCapabilities + ClientCapability Method_TextDocumentRangeFormatting = DocumentRangeFormattingClientCapabilities + ClientCapability Method_TextDocumentOnTypeFormatting = DocumentOnTypeFormattingClientCapabilities + ClientCapability Method_TextDocumentPrepareCallHierarchy = CallHierarchyClientCapabilities + ClientCapability Method_CallHierarchyIncomingCalls = CallHierarchyClientCapabilities + ClientCapability Method_CallHierarchyOutgoingCalls = CallHierarchyClientCapabilities + ClientCapability Method_TextDocumentSemanticTokensFull = SemanticTokensClientCapabilities + ClientCapability Method_TextDocumentSemanticTokensFullDelta = SemanticTokensClientCapabilities + ClientCapability Method_TextDocumentSemanticTokensRange = SemanticTokensClientCapabilities + ClientCapability Method_WorkspaceSemanticTokensRefresh = SemanticTokensWorkspaceClientCapabilities + ClientCapability Method_TextDocumentPrepareTypeHierarchy = TypeHierarchyClientCapabilities + ClientCapability Method_TypeHierarchySupertypes = TypeHierarchyClientCapabilities + ClientCapability Method_TypeHierarchySubtypes = TypeHierarchyClientCapabilities + ClientCapability Method_TextDocumentInlineValue = InlineValueClientCapabilities + ClientCapability Method_WorkspaceInlineValueRefresh = InlineValueWorkspaceClientCapabilities + ClientCapability Method_TextDocumentInlayHint = InlayHintClientCapabilities + ClientCapability Method_InlayHintResolve = InlayHintClientCapabilities + ClientCapability Method_WorkspaceInlayHintRefresh = InlayHintWorkspaceClientCapabilities + ClientCapability Method_TextDocumentDiagnostic = DiagnosticClientCapabilities + ClientCapability Method_WorkspaceDiagnostic = DiagnosticWorkspaceClientCapabilities + ClientCapability Method_WorkspaceDiagnosticRefresh = DiagnosticWorkspaceClientCapabilities + ClientCapability Method_WorkspaceWillCreateFiles = FileOperationClientCapabilities + ClientCapability Method_WorkspaceWillRenameFiles = FileOperationClientCapabilities + ClientCapability Method_WorkspaceWillDeleteFiles = FileOperationClientCapabilities + ClientCapability Method_WorkspaceDidCreateFiles = FileOperationClientCapabilities + ClientCapability Method_WorkspaceDidRenameFiles = FileOperationClientCapabilities + ClientCapability Method_WorkspaceDidDeleteFiles = FileOperationClientCapabilities + ClientCapability Method_TextDocumentDidOpen = TextDocumentSyncClientCapabilities + ClientCapability Method_TextDocumentDidChange = TextDocumentSyncClientCapabilities + ClientCapability Method_TextDocumentDidClose = TextDocumentSyncClientCapabilities + ClientCapability Method_TextDocumentDidSave = TextDocumentSyncClientCapabilities + ClientCapability Method_TextDocumentWillSave = TextDocumentSyncClientCapabilities + ClientCapability Method_TextDocumentWillSaveWaitUntil = TextDocumentSyncClientCapabilities + ClientCapability Method_NotebookDocumentDidOpen = NotebookDocumentSyncClientCapabilities + ClientCapability Method_NotebookDocumentDidChange = NotebookDocumentSyncClientCapabilities + ClientCapability Method_NotebookDocumentDidSave = NotebookDocumentSyncClientCapabilities + ClientCapability Method_NotebookDocumentDidClose = NotebookDocumentSyncClientCapabilities + ClientCapability Method_WorkspaceDidChangeConfiguration = DidChangeConfigurationClientCapabilities + ClientCapability Method_WorkspaceDidChangeWatchedFiles = DidChangeWatchedFilesClientCapabilities + ClientCapability Method_WorkspaceDidChangeWorkspaceFolders = Void + ClientCapability Method_TextDocumentPublishDiagnostics = PublishDiagnosticsClientCapabilities + ClientCapability Method_WorkspaceConfiguration = Bool + ClientCapability Method_WorkspaceApplyEdit = Bool + ClientCapability Method_WindowWorkDoneProgressCreate = Bool + ClientCapability Method_WindowWorkDoneProgressCancel = Bool + ClientCapability Method_WindowShowMessage = ShowMessageRequestClientCapabilities + ClientCapability Method_WindowShowMessageRequest = ShowMessageRequestClientCapabilities + ClientCapability Method_WindowShowDocument = ShowDocumentClientCapabilities + -- All required by default, no capabilities + ClientCapability Method_Progress = Void + ClientCapability Method_WindowLogMessage = Void + ClientCapability Method_ClientRegisterCapability = Void + ClientCapability Method_ClientUnregisterCapability = Void + ClientCapability Method_Initialize = Void + ClientCapability Method_Initialized = Void + ClientCapability Method_Shutdown = Void + ClientCapability Method_Exit = Void + ClientCapability Method_TelemetryEvent = Void + ClientCapability Method_SetTrace = Void + ClientCapability Method_LogTrace = Void + ClientCapability Method_CancelRequest = Void + ClientCapability (Method_CustomMethod s) = Void + +-- See Note [Capability mappings] + +-- | A lens which focusses on the (possibly absent) client capability associated with a method. +clientCapability :: forall m. SMethod m -> Lens' ClientCapabilities (Maybe (ClientCapability m)) +clientCapability = \case + SMethod_TextDocumentDeclaration -> td . L.declaration + SMethod_TextDocumentImplementation -> td . L.implementation + SMethod_TextDocumentTypeDefinition -> td . L.typeDefinition + SMethod_TextDocumentHover -> td . L.hover + SMethod_TextDocumentSignatureHelp -> td . L.signatureHelp + SMethod_TextDocumentDefinition -> td . L.definition + SMethod_TextDocumentReferences -> td . L.references + SMethod_TextDocumentDocumentHighlight -> td . L.documentHighlight + SMethod_TextDocumentDocumentSymbol -> td . L.documentSymbol + SMethod_TextDocumentFoldingRange -> td . L.foldingRange + SMethod_TextDocumentSelectionRange -> td . L.selectionRange + SMethod_WorkspaceExecuteCommand -> ws . L.executeCommand + SMethod_TextDocumentMoniker -> td . L.moniker + SMethod_TextDocumentCompletion -> td . L.completion + SMethod_CompletionItemResolve -> td . L.completion + SMethod_TextDocumentCodeAction -> td . L.codeAction + SMethod_CodeActionResolve -> td . L.codeAction + SMethod_TextDocumentCodeLens -> td . L.codeLens + SMethod_CodeLensResolve -> td . L.codeLens + SMethod_WorkspaceCodeLensRefresh -> ws . L.codeLens + SMethod_TextDocumentDocumentLink -> td . L.documentLink + SMethod_DocumentLinkResolve -> td . L.documentLink + SMethod_TextDocumentDocumentColor -> td . L.colorProvider + SMethod_TextDocumentColorPresentation -> td . L.colorProvider + SMethod_WorkspaceSymbol -> ws . L.symbol + SMethod_WorkspaceSymbolResolve -> ws . L.symbol + SMethod_TextDocumentFormatting -> td . L.formatting + SMethod_TextDocumentRangeFormatting -> td . L.rangeFormatting + SMethod_TextDocumentOnTypeFormatting -> td . L.onTypeFormatting + SMethod_TextDocumentRename -> td . L.rename + SMethod_TextDocumentPrepareRename -> td . L.rename + SMethod_TextDocumentPrepareCallHierarchy -> td . L.callHierarchy + SMethod_CallHierarchyIncomingCalls -> td . L.callHierarchy + SMethod_CallHierarchyOutgoingCalls -> td . L.callHierarchy + SMethod_TextDocumentLinkedEditingRange -> td . L.linkedEditingRange + SMethod_TextDocumentSemanticTokensFull -> td . L.semanticTokens + SMethod_TextDocumentSemanticTokensFullDelta -> td . L.semanticTokens + SMethod_TextDocumentSemanticTokensRange -> td . L.semanticTokens + SMethod_WorkspaceSemanticTokensRefresh -> ws . L.semanticTokens + SMethod_TextDocumentPrepareTypeHierarchy -> td . L.typeHierarchy + SMethod_TypeHierarchySubtypes -> td . L.typeHierarchy + SMethod_TypeHierarchySupertypes -> td . L.typeHierarchy + SMethod_TextDocumentInlineValue -> td . L.inlineValue + SMethod_WorkspaceInlineValueRefresh -> ws . L.inlineValue + SMethod_TextDocumentInlayHint -> td . L.inlayHint + SMethod_InlayHintResolve -> td . L.inlayHint + SMethod_WorkspaceInlayHintRefresh -> ws . L.inlayHint + SMethod_TextDocumentDiagnostic -> td . L.diagnostic + SMethod_WorkspaceDiagnostic -> ws . L.diagnostics + SMethod_WorkspaceDiagnosticRefresh -> ws . L.diagnostics + SMethod_WorkspaceWorkspaceFolders -> ws . L.workspaceFolders + SMethod_WorkspaceWillCreateFiles -> ws . L.fileOperations + SMethod_WorkspaceWillRenameFiles -> ws . L.fileOperations + SMethod_WorkspaceWillDeleteFiles -> ws . L.fileOperations + SMethod_WorkspaceDidCreateFiles -> ws . L.fileOperations + SMethod_WorkspaceDidRenameFiles -> ws . L.fileOperations + SMethod_WorkspaceDidDeleteFiles -> ws . L.fileOperations + SMethod_TextDocumentDidOpen -> td . L.synchronization + SMethod_TextDocumentDidChange -> td . L.synchronization + SMethod_TextDocumentDidClose -> td . L.synchronization + SMethod_TextDocumentDidSave -> td . L.synchronization + SMethod_TextDocumentWillSave -> td . L.synchronization + SMethod_TextDocumentWillSaveWaitUntil -> td . L.synchronization + SMethod_NotebookDocumentDidOpen -> nbs + SMethod_NotebookDocumentDidChange -> nbs + SMethod_NotebookDocumentDidSave -> nbs + SMethod_NotebookDocumentDidClose -> nbs + SMethod_WorkspaceDidChangeConfiguration -> ws . L.didChangeConfiguration + SMethod_WorkspaceDidChangeWatchedFiles -> ws . L.didChangeWatchedFiles + SMethod_TextDocumentPublishDiagnostics -> td . L.publishDiagnostics + SMethod_WorkspaceConfiguration -> ws . L.configuration + SMethod_WindowWorkDoneProgressCreate -> wd . L.workDoneProgress + SMethod_WindowWorkDoneProgressCancel -> wd . L.workDoneProgress + SMethod_WorkspaceApplyEdit -> ws . L.applyEdit + SMethod_WindowShowDocument -> wd . L.showDocument + SMethod_WindowShowMessageRequest -> wd . L.showMessage + SMethod_WindowShowMessage -> wd . L.showMessage + SMethod_WorkspaceDidChangeWorkspaceFolders -> noCap + SMethod_Progress -> noCap + SMethod_WindowLogMessage -> noCap + SMethod_ClientRegisterCapability -> noCap + SMethod_ClientUnregisterCapability -> noCap + SMethod_Initialize -> noCap + SMethod_Initialized -> noCap + SMethod_Shutdown -> noCap + SMethod_Exit -> noCap + SMethod_TelemetryEvent -> noCap + SMethod_SetTrace -> noCap + SMethod_LogTrace -> noCap + SMethod_CancelRequest -> noCap + (SMethod_CustomMethod _s) -> noCap + where + ws :: Lens' ClientCapabilities WorkspaceClientCapabilities + ws = L.workspace . non emptyWorkspaceClientCaps + wd :: Lens' ClientCapabilities WindowClientCapabilities + wd = L.window . non emptyWindowClientCaps + td :: Lens' ClientCapabilities TextDocumentClientCapabilities + td = L.textDocument . non emptyTextDocumentClientCaps + -- This is messed up because, unlike literally everything else, `NotebookDocumentClientCapabilities.synchronization` is + -- a mandatory field, so if we don't have it we need to unset the parent `notebookDocument` field. Maybe. + nbs :: Lens' ClientCapabilities (Maybe NotebookDocumentSyncClientCapabilities) + nbs = lens g s + where + g c = c ^. L.notebookDocument . non emptyNotebookDocumentClientCaps . L.synchronization . to Just + s c Nothing = c & L.notebookDocument .~ Nothing + s c (Just v) = c & L.notebookDocument . non emptyNotebookDocumentClientCaps . L.synchronization .~ v + +-- TODO: can we do this generically somehow? + +{- | Whether the client supports dynamic registration for the given method. + +Note that here we only consider the "main" method against which you dynamically register, so +even though e.g. we associate the client capabilities for code lenses with `codeLens/resolve`, +we don't ever say that you can dynamically register `codeLens/resolve`, because you in fact +need to register `textDocument/codeLens`. -} +dynamicRegistrationSupported :: SMethod m -> ClientCapabilities -> Bool +dynamicRegistrationSupported m caps = fromMaybe False $ case m of + SMethod_WorkspaceDidChangeConfiguration -> caps ^? dyn m + SMethod_WorkspaceDidChangeWatchedFiles -> caps ^? dyn m + SMethod_WorkspaceSymbol -> caps ^? dyn m + SMethod_WorkspaceExecuteCommand -> caps ^? dyn m + SMethod_WorkspaceWillCreateFiles -> caps ^? dyn m + SMethod_WorkspaceDidCreateFiles -> caps ^? dyn m + SMethod_WorkspaceWillDeleteFiles -> caps ^? dyn m + SMethod_WorkspaceDidDeleteFiles -> caps ^? dyn m + SMethod_TextDocumentDidOpen -> caps ^? dyn m + SMethod_TextDocumentDidChange -> caps ^? dyn m + SMethod_TextDocumentDidClose -> caps ^? dyn m + SMethod_TextDocumentCompletion -> caps ^? dyn m + SMethod_TextDocumentHover -> caps ^? dyn m + SMethod_TextDocumentSignatureHelp -> caps ^? dyn m + SMethod_TextDocumentDeclaration -> caps ^? dyn m + SMethod_TextDocumentDefinition -> caps ^? dyn m + SMethod_TextDocumentTypeDefinition -> caps ^? dyn m + SMethod_TextDocumentImplementation -> caps ^? dyn m + SMethod_TextDocumentReferences -> caps ^? dyn m + SMethod_TextDocumentDocumentHighlight -> caps ^? dyn m + SMethod_TextDocumentDocumentSymbol -> caps ^? dyn m + SMethod_TextDocumentCodeAction -> caps ^? dyn m + SMethod_TextDocumentCodeLens -> caps ^? dyn m + SMethod_TextDocumentDocumentLink -> caps ^? dyn m + SMethod_TextDocumentDocumentColor -> caps ^? dyn m + SMethod_TextDocumentColorPresentation -> caps ^? dyn m + SMethod_TextDocumentFormatting -> caps ^? dyn m + SMethod_TextDocumentRangeFormatting -> caps ^? dyn m + SMethod_TextDocumentOnTypeFormatting -> caps ^? dyn m + SMethod_TextDocumentRename -> caps ^? dyn m + SMethod_TextDocumentFoldingRange -> caps ^? dyn m + SMethod_TextDocumentSelectionRange -> caps ^? dyn m + SMethod_TextDocumentLinkedEditingRange -> caps ^? dyn m + SMethod_TextDocumentPrepareCallHierarchy -> caps ^? dyn m + SMethod_TextDocumentInlayHint -> caps ^? dyn m + SMethod_TextDocumentInlineValue -> caps ^? dyn m + SMethod_TextDocumentMoniker -> caps ^? dyn m + SMethod_TextDocumentPrepareTypeHierarchy -> caps ^? dyn m + SMethod_TextDocumentDiagnostic -> caps ^? dyn m + -- semantic tokens is messed up due to it having you register with an otherwise non-existent method + -- SMethod_TextDocumentSemanticTokens -> capDyn $ clientCaps ^? L.textDocument . _Just . L.semanticTokens . _Just + -- Notebook document methods alway support dynamic registration, it seems? + _ -> Just False + where + dyn :: L.HasDynamicRegistration (ClientCapability m) (Maybe Bool) => SMethod m -> Traversal' ClientCapabilities Bool + dyn m1 = clientCapability m1 . _Just . L.dynamicRegistration . _Just --- | Capabilities for full conformance to the current LSP specification. -fullCaps :: ClientCapabilities -fullCaps = capsForVersion (LSPVersion maxBound maxBound) +-- | Client capabilities for full support of the current LSP specification. +fullLatestClientCaps :: ClientCapabilities +fullLatestClientCaps = fullClientCapsForVersion (LSPVersion maxBound maxBound) --- | A specific version of the LSP specification. -data LSPVersion = LSPVersion Int Int +{- +TODO: the "since" conditions are out-of-date/needs an audit +TODO: can we generate this? process the 'since' annotations in the metamodel? +-} --- | Capabilities for full conformance to the LSP specification up until a version. -capsForVersion :: LSPVersion -> ClientCapabilities -capsForVersion (LSPVersion maj min) = caps +-- | Client capabilities for full support of the LSP specification up until a version. +fullClientCapsForVersion :: LSPVersion -> ClientCapabilities +fullClientCapsForVersion v@(LSPVersion maj min) = caps where + methCaps :: SMethod m -> Maybe (ClientCapability m) + methCaps = fullClientCapsForVersionAndMethod v + caps = ClientCapabilities - { _workspace = Just w + { _workspace = Just workspace , _textDocument = Just td , _window = Just window , _general = since 3 16 general - , _notebookDocument = since 3 17 $ NotebookDocumentClientCapabilities $ NotebookDocumentSyncClientCapabilities dynamicReg (Just True) + , _notebookDocument = NotebookDocumentClientCapabilities <$> methCaps SMethod_NotebookDocumentDidOpen , _experimental = Nothing } - w = + + window = + WindowClientCapabilities + { _workDoneProgress = methCaps SMethod_WindowWorkDoneProgressCreate + , _showMessage = methCaps SMethod_WindowShowMessageRequest + , _showDocument = methCaps SMethod_WindowShowDocument + } + + general = + GeneralClientCapabilities + { _staleRequestSupport = since 3 16 (StaleRequestSupportOptions{_cancel = True, _retryOnContentModified = []}) + , _regularExpressions = since 3 16 $ RegularExpressionsClientCapabilities (RegularExpressionEngineKind "") Nothing + , _markdown = since 3 16 $ MarkdownClientCapabilities "" Nothing (Just []) + , _positionEncodings = since 3 17 [PositionEncodingKind_UTF16] + } + + workspace = WorkspaceClientCapabilities - { _applyEdit = Just True + { _applyEdit = methCaps SMethod_WorkspaceApplyEdit , _workspaceEdit = Just ( WorkspaceEditClientCapabilities (Just True) - (since 3 13 resourceOperations) + (since 3 13 [ResourceOperationKind_Create, ResourceOperationKind_Delete, ResourceOperationKind_Rename]) Nothing (since 3 16 True) (since 3 16 (ChangeAnnotationsSupportOptions{_groupsOnLabel = Just True})) ) - , _didChangeConfiguration = Just (DidChangeConfigurationClientCapabilities dynamicReg) - , _didChangeWatchedFiles = Just (DidChangeWatchedFilesClientCapabilities dynamicReg (Just True)) - , _symbol = Just symbolCapabilities - , _executeCommand = Just (ExecuteCommandClientCapabilities dynamicReg) - , _codeLens = Just (CodeLensWorkspaceClientCapabilities $ Just True) - , _workspaceFolders = since 3 6 True - , _configuration = since 3 6 True - , _semanticTokens = since 3 16 (SemanticTokensWorkspaceClientCapabilities $ Just True) - , _inlayHint = since 3 17 (InlayHintWorkspaceClientCapabilities $ Just True) - , _fileOperations = since 3 16 fileOperations - , _inlineValue = since 3 17 (InlineValueWorkspaceClientCapabilities $ Just True) - , _diagnostics = since 3 17 (DiagnosticWorkspaceClientCapabilities $ Just True) + , _didChangeConfiguration = methCaps SMethod_WorkspaceDidChangeConfiguration + , _didChangeWatchedFiles = methCaps SMethod_WorkspaceDidChangeWatchedFiles + , _symbol = methCaps SMethod_WorkspaceSymbol + , _executeCommand = methCaps SMethod_WorkspaceExecuteCommand + , _codeLens = methCaps SMethod_WorkspaceCodeLensRefresh + , _workspaceFolders = methCaps SMethod_WorkspaceWorkspaceFolders + , _configuration = methCaps SMethod_WorkspaceConfiguration + , _semanticTokens = methCaps SMethod_WorkspaceSemanticTokensRefresh + , _inlayHint = methCaps SMethod_WorkspaceInlayHintRefresh + , _fileOperations = methCaps SMethod_WorkspaceDidCreateFiles + , _inlineValue = methCaps SMethod_WorkspaceInlineValueRefresh + , _diagnostics = methCaps SMethod_WorkspaceDiagnostic } - resourceOperations = - [ ResourceOperationKind_Create - , ResourceOperationKind_Delete - , ResourceOperationKind_Rename - ] + td = + TextDocumentClientCapabilities + { _synchronization = methCaps SMethod_TextDocumentDidOpen + , _completion = methCaps SMethod_TextDocumentCompletion + , _hover = methCaps SMethod_TextDocumentHover + , _signatureHelp = methCaps SMethod_TextDocumentSignatureHelp + , _references = methCaps SMethod_TextDocumentReferences + , _documentHighlight = methCaps SMethod_TextDocumentDocumentHighlight + , _documentSymbol = methCaps SMethod_TextDocumentDocumentSymbol + , _formatting = methCaps SMethod_TextDocumentFormatting + , _rangeFormatting = methCaps SMethod_TextDocumentRangeFormatting + , _onTypeFormatting = methCaps SMethod_TextDocumentOnTypeFormatting + , _declaration = methCaps SMethod_TextDocumentDeclaration + , _definition = methCaps SMethod_TextDocumentDefinition + , _typeDefinition = methCaps SMethod_TextDocumentTypeDefinition + , _implementation = methCaps SMethod_TextDocumentImplementation + , _codeAction = methCaps SMethod_TextDocumentCodeAction + , _codeLens = methCaps SMethod_TextDocumentCodeLens + , _documentLink = methCaps SMethod_TextDocumentDocumentLink + , _colorProvider = methCaps SMethod_TextDocumentDocumentColor + , _rename = methCaps SMethod_TextDocumentRename + , _publishDiagnostics = methCaps SMethod_TextDocumentPublishDiagnostics + , _foldingRange = methCaps SMethod_TextDocumentFoldingRange + , _selectionRange = methCaps SMethod_TextDocumentSelectionRange + , _callHierarchy = methCaps SMethod_TextDocumentPrepareCallHierarchy + , _semanticTokens = methCaps SMethod_TextDocumentSemanticTokensFull + , _linkedEditingRange = methCaps SMethod_TextDocumentLinkedEditingRange + , _moniker = methCaps SMethod_TextDocumentMoniker + , _inlayHint = methCaps SMethod_TextDocumentInlayHint + , _typeHierarchy = methCaps SMethod_TextDocumentPrepareTypeHierarchy + , _inlineValue = methCaps SMethod_TextDocumentInlineValue + , _diagnostic = methCaps SMethod_TextDocumentDiagnostic + } + + since :: Int -> Int -> a -> Maybe a + since x y a + | maj >= x && min >= y = Just a + | otherwise = Nothing +-- TODO: make this only include the caps that are necessary for that specific method. That will require +-- some code to merge capabilities... + +-- | Client capabilities for full support of a specific method in the LSP specification up until a version. +fullClientCapsForVersionAndMethod :: LSPVersion -> SMethod m -> Maybe (ClientCapability m) +fullClientCapsForVersionAndMethod (LSPVersion maj min) = \case + SMethod_TextDocumentDeclaration -> declaration + SMethod_TextDocumentImplementation -> implementation + SMethod_TextDocumentTypeDefinition -> typeDefinition + SMethod_TextDocumentHover -> hover + SMethod_TextDocumentSignatureHelp -> signatureHelp + SMethod_TextDocumentDefinition -> definition + SMethod_TextDocumentReferences -> references + SMethod_TextDocumentDocumentHighlight -> documentHighlight + SMethod_TextDocumentDocumentSymbol -> documentSymbol + SMethod_TextDocumentFoldingRange -> foldingRange + SMethod_TextDocumentSelectionRange -> selectionRange + SMethod_WorkspaceExecuteCommand -> executeCommand + SMethod_TextDocumentMoniker -> moniker + SMethod_TextDocumentCompletion -> completion + SMethod_CompletionItemResolve -> completion + SMethod_TextDocumentCodeAction -> codeAction + SMethod_CodeActionResolve -> codeAction + SMethod_TextDocumentCodeLens -> codeLens + SMethod_CodeLensResolve -> codeLens + SMethod_WorkspaceCodeLensRefresh -> wsCodeLens + SMethod_TextDocumentDocumentLink -> documentLink + SMethod_DocumentLinkResolve -> documentLink + SMethod_TextDocumentDocumentColor -> colorProvider + SMethod_TextDocumentColorPresentation -> colorProvider + SMethod_WorkspaceSymbol -> wsSymbol + SMethod_WorkspaceSymbolResolve -> wsSymbol + SMethod_TextDocumentFormatting -> formatting + SMethod_TextDocumentRangeFormatting -> rangeFormatting + SMethod_TextDocumentOnTypeFormatting -> onTypeFormatting + SMethod_TextDocumentRename -> rename + SMethod_TextDocumentPrepareRename -> rename + SMethod_TextDocumentPrepareCallHierarchy -> callHierarchy + SMethod_CallHierarchyIncomingCalls -> callHierarchy + SMethod_CallHierarchyOutgoingCalls -> callHierarchy + SMethod_TextDocumentLinkedEditingRange -> linkedEditingRange + SMethod_TextDocumentSemanticTokensFull -> semanticTokens + SMethod_TextDocumentSemanticTokensFullDelta -> semanticTokens + SMethod_TextDocumentSemanticTokensRange -> semanticTokens + SMethod_WorkspaceSemanticTokensRefresh -> wsSemanticTokens + SMethod_TextDocumentPrepareTypeHierarchy -> typeHierarchy + SMethod_TypeHierarchySubtypes -> typeHierarchy + SMethod_TypeHierarchySupertypes -> typeHierarchy + SMethod_TextDocumentInlineValue -> inlineValue + SMethod_WorkspaceInlineValueRefresh -> wsInlineValue + SMethod_TextDocumentInlayHint -> inlayHint + SMethod_InlayHintResolve -> inlayHint + SMethod_WorkspaceInlayHintRefresh -> wsInlayHint + SMethod_TextDocumentDiagnostic -> diagnostic + SMethod_WorkspaceDiagnostic -> diagnostics + SMethod_WorkspaceDiagnosticRefresh -> diagnostics + SMethod_WorkspaceWorkspaceFolders -> workspaceFolders + SMethod_WorkspaceWillCreateFiles -> fileOperations + SMethod_WorkspaceWillRenameFiles -> fileOperations + SMethod_WorkspaceWillDeleteFiles -> fileOperations + SMethod_WorkspaceDidCreateFiles -> fileOperations + SMethod_WorkspaceDidRenameFiles -> fileOperations + SMethod_WorkspaceDidDeleteFiles -> fileOperations + SMethod_TextDocumentDidOpen -> synchronization + SMethod_TextDocumentDidChange -> synchronization + SMethod_TextDocumentDidClose -> synchronization + SMethod_TextDocumentDidSave -> synchronization + SMethod_TextDocumentWillSave -> synchronization + SMethod_TextDocumentWillSaveWaitUntil -> synchronization + SMethod_NotebookDocumentDidOpen -> notebookDocumentSync + SMethod_NotebookDocumentDidChange -> notebookDocumentSync + SMethod_NotebookDocumentDidSave -> notebookDocumentSync + SMethod_NotebookDocumentDidClose -> notebookDocumentSync + SMethod_WorkspaceDidChangeConfiguration -> didChangeConfiguration + SMethod_WorkspaceDidChangeWatchedFiles -> didChangeWatchedFiles + SMethod_TextDocumentPublishDiagnostics -> publishDiagnostics + SMethod_WorkspaceConfiguration -> configuration + SMethod_WindowWorkDoneProgressCreate -> workDoneProgress + SMethod_WindowWorkDoneProgressCancel -> workDoneProgress + SMethod_WorkspaceApplyEdit -> applyEdit + SMethod_WindowShowDocument -> showDocument + SMethod_WindowShowMessageRequest -> showMessage + SMethod_WindowShowMessage -> showMessage + SMethod_WorkspaceDidChangeWorkspaceFolders -> Nothing + SMethod_Progress -> Nothing + SMethod_WindowLogMessage -> Nothing + SMethod_ClientRegisterCapability -> Nothing + SMethod_ClientUnregisterCapability -> Nothing + SMethod_Initialize -> Nothing + SMethod_Initialized -> Nothing + SMethod_Shutdown -> Nothing + SMethod_Exit -> Nothing + SMethod_TelemetryEvent -> Nothing + SMethod_SetTrace -> Nothing + SMethod_LogTrace -> Nothing + SMethod_CancelRequest -> Nothing + (SMethod_CustomMethod _s) -> Nothing + where + workDoneProgress = since 3 15 True + showMessage = since 3 16 $ ShowMessageRequestClientCapabilities Nothing + showDocument = since 3 16 $ ShowDocumentClientCapabilities True + applyEdit = Just True + didChangeConfiguration = Just (DidChangeConfigurationClientCapabilities dynamicReg) + didChangeWatchedFiles = Just (DidChangeWatchedFilesClientCapabilities dynamicReg (Just True)) + wsSymbol = + Just $ + WorkspaceSymbolClientCapabilities + dynamicReg + (since 3 4 (ClientSymbolKindOptions{_valueSet = Just sKs})) + (since 3 16 (ClientSymbolTagOptions{_valueSet = [SymbolTag_Deprecated]})) + (since 3 17 (ClientSymbolResolveOptions{_properties = []})) + executeCommand = Just (ExecuteCommandClientCapabilities dynamicReg) + wsCodeLens = Just (CodeLensWorkspaceClientCapabilities $ Just True) + workspaceFolders = since 3 6 True + configuration = since 3 6 True + wsSemanticTokens = since 3 16 (SemanticTokensWorkspaceClientCapabilities $ Just True) + wsInlayHint = since 3 17 (InlayHintWorkspaceClientCapabilities $ Just True) fileOperations = - FileOperationClientCapabilities - dynamicReg - (Just True) - (Just True) - (Just True) - (Just True) - (Just True) - (Just True) - - symbolCapabilities = - WorkspaceSymbolClientCapabilities - dynamicReg - (since 3 4 (ClientSymbolKindOptions{_valueSet = Just sKs})) - (since 3 16 (ClientSymbolTagOptions{_valueSet = [SymbolTag_Deprecated]})) - (since 3 17 (ClientSymbolResolveOptions{_properties = []})) + since 3 16 $ + FileOperationClientCapabilities + dynamicReg + (Just True) + (Just True) + (Just True) + (Just True) + (Just True) + (Just True) + wsInlineValue = since 3 17 (InlineValueWorkspaceClientCapabilities $ Just True) + diagnostics = since 3 17 (DiagnosticWorkspaceClientCapabilities $ Just True) + + notebookDocumentSync = since 3 17 $ NotebookDocumentSyncClientCapabilities dynamicReg (Just True) + + synchronization = + Just $ + TextDocumentSyncClientCapabilities{_dynamicRegistration = dynamicReg, _willSave = Just True, _willSaveWaitUntil = Just True, _didSave = Just True} + completion = + Just $ + CompletionClientCapabilities + { _dynamicRegistration = dynamicReg + , _completionItem = Just completionItemCapabilities + , _completionItemKind = since 3 4 (ClientCompletionItemOptionsKind{_valueSet = Just ciKs}) + , _insertTextMode = since 3 17 InsertTextMode_AsIs + , _contextSupport = since 3 3 True + , _completionList = since 3 17 (CompletionListCapabilities{_itemDefaults = Just []}) + } + hover = + Just $ + HoverClientCapabilities + { _dynamicRegistration = dynamicReg + , _contentFormat = since 3 3 allMarkups + } + signatureHelp = + Just $ + SignatureHelpClientCapabilities + { _dynamicRegistration = dynamicReg + , _signatureInformation = + Just $ + ClientSignatureInformationOptions + { _documentationFormat = Just allMarkups + , _parameterInformation = Just (ClientSignatureParameterInformationOptions{_labelOffsetSupport = Just True}) + , _activeParameterSupport = Just True + } + , _contextSupport = since 3 16 True + } + references = Just $ ReferenceClientCapabilities dynamicReg + documentHighlight = Just $ DocumentHighlightClientCapabilities dynamicReg + documentSymbol = + Just $ + DocumentSymbolClientCapabilities + { _dynamicRegistration = dynamicReg + , -- same as workspace symbol kinds + _symbolKind = Just (ClientSymbolKindOptions{_valueSet = Just sKs}) + , _hierarchicalDocumentSymbolSupport = since 3 10 True + , _tagSupport = since 3 16 (ClientSymbolTagOptions{_valueSet = [SymbolTag_Deprecated]}) + , _labelSupport = since 3 16 True + } + formatting = Just $ DocumentFormattingClientCapabilities dynamicReg + rangeFormatting = Just $ DocumentRangeFormattingClientCapabilities dynamicReg + onTypeFormatting = Just $ DocumentOnTypeFormattingClientCapabilities dynamicReg + declaration = since 3 14 (DeclarationClientCapabilities dynamicReg (Just True)) + definition = Just (DefinitionClientCapabilities dynamicReg (since 3 14 True)) + typeDefinition = since 3 6 (TypeDefinitionClientCapabilities dynamicReg (since 3 14 True)) + implementation = since 3 6 (ImplementationClientCapabilities dynamicReg (since 3 14 True)) + codeAction = + Just $ + CodeActionClientCapabilities + { _dynamicRegistration = dynamicReg + , _codeActionLiteralSupport = since 3 8 (ClientCodeActionLiteralOptions{_codeActionKind = ClientCodeActionKindOptions{_valueSet = Set.toList knownValues}}) + , _isPreferredSupport = since 3 15 True + , _disabledSupport = since 3 16 True + , _dataSupport = since 3 16 True + , _resolveSupport = since 3 16 (ClientCodeActionResolveOptions{_properties = []}) + , _honorsChangeAnnotations = since 3 16 True + } + codeLens = Just (CodeLensClientCapabilities dynamicReg) + documentLink = Just (DocumentLinkClientCapabilities dynamicReg (since 3 15 True)) + colorProvider = since 3 6 (DocumentColorClientCapabilities dynamicReg) + rename = Just (RenameClientCapabilities dynamicReg (since 3 12 True) (since 3 16 PrepareSupportDefaultBehavior_Identifier) (since 3 16 True)) + publishDiagnostics = + Just + PublishDiagnosticsClientCapabilities + { _relatedInformation = since 3 7 True + , _tagSupport = since 3 15 (ClientDiagnosticsTagOptions{_valueSet = [DiagnosticTag_Unnecessary, DiagnosticTag_Deprecated]}) + , _versionSupport = since 3 15 True + , _codeDescriptionSupport = since 3 16 True + , _dataSupport = since 3 16 True + } + foldingRange = + since 3 10 $ + FoldingRangeClientCapabilities + { _dynamicRegistration = dynamicReg + , _rangeLimit = Nothing + , _lineFoldingOnly = Nothing + , _foldingRangeKind = since 3 17 (ClientFoldingRangeKindOptions{_valueSet = Just []}) + , _foldingRange = since 3 16 (ClientFoldingRangeOptions{_collapsedText = Just True}) + } + selectionRange = since 3 5 (SelectionRangeClientCapabilities dynamicReg) + callHierarchy = since 3 16 (CallHierarchyClientCapabilities dynamicReg) + semanticTokens = + since 3 16 $ + SemanticTokensClientCapabilities + { _dynamicRegistration = Just True + , _requests = ClientSemanticTokensRequestOptions{_range = Just (InL True), _full = Just (InR (ClientSemanticTokensRequestFullDelta{_delta = Just True}))} + , _tokenTypes = toEnumBaseType <$> Set.toList (knownValues @SemanticTokenTypes) + , _tokenModifiers = toEnumBaseType <$> Set.toList (knownValues @SemanticTokenModifiers) + , _formats = tfs + , _overlappingTokenSupport = Just True + , _multilineTokenSupport = Just True + , _serverCancelSupport = Just True + , _augmentsSyntaxTokens = Just True + } + linkedEditingRange = since 3 16 (LinkedEditingRangeClientCapabilities dynamicReg) + moniker = since 3 16 (MonikerClientCapabilities dynamicReg) + inlayHint = + since 3 17 $ + InlayHintClientCapabilities + { _dynamicRegistration = dynamicReg + , _resolveSupport = Just (ClientInlayHintResolveOptions{_properties = []}) + } + typeHierarchy = since 3 17 (TypeHierarchyClientCapabilities dynamicReg) + inlineValue = since 3 17 (InlineValueClientCapabilities dynamicReg) + diagnostic = since 3 17 (DiagnosticClientCapabilities dynamicReg (Just True)) + + completionItemCapabilities = + ClientCompletionItemOptions + { _snippetSupport = Just True + , _commitCharactersSupport = Just True + , _documentationFormat = since 3 3 allMarkups + , _deprecatedSupport = Just True + , _preselectSupport = since 3 9 True + , _tagSupport = since 3 15 (CompletionItemTagOptions{_valueSet = []}) + , _insertReplaceSupport = since 3 16 True + , _resolveSupport = since 3 16 (ClientCompletionItemResolveOptions{_properties = ["documentation", "details"]}) + , _insertTextModeSupport = since 3 16 (ClientCompletionItemInsertTextModeOptions{_valueSet = []}) + , _labelDetailsSupport = since 3 17 True + } sKs | maj >= 3 && min >= 4 = oldSKs ++ newSKs @@ -126,94 +705,6 @@ capsForVersion (LSPVersion maj min) = caps , SymbolKind_TypeParameter ] - -- Only one token format for now, just list it here - tfs = [TokenFormat_Relative] - - semanticTokensCapabilities = - SemanticTokensClientCapabilities - { _dynamicRegistration = Just True - , _requests = ClientSemanticTokensRequestOptions{_range = Just (InL True), _full = Just (InR (ClientSemanticTokensRequestFullDelta{_delta = Just True}))} - , _tokenTypes = toEnumBaseType <$> Set.toList (knownValues @SemanticTokenTypes) - , _tokenModifiers = toEnumBaseType <$> Set.toList (knownValues @SemanticTokenModifiers) - , _formats = tfs - , _overlappingTokenSupport = Just True - , _multilineTokenSupport = Just True - , _serverCancelSupport = Just True - , _augmentsSyntaxTokens = Just True - } - - td = - TextDocumentClientCapabilities - { _synchronization = Just sync - , _completion = Just completionCapability - , _hover = Just hoverCapability - , _signatureHelp = Just signatureHelpCapability - , _references = Just (ReferenceClientCapabilities dynamicReg) - , _documentHighlight = Just (DocumentHighlightClientCapabilities dynamicReg) - , _documentSymbol = Just documentSymbolCapability - , _formatting = Just (DocumentFormattingClientCapabilities dynamicReg) - , _rangeFormatting = Just (DocumentRangeFormattingClientCapabilities dynamicReg) - , _onTypeFormatting = Just (DocumentOnTypeFormattingClientCapabilities dynamicReg) - , _declaration = since 3 14 (DeclarationClientCapabilities dynamicReg (Just True)) - , _definition = Just (DefinitionClientCapabilities dynamicReg (since 3 14 True)) - , _typeDefinition = since 3 6 (TypeDefinitionClientCapabilities dynamicReg (since 3 14 True)) - , _implementation = since 3 6 (ImplementationClientCapabilities dynamicReg (since 3 14 True)) - , _codeAction = Just codeActionCapability - , _codeLens = Just (CodeLensClientCapabilities dynamicReg) - , _documentLink = Just (DocumentLinkClientCapabilities dynamicReg (since 3 15 True)) - , _colorProvider = since 3 6 (DocumentColorClientCapabilities dynamicReg) - , _rename = Just (RenameClientCapabilities dynamicReg (since 3 12 True) (since 3 16 PrepareSupportDefaultBehavior_Identifier) (since 3 16 True)) - , _publishDiagnostics = Just publishDiagnosticsCapabilities - , _foldingRange = since 3 10 foldingRangeCapability - , _selectionRange = since 3 5 (SelectionRangeClientCapabilities dynamicReg) - , _callHierarchy = since 3 16 (CallHierarchyClientCapabilities dynamicReg) - , _semanticTokens = since 3 16 semanticTokensCapabilities - , _linkedEditingRange = since 3 16 (LinkedEditingRangeClientCapabilities dynamicReg) - , _moniker = since 3 16 (MonikerClientCapabilities dynamicReg) - , _inlayHint = since 3 17 inlayHintCapabilities - , _typeHierarchy = since 3 17 (TypeHierarchyClientCapabilities dynamicReg) - , _inlineValue = since 3 17 (InlineValueClientCapabilities dynamicReg) - , _diagnostic = since 3 17 (DiagnosticClientCapabilities dynamicReg (Just True)) - } - - sync = - TextDocumentSyncClientCapabilities - { _dynamicRegistration = dynamicReg - , _willSave = Just True - , _willSaveWaitUntil = Just True - , _didSave = Just True - } - - completionCapability = - CompletionClientCapabilities - { _dynamicRegistration = dynamicReg - , _completionItem = Just completionItemCapabilities - , _completionItemKind = since 3 4 (ClientCompletionItemOptionsKind{_valueSet = Just ciKs}) - , _insertTextMode = since 3 17 InsertTextMode_AsIs - , _contextSupport = since 3 3 True - , _completionList = since 3 17 (CompletionListCapabilities{_itemDefaults = Just []}) - } - - inlayHintCapabilities = - InlayHintClientCapabilities - { _dynamicRegistration = dynamicReg - , _resolveSupport = Just (ClientInlayHintResolveOptions{_properties = []}) - } - - completionItemCapabilities = - ClientCompletionItemOptions - { _snippetSupport = Just True - , _commitCharactersSupport = Just True - , _documentationFormat = since 3 3 allMarkups - , _deprecatedSupport = Just True - , _preselectSupport = since 3 9 True - , _tagSupport = since 3 15 (CompletionItemTagOptions{_valueSet = []}) - , _insertReplaceSupport = since 3 16 True - , _resolveSupport = since 3 16 (ClientCompletionItemResolveOptions{_properties = ["documentation", "details"]}) - , _insertTextModeSupport = since 3 16 (ClientCompletionItemInsertTextModeOptions{_valueSet = []}) - , _labelDetailsSupport = since 3 17 True - } - ciKs | maj >= 3 && min >= 4 = oldCiKs ++ newCiKs | otherwise = oldCiKs @@ -249,63 +740,9 @@ capsForVersion (LSPVersion maj min) = caps , CompletionItemKind_TypeParameter ] - hoverCapability = - HoverClientCapabilities - { _dynamicRegistration = dynamicReg - , _contentFormat = since 3 3 allMarkups - } - - codeActionCapability = - CodeActionClientCapabilities - { _dynamicRegistration = dynamicReg - , _codeActionLiteralSupport = since 3 8 (ClientCodeActionLiteralOptions{_codeActionKind = ClientCodeActionKindOptions{_valueSet = Set.toList knownValues}}) - , _isPreferredSupport = since 3 15 True - , _disabledSupport = since 3 16 True - , _dataSupport = since 3 16 True - , _resolveSupport = since 3 16 (ClientCodeActionResolveOptions{_properties = []}) - , _honorsChangeAnnotations = since 3 16 True - } - - signatureHelpCapability = - SignatureHelpClientCapabilities - { _dynamicRegistration = dynamicReg - , _signatureInformation = - Just $ - ClientSignatureInformationOptions - { _documentationFormat = Just allMarkups - , _parameterInformation = Just (ClientSignatureParameterInformationOptions{_labelOffsetSupport = Just True}) - , _activeParameterSupport = Just True - } - , _contextSupport = since 3 16 True - } - - documentSymbolCapability = - DocumentSymbolClientCapabilities - { _dynamicRegistration = dynamicReg - , -- same as workspace symbol kinds - _symbolKind = Just (ClientSymbolKindOptions{_valueSet = Just sKs}) - , _hierarchicalDocumentSymbolSupport = since 3 10 True - , _tagSupport = since 3 16 (ClientSymbolTagOptions{_valueSet = [SymbolTag_Deprecated]}) - , _labelSupport = since 3 16 True - } - - foldingRangeCapability = - FoldingRangeClientCapabilities - { _dynamicRegistration = dynamicReg - , _rangeLimit = Nothing - , _lineFoldingOnly = Nothing - , _foldingRangeKind = since 3 17 (ClientFoldingRangeKindOptions{_valueSet = Just []}) - , _foldingRange = since 3 16 (ClientFoldingRangeOptions{_collapsedText = Just True}) - } + allMarkups = [MarkupKind_PlainText, MarkupKind_Markdown] - publishDiagnosticsCapabilities = - PublishDiagnosticsClientCapabilities - { _relatedInformation = since 3 7 True - , _tagSupport = since 3 15 (ClientDiagnosticsTagOptions{_valueSet = [DiagnosticTag_Unnecessary, DiagnosticTag_Deprecated]}) - , _versionSupport = since 3 15 True - , _codeDescriptionSupport = since 3 16 True - , _dataSupport = since 3 16 True - } + tfs = [TokenFormat_Relative] dynamicReg | maj >= 3 = Just True @@ -315,75 +752,243 @@ capsForVersion (LSPVersion maj min) = caps | maj >= x && min >= y = Just a | otherwise = Nothing - window = - WindowClientCapabilities - { _workDoneProgress = since 3 15 True - , _showMessage = since 3 16 $ ShowMessageRequestClientCapabilities Nothing - , _showDocument = since 3 16 $ ShowDocumentClientCapabilities True - } +---- SERVER CAPABILITIES - general = - GeneralClientCapabilities - { _staleRequestSupport = since 3 16 (StaleRequestSupportOptions{_cancel = True, _retryOnContentModified = []}) - , _regularExpressions = since 3 16 $ RegularExpressionsClientCapabilities (RegularExpressionEngineKind "") Nothing - , _markdown = since 3 16 $ MarkdownClientCapabilities "" Nothing (Just []) - , _positionEncodings = since 3 17 [PositionEncodingKind_UTF16] - } +type DocumentSyncCaps = TextDocumentSyncOptions |? TextDocumentSyncKind +type NotebookDocumentSyncCaps = NotebookDocumentSyncOptions |? NotebookDocumentSyncRegistrationOptions - allMarkups = [MarkupKind_PlainText, MarkupKind_Markdown] +type ServerCapability :: forall f t. Method f t -> Type --- | Whether the client supports dynamic registration for the given method. -dynamicRegistrationSupported :: SMethod m -> ClientCapabilities -> Bool -dynamicRegistrationSupported method caps = fromMaybe False $ case method of - SMethod_WorkspaceDidChangeConfiguration -> caps ^? ws . L.didChangeConfiguration . _Just . dyn - SMethod_WorkspaceDidChangeWatchedFiles -> caps ^? ws . L.didChangeWatchedFiles . _Just . dyn - SMethod_WorkspaceSymbol -> caps ^? ws . L.symbol . _Just . dyn - SMethod_WorkspaceExecuteCommand -> caps ^? ws . L.executeCommand . _Just . dyn - SMethod_WorkspaceWillCreateFiles -> caps ^? ws . L.fileOperations . _Just . dyn - SMethod_WorkspaceDidCreateFiles -> caps ^? ws . L.fileOperations . _Just . dyn - SMethod_WorkspaceWillDeleteFiles -> caps ^? ws . L.fileOperations . _Just . dyn - SMethod_WorkspaceDidDeleteFiles -> caps ^? ws . L.fileOperations . _Just . dyn - SMethod_TextDocumentDidOpen -> caps ^? td . L.synchronization . _Just . dyn - SMethod_TextDocumentDidChange -> caps ^? td . L.synchronization . _Just . dyn - SMethod_TextDocumentDidClose -> caps ^? td . L.synchronization . _Just . dyn - SMethod_TextDocumentCompletion -> caps ^? td . L.completion . _Just . dyn - SMethod_TextDocumentHover -> caps ^? td . L.hover . _Just . dyn - SMethod_TextDocumentSignatureHelp -> caps ^? td . L.signatureHelp . _Just . dyn - SMethod_TextDocumentDeclaration -> caps ^? td . L.declaration . _Just . dyn - SMethod_TextDocumentDefinition -> caps ^? td . L.definition . _Just . dyn - SMethod_TextDocumentTypeDefinition -> caps ^? td . L.typeDefinition . _Just . dyn - SMethod_TextDocumentImplementation -> caps ^? td . L.implementation . _Just . dyn - SMethod_TextDocumentReferences -> caps ^? td . L.references . _Just . dyn - SMethod_TextDocumentDocumentHighlight -> caps ^? td . L.documentHighlight . _Just . dyn - SMethod_TextDocumentDocumentSymbol -> caps ^? td . L.documentSymbol . _Just . dyn - SMethod_TextDocumentCodeAction -> caps ^? td . L.codeAction . _Just . dyn - SMethod_TextDocumentCodeLens -> caps ^? td . L.codeLens . _Just . dyn - SMethod_TextDocumentDocumentLink -> caps ^? td . L.documentLink . _Just . dyn - SMethod_TextDocumentDocumentColor -> caps ^? td . L.colorProvider . _Just . dyn - SMethod_TextDocumentColorPresentation -> caps ^? td . L.colorProvider . _Just . dyn - SMethod_TextDocumentFormatting -> caps ^? td . L.formatting . _Just . dyn - SMethod_TextDocumentRangeFormatting -> caps ^? td . L.rangeFormatting . _Just . dyn - SMethod_TextDocumentOnTypeFormatting -> caps ^? td . L.onTypeFormatting . _Just . dyn - SMethod_TextDocumentRename -> caps ^? td . L.rename . _Just . dyn - SMethod_TextDocumentFoldingRange -> caps ^? td . L.foldingRange . _Just . dyn - SMethod_TextDocumentSelectionRange -> caps ^? td . L.selectionRange . _Just . dyn - SMethod_TextDocumentLinkedEditingRange -> caps ^? td . L.linkedEditingRange . _Just . dyn - SMethod_TextDocumentPrepareCallHierarchy -> caps ^? td . L.callHierarchy . _Just . dyn - SMethod_TextDocumentInlayHint -> caps ^? td . L.inlayHint . _Just . dyn - SMethod_TextDocumentInlineValue -> caps ^? td . L.inlineValue . _Just . dyn - SMethod_TextDocumentMoniker -> caps ^? td . L.moniker . _Just . dyn - SMethod_TextDocumentPrepareTypeHierarchy -> caps ^? td . L.typeHierarchy . _Just . dyn - SMethod_TextDocumentDiagnostic -> caps ^? td . L.diagnostic . _Just . dyn - -- semantic tokens is messed up due to it having you register with an otherwise non-existent method - -- SMethod_TextDocumentSemanticTokens -> capDyn $ clientCaps ^? L.textDocument . _Just . L.semanticTokens . _Just - -- Notebook document methods alway support dynamic registration, it seems? - _ -> Just False - where - td :: Traversal' ClientCapabilities TextDocumentClientCapabilities - td = L.textDocument . _Just +-- See Note [Capability mappings] - ws :: Traversal' ClientCapabilities WorkspaceClientCapabilities - ws = L.workspace . _Just +{- | The server capability associated with a given method. - dyn :: L.HasDynamicRegistration a (Maybe Bool) => Traversal' a Bool - dyn = L.dynamicRegistration . _Just +Where several methods are provided together (e.g. the three `callHierarchy` methods), we associate all of them +with the capaiblity, even if there is one "primary" method. + +For methods which strictly only need a client capability but which are closely related to a server capability +(e.g. `codeLens/refresh`), we also associate them with that server capability. +-} +type family ServerCapability (m :: Method f t) where + ServerCapability Method_TextDocumentDeclaration = Bool |? (DeclarationOptions |? DeclarationRegistrationOptions) + ServerCapability Method_TextDocumentImplementation = Bool |? (ImplementationOptions |? ImplementationRegistrationOptions) + ServerCapability Method_TextDocumentTypeDefinition = Bool |? (TypeDefinitionOptions |? TypeDefinitionRegistrationOptions) + ServerCapability Method_TextDocumentHover = Bool |? HoverOptions + ServerCapability Method_TextDocumentSignatureHelp = SignatureHelpOptions + ServerCapability Method_TextDocumentDefinition = Bool |? DefinitionOptions + ServerCapability Method_TextDocumentReferences = Bool |? ReferenceOptions + ServerCapability Method_TextDocumentDocumentHighlight = Bool |? DocumentHighlightOptions + ServerCapability Method_TextDocumentDocumentSymbol = Bool |? DocumentSymbolOptions + ServerCapability Method_TextDocumentFoldingRange = Bool |? (FoldingRangeOptions |? FoldingRangeRegistrationOptions) + ServerCapability Method_TextDocumentSelectionRange = Bool |? (SelectionRangeOptions |? SelectionRangeRegistrationOptions) + ServerCapability Method_WorkspaceExecuteCommand = ExecuteCommandOptions + ServerCapability Method_TextDocumentLinkedEditingRange = Bool |? (LinkedEditingRangeOptions |? LinkedEditingRangeRegistrationOptions) + ServerCapability Method_TextDocumentMoniker = Bool |? (MonikerOptions |? MonikerRegistrationOptions) + ServerCapability Method_WorkspaceWorkspaceFolders = WorkspaceFoldersServerCapabilities + ServerCapability Method_TextDocumentCompletion = CompletionOptions + ServerCapability Method_CompletionItemResolve = CompletionOptions + ServerCapability Method_TextDocumentCodeAction = Bool |? CodeActionOptions + ServerCapability Method_CodeActionResolve = Bool |? CodeActionOptions + ServerCapability Method_TextDocumentCodeLens = CodeLensOptions + ServerCapability Method_CodeLensResolve = CodeLensOptions + ServerCapability Method_WorkspaceCodeLensRefresh = CodeLensOptions + ServerCapability Method_TextDocumentDocumentLink = DocumentLinkOptions + ServerCapability Method_DocumentLinkResolve = DocumentLinkOptions + ServerCapability Method_WorkspaceSymbol = Bool |? WorkspaceSymbolOptions + ServerCapability Method_WorkspaceSymbolResolve = Bool |? WorkspaceSymbolOptions + ServerCapability Method_TextDocumentRename = Bool |? RenameOptions + ServerCapability Method_TextDocumentPrepareRename = Bool |? RenameOptions + ServerCapability Method_TextDocumentDocumentColor = Bool |? (DocumentColorOptions |? DocumentColorRegistrationOptions) + ServerCapability Method_TextDocumentColorPresentation = Bool |? (DocumentColorOptions |? DocumentColorRegistrationOptions) + ServerCapability Method_TextDocumentFormatting = Bool |? DocumentFormattingOptions + ServerCapability Method_TextDocumentRangeFormatting = Bool |? DocumentRangeFormattingOptions + ServerCapability Method_TextDocumentOnTypeFormatting = DocumentOnTypeFormattingOptions + ServerCapability Method_TextDocumentPrepareCallHierarchy = Bool |? (CallHierarchyOptions |? CallHierarchyRegistrationOptions) + ServerCapability Method_CallHierarchyIncomingCalls = Bool |? (CallHierarchyOptions |? CallHierarchyRegistrationOptions) + ServerCapability Method_CallHierarchyOutgoingCalls = Bool |? (CallHierarchyOptions |? CallHierarchyRegistrationOptions) + ServerCapability Method_TextDocumentSemanticTokensFull = SemanticTokensOptions |? SemanticTokensRegistrationOptions + ServerCapability Method_TextDocumentSemanticTokensFullDelta = SemanticTokensOptions |? SemanticTokensRegistrationOptions + ServerCapability Method_TextDocumentSemanticTokensRange = SemanticTokensOptions |? SemanticTokensRegistrationOptions + ServerCapability Method_WorkspaceSemanticTokensRefresh = SemanticTokensOptions |? SemanticTokensRegistrationOptions + ServerCapability Method_TextDocumentPrepareTypeHierarchy = Bool |? (TypeHierarchyOptions |? TypeHierarchyRegistrationOptions) + ServerCapability Method_TypeHierarchySupertypes = Bool |? (TypeHierarchyOptions |? TypeHierarchyRegistrationOptions) + ServerCapability Method_TypeHierarchySubtypes = Bool |? (TypeHierarchyOptions |? TypeHierarchyRegistrationOptions) + ServerCapability Method_TextDocumentInlineValue = Bool |? (InlineValueOptions |? InlineValueRegistrationOptions) + ServerCapability Method_WorkspaceInlineValueRefresh = Bool |? (InlineValueOptions |? InlineValueRegistrationOptions) + ServerCapability Method_TextDocumentInlayHint = Bool |? (InlayHintOptions |? InlayHintRegistrationOptions) + ServerCapability Method_InlayHintResolve = Bool |? (InlayHintOptions |? InlayHintRegistrationOptions) + ServerCapability Method_WorkspaceInlayHintRefresh = Bool |? (InlayHintOptions |? InlayHintRegistrationOptions) + ServerCapability Method_TextDocumentDiagnostic = DiagnosticOptions |? DiagnosticRegistrationOptions + ServerCapability Method_WorkspaceDiagnostic = DiagnosticOptions |? DiagnosticRegistrationOptions + ServerCapability Method_WorkspaceDiagnosticRefresh = DiagnosticOptions |? DiagnosticRegistrationOptions + ServerCapability Method_WorkspaceWillCreateFiles = FileOperationOptions + ServerCapability Method_WorkspaceWillRenameFiles = FileOperationOptions + ServerCapability Method_WorkspaceWillDeleteFiles = FileOperationOptions + ServerCapability Method_WorkspaceDidCreateFiles = FileOperationOptions + ServerCapability Method_WorkspaceDidRenameFiles = FileOperationOptions + ServerCapability Method_WorkspaceDidDeleteFiles = FileOperationOptions + ServerCapability Method_TextDocumentDidOpen = DocumentSyncCaps + ServerCapability Method_TextDocumentDidChange = DocumentSyncCaps + ServerCapability Method_TextDocumentDidClose = DocumentSyncCaps + ServerCapability Method_TextDocumentDidSave = DocumentSyncCaps + ServerCapability Method_TextDocumentWillSave = DocumentSyncCaps + ServerCapability Method_TextDocumentWillSaveWaitUntil = DocumentSyncCaps + ServerCapability Method_NotebookDocumentDidOpen = NotebookDocumentSyncCaps + ServerCapability Method_NotebookDocumentDidChange = NotebookDocumentSyncCaps + ServerCapability Method_NotebookDocumentDidSave = NotebookDocumentSyncCaps + ServerCapability Method_NotebookDocumentDidClose = NotebookDocumentSyncCaps + -- Dynamic registration only + ServerCapability Method_WorkspaceDidChangeConfiguration = Void + ServerCapability Method_WorkspaceDidChangeWatchedFiles = Void + ServerCapability Method_WorkspaceDidChangeWorkspaceFolders = Void + -- Client capability only + ServerCapability Method_TextDocumentPublishDiagnostics = Void + ServerCapability Method_WorkspaceConfiguration = Void + -- All required by default, no capabilities + ServerCapability Method_WindowWorkDoneProgressCreate = Void + ServerCapability Method_WindowWorkDoneProgressCancel = Void + ServerCapability Method_Progress = Void + ServerCapability Method_WindowShowDocument = Void + ServerCapability Method_WindowShowMessageRequest = Void + ServerCapability Method_WindowShowMessage = Void + ServerCapability Method_WindowLogMessage = Void + ServerCapability Method_ClientRegisterCapability = Void + ServerCapability Method_ClientUnregisterCapability = Void + ServerCapability Method_Initialize = Void + ServerCapability Method_Initialized = Void + ServerCapability Method_Shutdown = Void + ServerCapability Method_Exit = Void + ServerCapability Method_WorkspaceApplyEdit = Void + ServerCapability Method_TelemetryEvent = Void + ServerCapability Method_SetTrace = Void + ServerCapability Method_LogTrace = Void + ServerCapability Method_CancelRequest = Void + ServerCapability (Method_CustomMethod s) = Void + +-- See Note [Capability mappings] + +-- | A lens which focusses on the (possibly absent) server capability associated with a method. +serverCapability :: forall m. SMethod m -> Lens' ServerCapabilities (Maybe (ServerCapability m)) +serverCapability = \case + SMethod_TextDocumentDeclaration -> L.declarationProvider + SMethod_TextDocumentImplementation -> L.implementationProvider + SMethod_TextDocumentTypeDefinition -> L.typeDefinitionProvider + SMethod_TextDocumentHover -> L.hoverProvider + SMethod_TextDocumentSignatureHelp -> L.signatureHelpProvider + SMethod_TextDocumentDefinition -> L.definitionProvider + SMethod_TextDocumentReferences -> L.referencesProvider + SMethod_TextDocumentDocumentHighlight -> L.documentHighlightProvider + SMethod_TextDocumentDocumentSymbol -> L.documentSymbolProvider + SMethod_TextDocumentFoldingRange -> L.foldingRangeProvider + SMethod_TextDocumentSelectionRange -> L.selectionRangeProvider + SMethod_WorkspaceExecuteCommand -> L.executeCommandProvider + SMethod_TextDocumentMoniker -> L.monikerProvider + SMethod_TextDocumentCompletion -> L.completionProvider + SMethod_CompletionItemResolve -> L.completionProvider + SMethod_TextDocumentCodeAction -> L.codeActionProvider + SMethod_CodeActionResolve -> L.codeActionProvider + SMethod_TextDocumentCodeLens -> L.codeLensProvider + SMethod_CodeLensResolve -> L.codeLensProvider + SMethod_WorkspaceCodeLensRefresh -> L.codeLensProvider + SMethod_TextDocumentDocumentLink -> L.documentLinkProvider + SMethod_DocumentLinkResolve -> L.documentLinkProvider + SMethod_TextDocumentDocumentColor -> L.colorProvider + SMethod_TextDocumentColorPresentation -> L.colorProvider + SMethod_WorkspaceSymbol -> L.workspaceSymbolProvider + SMethod_WorkspaceSymbolResolve -> L.workspaceSymbolProvider + SMethod_TextDocumentFormatting -> L.documentFormattingProvider + SMethod_TextDocumentRangeFormatting -> L.documentRangeFormattingProvider + SMethod_TextDocumentOnTypeFormatting -> L.documentOnTypeFormattingProvider + SMethod_TextDocumentRename -> L.renameProvider + SMethod_TextDocumentPrepareRename -> L.renameProvider + SMethod_TextDocumentPrepareCallHierarchy -> L.callHierarchyProvider + SMethod_CallHierarchyIncomingCalls -> L.callHierarchyProvider + SMethod_CallHierarchyOutgoingCalls -> L.callHierarchyProvider + SMethod_TextDocumentLinkedEditingRange -> L.linkedEditingRangeProvider + SMethod_TextDocumentSemanticTokensFull -> L.semanticTokensProvider + SMethod_TextDocumentSemanticTokensFullDelta -> L.semanticTokensProvider + SMethod_TextDocumentSemanticTokensRange -> L.semanticTokensProvider + SMethod_WorkspaceSemanticTokensRefresh -> L.semanticTokensProvider + SMethod_TextDocumentPrepareTypeHierarchy -> L.typeHierarchyProvider + SMethod_TypeHierarchySubtypes -> L.typeHierarchyProvider + SMethod_TypeHierarchySupertypes -> L.typeHierarchyProvider + SMethod_TextDocumentInlineValue -> L.inlineValueProvider + SMethod_WorkspaceInlineValueRefresh -> L.inlineValueProvider + SMethod_TextDocumentInlayHint -> L.inlayHintProvider + SMethod_InlayHintResolve -> L.inlayHintProvider + SMethod_WorkspaceInlayHintRefresh -> L.inlayHintProvider + SMethod_TextDocumentDiagnostic -> L.diagnosticProvider + SMethod_WorkspaceDiagnostic -> L.diagnosticProvider + SMethod_WorkspaceDiagnosticRefresh -> L.diagnosticProvider + SMethod_WorkspaceWorkspaceFolders -> L.workspace . non emptyWorkspaceServerCaps . L.workspaceFolders + SMethod_WorkspaceWillCreateFiles -> fileOps + SMethod_WorkspaceWillRenameFiles -> fileOps + SMethod_WorkspaceWillDeleteFiles -> fileOps + SMethod_WorkspaceDidCreateFiles -> fileOps + SMethod_WorkspaceDidRenameFiles -> fileOps + SMethod_WorkspaceDidDeleteFiles -> fileOps + SMethod_TextDocumentDidOpen -> documentSync + SMethod_TextDocumentDidChange -> documentSync + SMethod_TextDocumentDidClose -> documentSync + SMethod_TextDocumentDidSave -> documentSync + SMethod_TextDocumentWillSave -> documentSync + SMethod_TextDocumentWillSaveWaitUntil -> documentSync + SMethod_NotebookDocumentDidOpen -> notebookDocumentSync + SMethod_NotebookDocumentDidChange -> notebookDocumentSync + SMethod_NotebookDocumentDidSave -> notebookDocumentSync + SMethod_NotebookDocumentDidClose -> notebookDocumentSync + SMethod_WorkspaceDidChangeConfiguration -> noCap + SMethod_WorkspaceDidChangeWatchedFiles -> noCap + SMethod_WorkspaceDidChangeWorkspaceFolders -> noCap + SMethod_TextDocumentPublishDiagnostics -> noCap + SMethod_WorkspaceConfiguration -> noCap + SMethod_WindowWorkDoneProgressCreate -> noCap + SMethod_WindowWorkDoneProgressCancel -> noCap + SMethod_Progress -> noCap + SMethod_WindowShowDocument -> noCap + SMethod_WindowShowMessageRequest -> noCap + SMethod_WindowShowMessage -> noCap + SMethod_WindowLogMessage -> noCap + SMethod_ClientRegisterCapability -> noCap + SMethod_ClientUnregisterCapability -> noCap + SMethod_Initialize -> noCap + SMethod_Initialized -> noCap + SMethod_Shutdown -> noCap + SMethod_Exit -> noCap + SMethod_WorkspaceApplyEdit -> noCap + SMethod_TelemetryEvent -> noCap + SMethod_SetTrace -> noCap + SMethod_LogTrace -> noCap + SMethod_CancelRequest -> noCap + (SMethod_CustomMethod _s) -> noCap + where + fileOps :: Lens' ServerCapabilities (Maybe FileOperationOptions) + fileOps = L.workspace . non emptyWorkspaceServerCaps . L.fileOperations + documentSync :: Lens' ServerCapabilities (Maybe DocumentSyncCaps) + documentSync = L.textDocumentSync + notebookDocumentSync :: Lens' ServerCapabilities (Maybe NotebookDocumentSyncCaps) + notebookDocumentSync = L.notebookDocumentSync + +noCap :: Lens' a (Maybe Void) +noCap = lens g s + where + g _ = Nothing + s a Nothing = a + s _ (Just v) = absurd v + +-- TODO: this is silly +emptyWorkspaceClientCaps :: WorkspaceClientCapabilities +emptyWorkspaceClientCaps = WorkspaceClientCapabilities Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing +emptyWindowClientCaps :: WindowClientCapabilities +emptyWindowClientCaps = WindowClientCapabilities Nothing Nothing Nothing +emptyTextDocumentClientCaps :: TextDocumentClientCapabilities +emptyTextDocumentClientCaps = TextDocumentClientCapabilities Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing +emptyNotebookDocumentClientCaps :: NotebookDocumentClientCapabilities +emptyNotebookDocumentClientCaps = NotebookDocumentClientCapabilities (NotebookDocumentSyncClientCapabilities Nothing Nothing) + +emptyWorkspaceServerCaps :: WorkspaceOptions +emptyWorkspaceServerCaps = WorkspaceOptions Nothing Nothing + +{- Note [Capability mappings] +Sadly these are all manually defined as we don't have the information in the metamodel to do them automatically. +-} diff --git a/lsp-types/src/Language/LSP/Protocol/Message/Registration.hs b/lsp-types/src/Language/LSP/Protocol/Message/Registration.hs index 0b4ad44bc..23d606b44 100644 --- a/lsp-types/src/Language/LSP/Protocol/Message/Registration.hs +++ b/lsp-types/src/Language/LSP/Protocol/Message/Registration.hs @@ -1,6 +1,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-} module Language.LSP.Protocol.Message.Registration where @@ -17,7 +18,7 @@ import Data.Text qualified as T import GHC.Generics import Prettyprinter --- | Typed registration type, with correct options. +-- | Typed dynamic registration type, with correct options. data TRegistration (m :: Method ClientToServer t) = TRegistration { _id :: Text -- ^ The id used to register the request. The id can be used to deregister @@ -76,7 +77,7 @@ toSomeRegistration r = -- --------------------------------------------------------------------- --- | Typed unregistration type. +-- | Typed dynamic unregistration type. data TUnregistration (m :: Method ClientToServer t) = TUnregistration { _id :: Text -- ^ The id used to unregister the request or notification. Usually an id diff --git a/lsp-types/test/CapabilitiesSpec.hs b/lsp-types/test/CapabilitiesSpec.hs index e09aa6b6d..3b984f685 100644 --- a/lsp-types/test/CapabilitiesSpec.hs +++ b/lsp-types/test/CapabilitiesSpec.hs @@ -1,19 +1,11 @@ -{-# LANGUAGE DuplicateRecordFields #-} -{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} - module CapabilitiesSpec where import Language.LSP.Protocol.Capabilities -import Language.LSP.Protocol.Types +import Prettyprinter import Test.Hspec +import Test.Hspec.Golden spec :: Spec spec = describe "capabilities" $ do - it "gives 3.10 capabilities" $ - let ClientCapabilities{_textDocument = Just tdcs} = capsForVersion (LSPVersion 3 10) - Just (DocumentSymbolClientCapabilities{_hierarchicalDocumentSymbolSupport = mHierarchical}) = _documentSymbol tdcs - in mHierarchical `shouldBe` Just True - it "gives pre 3.10 capabilities" $ - let ClientCapabilities{_textDocument = Just tdcs} = capsForVersion (LSPVersion 3 9) - Just (DocumentSymbolClientCapabilities{_hierarchicalDocumentSymbolSupport = mHierarchical}) = _documentSymbol tdcs - in mHierarchical `shouldBe` Nothing + it "produces full latest client capabilities" $ defaultGolden "fullCaps" $ show $ pretty fullLatestClientCaps + it "produces pre-3.10 client capabilities" $ defaultGolden "oldCaps" $ show $ pretty $ fullClientCapsForVersion (LSPVersion 3 9)