Skip to content

Commit b484c2f

Browse files
authored
Merge pull request #314 from michaelpj/semantic-tokens
Semantic tokens support
2 parents 692b73c + f2e1956 commit b484c2f

19 files changed

+720
-23
lines changed

lsp-test/src/Language/LSP/Test.hs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,14 @@ module Language.LSP.Test
9292
, applyEdit
9393
-- ** Code lenses
9494
, getCodeLenses
95-
-- ** Capabilities
96-
, getRegisteredCapabilities
95+
-- ** Call hierarchy
9796
, prepareCallHierarchy
9897
, incomingCalls
9998
, outgoingCalls
99+
-- ** SemanticTokens
100+
, getSemanticTokens
101+
-- ** Capabilities
102+
, getRegisteredCapabilities
100103
) where
101104

102105
import Control.Applicative.Combinators
@@ -606,7 +609,7 @@ applyEdit doc edit = do
606609

607610
let supportsDocChanges = fromMaybe False $ do
608611
let mWorkspace = caps ^. LSP.workspace
609-
C.WorkspaceClientCapabilities _ mEdit _ _ _ _ _ _ <- mWorkspace
612+
C.WorkspaceClientCapabilities _ mEdit _ _ _ _ _ _ _ <- mWorkspace
610613
C.WorkspaceEditClientCapabilities mDocChanges _ _ _ _ <- mEdit
611614
mDocChanges
612615

@@ -743,13 +746,6 @@ getCodeLenses tId = do
743746
case getResponseResult rsp of
744747
List res -> pure res
745748

746-
-- | Returns a list of capabilities that the server has requested to /dynamically/
747-
-- register during the 'Session'.
748-
--
749-
-- @since 0.11.0.0
750-
getRegisteredCapabilities :: Session [SomeRegistration]
751-
getRegisteredCapabilities = Map.elems . curDynCaps <$> get
752-
753749
-- | Pass a param and return the response from `prepareCallHierarchy`
754750
prepareCallHierarchy :: CallHierarchyPrepareParams -> Session [CallHierarchyItem]
755751
prepareCallHierarchy = resolveRequestWithListResp STextDocumentPrepareCallHierarchy
@@ -768,3 +764,17 @@ resolveRequestWithListResp method params = do
768764
case getResponseResult rsp of
769765
Nothing -> pure []
770766
Just (List x) -> pure x
767+
768+
-- | Pass a param and return the response from `prepareCallHierarchy`
769+
getSemanticTokens :: TextDocumentIdentifier -> Session (Maybe SemanticTokens)
770+
getSemanticTokens doc = do
771+
let params = SemanticTokensParams Nothing Nothing doc
772+
rsp <- request STextDocumentSemanticTokensFull params
773+
pure $ getResponseResult rsp
774+
775+
-- | Returns a list of capabilities that the server has requested to /dynamically/
776+
-- register during the 'Session'.
777+
--
778+
-- @since 0.11.0.0
779+
getRegisteredCapabilities :: Session [SomeRegistration]
780+
getRegisteredCapabilities = Map.elems . curDynCaps <$> get

lsp-test/test/DummyServer.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import System.Directory
1616
import System.FilePath
1717
import System.Process
1818
import Language.LSP.Types
19+
import Data.Default
1920

2021
withDummyServer :: ((Handle, Handle) -> IO ()) -> IO ()
2122
withDummyServer f = do
@@ -212,4 +213,9 @@ handlers =
212213
CallHierarchyOutgoingCallsParams _ _ item = params
213214
resp $ Right $ Just $
214215
List [CallHierarchyOutgoingCall item (List [Range (Position 4 5) (Position 2 3)])]
216+
, requestHandler STextDocumentSemanticTokensFull $ \_req resp -> do
217+
let tokens = makeSemanticTokens def [SemanticTokenAbsolute 0 1 2 SttType []]
218+
case tokens of
219+
Left t -> resp $ Left $ ResponseError InternalError t Nothing
220+
Right tokens -> resp $ Right $ Just tokens
215221
]

lsp-test/test/Test.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ main = hspec $ around withDummyServer $ do
394394
[CallHierarchyOutgoingCall _ (List fromRanges)] <- outgoingCalls (CallHierarchyOutgoingCallsParams Nothing Nothing item)
395395
liftIO $ head fromRanges `shouldBe` Range (Position 4 5) (Position 2 3)
396396

397+
describe "semantic tokens" $ do
398+
it "full works" $ \(hin, hout) -> runSessionWithHandles hin hout def fullCaps "." $ do
399+
let doc = TextDocumentIdentifier (Uri "")
400+
Just toks <- getSemanticTokens doc
401+
liftIO $ toks ^. xdata `shouldBe` List [0,1,2,0,0]
397402

398403
didChangeCaps :: ClientCapabilities
399404
didChangeCaps = def { _workspace = Just workspaceCaps }

lsp-types/lsp-types.cabal

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ library
5656
, Language.LSP.Types.Rename
5757
, Language.LSP.Types.SelectionRange
5858
, Language.LSP.Types.ServerCapabilities
59+
, Language.LSP.Types.SemanticTokens
5960
, Language.LSP.Types.SignatureHelp
6061
, Language.LSP.Types.StaticRegistrationOptions
6162
, Language.LSP.Types.TextDocument
@@ -76,17 +77,19 @@ library
7677
, containers
7778
, data-default
7879
, deepseq
80+
, Diff
7981
, directory
82+
, dlist
8083
, filepath
8184
, hashable
8285
, hslogger
8386
, lens >= 4.15.2
87+
, mtl
8488
, network-uri
8589
, rope-utf16-splay >= 0.3.1.0
8690
, scientific
8791
, some
8892
, dependent-sum-template
89-
, dependent-sum >= 0.6.2.2
9093
, text
9194
, template-haskell
9295
, temporary

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module Language.LSP.Types
3333
, module Language.LSP.Types.SignatureHelp
3434
, module Language.LSP.Types.StaticRegistrationOptions
3535
, module Language.LSP.Types.SelectionRange
36+
, module Language.LSP.Types.SemanticTokens
3637
, module Language.LSP.Types.TextDocument
3738
, module Language.LSP.Types.TypeDefinition
3839
, module Language.LSP.Types.Uri
@@ -76,6 +77,7 @@ import Language.LSP.Types.References
7677
import Language.LSP.Types.Registration
7778
import Language.LSP.Types.Rename
7879
import Language.LSP.Types.SelectionRange
80+
import Language.LSP.Types.SemanticTokens
7981
import Language.LSP.Types.SignatureHelp
8082
import Language.LSP.Types.StaticRegistrationOptions
8183
import Language.LSP.Types.TextDocument

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ capsForVersion (LSPVersion maj min) = ClientCapabilities (Just w) (Just td) (Jus
5151
(Just (ExecuteCommandClientCapabilities dynamicReg))
5252
(since 3 6 True)
5353
(since 3 6 True)
54+
(since 3 16 (SemanticTokensWorkspaceClientCapabilities $ Just True))
5455

5556
resourceOperations = List
5657
[ ResourceOperationCreate
@@ -103,6 +104,20 @@ capsForVersion (LSPVersion maj min) = ClientCapabilities (Just w) (Just td) (Jus
103104
, SkTypeParameter
104105
]
105106

107+
-- Only one token format for now, just list it here
108+
tfs = List [ TokenFormatRelative ]
109+
110+
semanticTokensCapabilities = SemanticTokensClientCapabilities
111+
(Just True)
112+
(SemanticTokensRequestsClientCapabilities
113+
(Just $ SemanticTokensRangeBool True)
114+
(Just (SemanticTokensFullDelta (SemanticTokensDeltaClientCapabilities $ Just True))))
115+
(List knownSemanticTokenTypes)
116+
(List knownSemanticTokenModifiers)
117+
tfs
118+
(Just True)
119+
(Just True)
120+
106121
td = TextDocumentClientCapabilities
107122
(Just sync)
108123
(Just completionCapability)
@@ -127,6 +142,8 @@ capsForVersion (LSPVersion maj min) = ClientCapabilities (Just w) (Just td) (Jus
127142
(since 3 10 foldingRangeCapability)
128143
(since 3 5 (SelectionRangeClientCapabilities dynamicReg))
129144
(since 3 16 (CallHierarchyClientCapabilities dynamicReg))
145+
(since 3 16 semanticTokensCapabilities)
146+
130147
sync =
131148
TextDocumentSyncClientCapabilities
132149
dynamicReg

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import Language.LSP.Types.Implementation
2626
import Language.LSP.Types.References
2727
import Language.LSP.Types.Rename
2828
import Language.LSP.Types.SelectionRange
29+
import Language.LSP.Types.SemanticTokens
2930
import Language.LSP.Types.SignatureHelp
3031
import Language.LSP.Types.TextDocument
3132
import Language.LSP.Types.TypeDefinition
@@ -61,12 +62,18 @@ data WorkspaceClientCapabilities =
6162

6263
-- | The client supports `workspace/configuration` requests.
6364
, _configuration :: Maybe Bool
65+
66+
-- | Capabilities specific to the semantic token requests scoped to the
67+
-- workspace.
68+
--
69+
-- @since 3.16.0
70+
, _semanticTokens :: Maybe SemanticTokensWorkspaceClientCapabilities
6471
} deriving (Show, Read, Eq)
6572

6673
deriveJSON lspOptions ''WorkspaceClientCapabilities
6774

6875
instance Default WorkspaceClientCapabilities where
69-
def = WorkspaceClientCapabilities def def def def def def def def
76+
def = WorkspaceClientCapabilities def def def def def def def def def
7077

7178
-- -------------------------------------
7279

@@ -147,14 +154,19 @@ data TextDocumentClientCapabilities =
147154
-- | Call hierarchy specific to the `textDocument/prepareCallHierarchy` request.
148155
-- Since LSP 3.16.0
149156
, _callHierarchy :: Maybe CallHierarchyClientCapabilities
157+
158+
-- | Capabilities specific to the various semantic token requests.
159+
--
160+
-- @since 3.16.0
161+
, _semanticTokens :: Maybe SemanticTokensClientCapabilities
150162
} deriving (Show, Read, Eq)
151163

152164
deriveJSON lspOptions ''TextDocumentClientCapabilities
153165

154166
instance Default TextDocumentClientCapabilities where
155167
def = TextDocumentClientCapabilities def def def def def def def def
156168
def def def def def def def def
157-
def def def def def def def
169+
def def def def def def def def
158170

159171
-- ---------------------------------------------------------------------
160172

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import Language.LSP.Types.WorkspaceEdit
5151
import Language.LSP.Types.WorkspaceFolders
5252
import Language.LSP.Types.WorkspaceSymbol
5353
import Language.LSP.Types.Message
54+
import Language.LSP.Types.SemanticTokens
5455
import Control.Lens.TH
5556

5657
-- TODO: This is out of date and very unmantainable, use TH to call all these!!
@@ -366,3 +367,15 @@ makeFieldsNoPrefix ''CallHierarchyIncomingCall
366367
makeFieldsNoPrefix ''CallHierarchyOutgoingCallsParams
367368
makeFieldsNoPrefix ''CallHierarchyOutgoingCall
368369
makeFieldsNoPrefix ''CallHierarchyItem
370+
371+
-- Semantic tokens
372+
makeFieldsNoPrefix ''SemanticTokensLegend
373+
makeFieldsNoPrefix ''SemanticTokensDeltaClientCapabilities
374+
makeFieldsNoPrefix ''SemanticTokensRequestsClientCapabilities
375+
makeFieldsNoPrefix ''SemanticTokensClientCapabilities
376+
makeFieldsNoPrefix ''SemanticTokens
377+
makeFieldsNoPrefix ''SemanticTokensPartialResult
378+
makeFieldsNoPrefix ''SemanticTokensEdit
379+
makeFieldsNoPrefix ''SemanticTokensDelta
380+
makeFieldsNoPrefix ''SemanticTokensDeltaPartialResult
381+
makeFieldsNoPrefix ''SemanticTokensWorkspaceClientCapabilities

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import Language.LSP.Types.Registration
4545
import Language.LSP.Types.Rename
4646
import Language.LSP.Types.References
4747
import Language.LSP.Types.SelectionRange
48+
import Language.LSP.Types.SemanticTokens
4849
import Language.LSP.Types.SignatureHelp
4950
import Language.LSP.Types.TextDocument
5051
import Language.LSP.Types.TypeDefinition
@@ -125,8 +126,14 @@ type family MessageParams (m :: Method f t) :: Type where
125126
MessageParams TextDocumentPrepareCallHierarchy = CallHierarchyPrepareParams
126127
MessageParams CallHierarchyIncomingCalls = CallHierarchyIncomingCallsParams
127128
MessageParams CallHierarchyOutgoingCalls = CallHierarchyOutgoingCallsParams
129+
-- Semantic tokens
130+
MessageParams TextDocumentSemanticTokens = Empty
131+
MessageParams TextDocumentSemanticTokensFull = SemanticTokensParams
132+
MessageParams TextDocumentSemanticTokensFullDelta = SemanticTokensDeltaParams
133+
MessageParams TextDocumentSemanticTokensRange = SemanticTokensRangeParams
134+
MessageParams WorkspaceSemanticTokensRefresh = Empty
128135
-- Server
129-
-- Window
136+
-- Window
130137
MessageParams WindowShowMessage = ShowMessageParams
131138
MessageParams WindowShowMessageRequest = ShowMessageRequestParams
132139
MessageParams WindowLogMessage = LogMessageParams
@@ -202,6 +209,12 @@ type family ResponseResult (m :: Method f Request) :: Type where
202209
ResponseResult TextDocumentPrepareCallHierarchy = Maybe (List CallHierarchyItem)
203210
ResponseResult CallHierarchyIncomingCalls = Maybe (List CallHierarchyIncomingCall)
204211
ResponseResult CallHierarchyOutgoingCalls = Maybe (List CallHierarchyOutgoingCall)
212+
-- Semantic tokens
213+
ResponseResult TextDocumentSemanticTokens = Empty
214+
ResponseResult TextDocumentSemanticTokensFull = Maybe SemanticTokens
215+
ResponseResult TextDocumentSemanticTokensFullDelta = Maybe (SemanticTokens |? SemanticTokensDelta)
216+
ResponseResult TextDocumentSemanticTokensRange = Maybe SemanticTokens
217+
ResponseResult WorkspaceSemanticTokensRefresh = Empty
205218
-- Custom can be either a notification or a message
206219
-- Server
207220
-- Window

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ data Method (f :: From) (t :: MethodType) where
7979
TextDocumentPrepareCallHierarchy :: Method FromClient Request
8080
CallHierarchyIncomingCalls :: Method FromClient Request
8181
CallHierarchyOutgoingCalls :: Method FromClient Request
82+
-- SemanticTokens
83+
TextDocumentSemanticTokens :: Method FromClient Request
84+
TextDocumentSemanticTokensFull :: Method FromClient Request
85+
TextDocumentSemanticTokensFullDelta :: Method FromClient Request
86+
TextDocumentSemanticTokensRange :: Method FromClient Request
87+
WorkspaceSemanticTokensRefresh :: Method FromClient Request
8288

8389
-- ServerMethods
8490
-- Window
@@ -153,6 +159,12 @@ data SMethod (m :: Method f t) where
153159
SCallHierarchyIncomingCalls :: SMethod CallHierarchyIncomingCalls
154160
SCallHierarchyOutgoingCalls :: SMethod CallHierarchyOutgoingCalls
155161

162+
STextDocumentSemanticTokens :: SMethod TextDocumentSemanticTokens
163+
STextDocumentSemanticTokensFull :: SMethod TextDocumentSemanticTokensFull
164+
STextDocumentSemanticTokensFullDelta :: SMethod TextDocumentSemanticTokensFullDelta
165+
STextDocumentSemanticTokensRange :: SMethod TextDocumentSemanticTokensRange
166+
SWorkspaceSemanticTokensRefresh :: SMethod WorkspaceSemanticTokensRefresh
167+
156168
SWindowShowMessage :: SMethod WindowShowMessage
157169
SWindowShowMessageRequest :: SMethod WindowShowMessageRequest
158170
SWindowLogMessage :: SMethod WindowLogMessage
@@ -243,6 +255,7 @@ instance FromJSON SomeClientMethod where
243255
parseJSON (A.String "workspace/didChangeWatchedFiles") = pure $ SomeClientMethod SWorkspaceDidChangeWatchedFiles
244256
parseJSON (A.String "workspace/symbol") = pure $ SomeClientMethod SWorkspaceSymbol
245257
parseJSON (A.String "workspace/executeCommand") = pure $ SomeClientMethod SWorkspaceExecuteCommand
258+
parseJSON (A.String "workspace/semanticTokens/refresh") = pure $ SomeClientMethod SWorkspaceSemanticTokensRefresh
246259
-- Document
247260
parseJSON (A.String "textDocument/didOpen") = pure $ SomeClientMethod STextDocumentDidOpen
248261
parseJSON (A.String "textDocument/didChange") = pure $ SomeClientMethod STextDocumentDidChange
@@ -278,6 +291,10 @@ instance FromJSON SomeClientMethod where
278291
parseJSON (A.String "textDocument/prepareCallHierarchy") = pure $ SomeClientMethod STextDocumentPrepareCallHierarchy
279292
parseJSON (A.String "callHierarchy/incomingCalls") = pure $ SomeClientMethod SCallHierarchyIncomingCalls
280293
parseJSON (A.String "callHierarchy/outgoingCalls") = pure $ SomeClientMethod SCallHierarchyOutgoingCalls
294+
parseJSON (A.String "textDocument/semanticTokens") = pure $ SomeClientMethod STextDocumentSemanticTokens
295+
parseJSON (A.String "textDocument/semanticTokens/full") = pure $ SomeClientMethod STextDocumentSemanticTokensFull
296+
parseJSON (A.String "textDocument/semanticTokens/full/delta") = pure $ SomeClientMethod STextDocumentSemanticTokensFullDelta
297+
parseJSON (A.String "textDocument/semanticTokens/range") = pure $ SomeClientMethod STextDocumentSemanticTokensRange
281298
parseJSON (A.String "window/workDoneProgress/cancel") = pure $ SomeClientMethod SWindowWorkDoneProgressCancel
282299
-- Cancelling
283300
parseJSON (A.String "$/cancelRequest") = pure $ SomeClientMethod SCancelRequest
@@ -338,6 +355,7 @@ instance A.ToJSON (SMethod m) where
338355
toJSON SWorkspaceDidChangeWatchedFiles = A.String "workspace/didChangeWatchedFiles"
339356
toJSON SWorkspaceSymbol = A.String "workspace/symbol"
340357
toJSON SWorkspaceExecuteCommand = A.String "workspace/executeCommand"
358+
toJSON SWorkspaceSemanticTokensRefresh = A.String "workspace/semanticTokens/refresh"
341359
-- Document
342360
toJSON STextDocumentDidOpen = A.String "textDocument/didOpen"
343361
toJSON STextDocumentDidChange = A.String "textDocument/didChange"
@@ -371,6 +389,10 @@ instance A.ToJSON (SMethod m) where
371389
toJSON STextDocumentPrepareCallHierarchy = A.String "textDocument/prepareCallHierarchy"
372390
toJSON SCallHierarchyIncomingCalls = A.String "callHierarchy/incomingCalls"
373391
toJSON SCallHierarchyOutgoingCalls = A.String "callHierarchy/outgoingCalls"
392+
toJSON STextDocumentSemanticTokens = A.String "textDocument/semanticTokens"
393+
toJSON STextDocumentSemanticTokensFull = A.String "textDocument/semanticTokens/full"
394+
toJSON STextDocumentSemanticTokensFullDelta = A.String "textDocument/semanticTokens/full/delta"
395+
toJSON STextDocumentSemanticTokensRange = A.String "textDocument/semanticTokens/range"
374396
toJSON STextDocumentDocumentLink = A.String "textDocument/documentLink"
375397
toJSON SDocumentLinkResolve = A.String "documentLink/resolve"
376398
toJSON SWindowWorkDoneProgressCancel = A.String "window/workDoneProgress/cancel"

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ splitClientMethod STextDocumentSelectionRange = IsClientReq
253253
splitClientMethod STextDocumentPrepareCallHierarchy = IsClientReq
254254
splitClientMethod SCallHierarchyIncomingCalls = IsClientReq
255255
splitClientMethod SCallHierarchyOutgoingCalls = IsClientReq
256+
splitClientMethod STextDocumentSemanticTokens = IsClientReq
257+
splitClientMethod STextDocumentSemanticTokensFull = IsClientReq
258+
splitClientMethod STextDocumentSemanticTokensFullDelta = IsClientReq
259+
splitClientMethod STextDocumentSemanticTokensRange = IsClientReq
260+
splitClientMethod SWorkspaceSemanticTokensRefresh = IsClientReq
256261
splitClientMethod SCancelRequest = IsClientNot
257262
splitClientMethod SCustomMethod{} = IsClientEither
258263

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import Language.LSP.Types.References
5050
import Language.LSP.Types.Rename
5151
import Language.LSP.Types.SignatureHelp
5252
import Language.LSP.Types.SelectionRange
53+
import Language.LSP.Types.SemanticTokens
5354
import Language.LSP.Types.TextDocument
5455
import Language.LSP.Types.TypeDefinition
5556
import Language.LSP.Types.Utils
@@ -98,6 +99,7 @@ type family RegistrationOptions (m :: Method FromClient t) :: Type where
9899
RegistrationOptions TextDocumentFoldingRange = FoldingRangeRegistrationOptions
99100
RegistrationOptions TextDocumentSelectionRange = SelectionRangeRegistrationOptions
100101
RegistrationOptions TextDocumentPrepareCallHierarchy = CallHierarchyRegistrationOptions
102+
RegistrationOptions TextDocumentSemanticTokens = SemanticTokensRegistrationOptions
101103
RegistrationOptions m = Void
102104

103105
data Registration (m :: Method FromClient t) =

0 commit comments

Comments
 (0)