1
1
{-# LANGUAGE GADTs #-}
2
+ {-# LANGUAGE OverloadedStrings #-}
2
3
{-# LANGUAGE ScopedTypeVariables #-}
3
4
{-# LANGUAGE DataKinds #-}
4
5
{-# LANGUAGE KindSignatures #-}
10
11
{-# LANGUAGE BangPatterns #-}
11
12
{-# LANGUAGE TypeOperators #-}
12
13
{-# LANGUAGE TypeFamilies #-}
14
+ {-# LANGUAGE DeriveAnyClass #-}
15
+ {-# LANGUAGE DeriveGeneric #-}
13
16
14
17
module Ide.Types
15
18
where
16
19
17
20
import Data.Aeson hiding (defaultOptions )
21
+ import GHC.Generics
18
22
import qualified Data.Map as Map
19
23
import Data.String
20
24
import qualified Data.Text as T
21
- import Development.Shake
25
+ import Development.Shake hiding ( command )
22
26
import Ide.Plugin.Config
23
27
import Language.LSP.Types
24
28
import Language.LSP.VFS
@@ -29,6 +33,7 @@ import Text.Regex.TDFA.Text()
29
33
import Data.Dependent.Map (DMap )
30
34
import qualified Data.Dependent.Map as DMap
31
35
import Data.List.NonEmpty (NonEmpty (.. ), toList )
36
+ import qualified Data.List.NonEmpty as NE
32
37
import Data.GADT.Compare
33
38
import Data.Maybe
34
39
import Data.Semigroup
@@ -69,20 +74,49 @@ class PluginMethod m where
69
74
pluginEnabled :: SMethod m -> PluginId -> Config -> Bool
70
75
71
76
-- | How to combine responses from different plugins
72
- combineResponses :: SMethod m -> Config -> ClientCapabilities -> MessageParams m -> NonEmpty (ResponseResult m ) -> ResponseResult m
73
-
74
- default combineResponses :: Semigroup (ResponseResult m ) => SMethod m -> Config -> ClientCapabilities -> MessageParams m -> NonEmpty (ResponseResult m ) -> ResponseResult m
75
- combineResponses _method _config _caps _params = sconcat
77
+ combineResponses
78
+ :: SMethod m
79
+ -> T. Text -- ^ the process id, to make commands
80
+ -> Config -- ^ IDE Configuration
81
+ -> ClientCapabilities
82
+ -> MessageParams m
83
+ -> NonEmpty (ResponseResult m ) -> ResponseResult m
84
+
85
+ default combineResponses :: Semigroup (ResponseResult m )
86
+ => SMethod m -> T. Text -> Config -> ClientCapabilities -> MessageParams m -> NonEmpty (ResponseResult m) -> ResponseResult m
87
+ combineResponses _method _pid _config _caps _params = sconcat
76
88
77
89
instance PluginMethod TextDocumentCodeAction where
78
90
pluginEnabled _ = pluginEnabledConfig plcCodeActionsOn
91
+ combineResponses _method pid _config (ClientCapabilities _ textDocCaps _ _) (CodeActionParams _ _ docId range context) resps =
92
+ fmap compat $ List $ filter wasRequested $ (\ (List x) -> x) $ sconcat resps
93
+ where
94
+
95
+ compat :: (Command |? CodeAction ) -> (Command |? CodeAction )
96
+ compat x@ (InL _) = x
97
+ compat x@ (InR action)
98
+ | Just _ <- textDocCaps >>= _codeAction >>= _codeActionLiteralSupport
99
+ = x
100
+ | otherwise = InL cmd
101
+ where
102
+ cmd = mkLspCommand' pid " hls" " fallbackCodeAction" (action ^. title) (Just cmdParams)
103
+ cmdParams = [toJSON (FallbackCodeActionParams (action ^. edit) (action ^. command))]
104
+
105
+ wasRequested :: (Command |? CodeAction ) -> Bool
106
+ wasRequested (InL _) = True
107
+ wasRequested (InR ca)
108
+ | Nothing <- _only context = True
109
+ | Just (List allowed) <- _only context
110
+ , Just caKind <- ca ^. kind = caKind `elem` allowed
111
+ | otherwise = False
112
+
79
113
instance PluginMethod TextDocumentCodeLens where
80
114
pluginEnabled _ = pluginEnabledConfig plcCodeLensOn
81
115
instance PluginMethod TextDocumentRename where
82
116
pluginEnabled _ = pluginEnabledConfig plcRenameOn
83
117
instance PluginMethod TextDocumentHover where
84
118
pluginEnabled _ = pluginEnabledConfig plcHoverOn
85
- combineResponses _ _ _ _ (catMaybes . toList -> hs) = h
119
+ combineResponses _ _ _ _ _ (catMaybes . toList -> hs) = h
86
120
where
87
121
r = listToMaybe $ mapMaybe (^. range) hs
88
122
h = case foldMap (^. contents) hs of
@@ -91,7 +125,7 @@ instance PluginMethod TextDocumentHover where
91
125
92
126
instance PluginMethod TextDocumentDocumentSymbol where
93
127
pluginEnabled _ = pluginEnabledConfig plcSymbolsOn
94
- combineResponses _ _ (ClientCapabilities _ tdc _ _) params xs = res
128
+ combineResponses _ _ _ (ClientCapabilities _ tdc _ _) params xs = res
95
129
where
96
130
uri' = params ^. textDocument . uri
97
131
supportsHierarchy = Just True == (tdc >>= _documentSymbol >>= _hierarchicalDocumentSymbolSupport)
@@ -113,7 +147,7 @@ instance PluginMethod TextDocumentDocumentSymbol where
113
147
114
148
instance PluginMethod TextDocumentCompletion where
115
149
pluginEnabled _ = pluginEnabledConfig plcCompletionOn
116
- combineResponses _ conf _ _ (toList -> xs) = consumeCompletionResponse limit $ combine xs
150
+ combineResponses _ _ conf _ _ (toList -> xs) = snd $ consumeCompletionResponse limit $ combine xs
117
151
where
118
152
limit = maxCompletions conf
119
153
combine :: [List CompletionItem |? CompletionList ] -> ((List CompletionItem ) |? CompletionList )
@@ -126,12 +160,19 @@ instance PluginMethod TextDocumentCompletion where
126
160
go comp acc (InR (CompletionList comp' (List ls)) : rest) =
127
161
go (comp && comp') (acc <> DList. fromList ls) rest
128
162
163
+ -- boolean disambiguators
164
+ isCompleteResponse , isIncompleteResponse :: Bool
165
+ isIncompleteResponse = True
166
+ isCompleteResponse = False
167
+
129
168
consumeCompletionResponse limit it@ (InR (CompletionList _ (List xx))) =
130
169
case splitAt limit xx of
131
- (_, [] ) -> it
132
- (xx', _) -> InR (CompletionList False (List xx'))
170
+ -- consumed all the items, return the result as is
171
+ (_, [] ) -> (limit - length xx, it)
172
+ -- need to crop the response, set the 'isIncomplete' flag
173
+ (xx', _) -> (0 , InR (CompletionList isIncompleteResponse (List xx')))
133
174
consumeCompletionResponse n (InL (List xx)) =
134
- consumeCompletionResponse n (InR (CompletionList False (List xx)))
175
+ consumeCompletionResponse n (InR (CompletionList isCompleteResponse (List xx)))
135
176
136
177
instance PluginMethod TextDocumentFormatting where
137
178
type ExtraParams TextDocumentFormatting = (FormattingType , T. Text )
@@ -142,7 +183,7 @@ instance PluginMethod TextDocumentFormatting where
142
183
Nothing -> pure $ Left $ responseError $ T. pack $ " Formatter plugin: could not get file contents for " ++ show uri
143
184
144
185
pluginEnabled _ pid conf = (PluginId $ formattingProvider conf) == pid
145
- combineResponses _ _ _ _ (x :| _) = x
186
+ combineResponses _ _ _ _ _ (x :| _) = x
146
187
147
188
instance PluginMethod TextDocumentRangeFormatting where
148
189
type ExtraParams TextDocumentRangeFormatting = (FormattingType , T. Text )
@@ -153,7 +194,7 @@ instance PluginMethod TextDocumentRangeFormatting where
153
194
Nothing -> pure $ Left $ responseError $ T. pack $ " Formatter plugin: could not get file contents for " ++ show uri
154
195
155
196
pluginEnabled _ pid conf = (PluginId $ formattingProvider conf) == pid
156
- combineResponses _ _ _ _ (x :| _) = x
197
+ combineResponses _ _ _ _ _ (x :| _) = x
157
198
158
199
-- | Methods which have a PluginMethod instance
159
200
data IdeMethod (m :: Method FromClient Request ) = PluginMethod m => IdeMethod (SMethod m )
@@ -254,4 +295,25 @@ data FormattingType = FormatText
254
295
responseError :: T. Text -> ResponseError
255
296
responseError txt = ResponseError InvalidParams txt Nothing
256
297
298
+ -- ---------------------------------------------------------------------
299
+
300
+ data FallbackCodeActionParams =
301
+ FallbackCodeActionParams
302
+ { fallbackWorkspaceEdit :: Maybe WorkspaceEdit
303
+ , fallbackCommand :: Maybe Command
304
+ }
305
+ deriving (Generic , ToJSON , FromJSON )
306
+
307
+ -- ---------------------------------------------------------------------
308
+
309
+ mkLspCommand' :: T. Text -> PluginId -> CommandId -> T. Text -> Maybe [Value ] -> Command
310
+ mkLspCommand' pid plid cn title args' = Command title cmdId args
311
+ where
312
+ cmdId = mkLspCmdId pid plid cn
313
+ args = List <$> args'
314
+
315
+ mkLspCmdId :: T. Text -> PluginId -> CommandId -> T. Text
316
+ mkLspCmdId pid (PluginId plid) (CommandId cid)
317
+ = pid <> " :" <> plid <> " :" <> cid
318
+
257
319
0 commit comments