10
10
-- | Provides code actions to add missing pragmas (whenever GHC suggests to)
11
11
module Ide.Plugin.Pragmas
12
12
( descriptor
13
+ -- For testing
14
+ , validPragmas
13
15
) where
14
16
15
- import Control.Applicative ((<|>) )
16
- import Control.Lens hiding (List )
17
- import Control.Monad (join )
18
- import Control.Monad.IO.Class (MonadIO (liftIO ))
19
- import Control.Monad.Trans.State.Strict (State )
20
- import Data.Bits (Bits (bit , complement , setBit , (.&.) ))
21
- import Data.Char (isSpace )
22
- import qualified Data.Char as Char
23
- import Data.Coerce (coerce )
24
- import Data.Functor (void , ($>) )
25
- import qualified Data.HashMap.Strict as H
26
- import qualified Data.List as List
27
- import Data.List.Extra (nubOrdOn )
28
- import qualified Data.Map.Strict as Map
29
- import Data.Maybe (catMaybes , listToMaybe ,
30
- mapMaybe )
31
- import qualified Data.Maybe as Maybe
32
- import Data.Ord (Down (Down ))
33
- import Data.Semigroup (Semigroup ((<>) ))
34
- import qualified Data.Text as T
35
- import Data.Word (Word64 )
36
- import Development.IDE as D (Diagnostic (Diagnostic , _code , _message ),
37
- GhcSession (GhcSession ),
38
- HscEnvEq (hscEnv ),
39
- IdeState , List (List ),
40
- ParseResult (POk ),
41
- Position (Position ),
42
- Range (Range ), Uri ,
43
- getFileContents ,
44
- getParsedModule ,
45
- printOutputable , runAction ,
46
- srcSpanToRange ,
47
- toNormalizedUri ,
48
- uriToFilePath' ,
49
- useWithStale )
17
+ import Control.Lens hiding (List )
18
+ import Control.Monad.IO.Class (MonadIO (liftIO ))
19
+ import qualified Data.HashMap.Strict as H
20
+ import Data.List.Extra (nubOrdOn )
21
+ import Data.Maybe (catMaybes )
22
+ import qualified Data.Text as T
23
+ import Development.IDE
50
24
import Development.IDE.GHC.Compat
51
- import Development.IDE.GHC.Compat.Util (StringBuffer , atEnd ,
52
- nextChar ,
53
- stringToStringBuffer )
54
- import qualified Development.IDE.Spans.Pragmas as Pragmas
55
- import Development.IDE.Types.HscEnvEq (HscEnvEq , hscEnv )
25
+ import qualified Development.IDE.Spans.Pragmas as Pragmas
56
26
import Ide.Types
57
- import qualified Language.LSP.Server as LSP
58
- import qualified Language.LSP.Types as J
59
- import qualified Language.LSP.Types.Lens as J
60
- import qualified Language.LSP.VFS as VFS
61
- import qualified Text.Fuzzy as Fuzzy
27
+ import qualified Language.LSP.Server as LSP
28
+ import qualified Language.LSP.Types as J
29
+ import qualified Language.LSP.Types.Lens as J
30
+ import qualified Language.LSP.VFS as VFS
31
+ import qualified Text.Fuzzy as Fuzzy
62
32
63
33
-- ---------------------------------------------------------------------
64
34
@@ -193,7 +163,9 @@ allPragmas =
193
163
-- Language Version Extensions
194
164
, " Haskell98"
195
165
, " Haskell2010"
196
- -- Maybe, GHC 2021 after its release?
166
+ #if MIN_VERSION_ghc(9,2,0)
167
+ , " GHC2021"
168
+ #endif
197
169
]
198
170
199
171
-- ---------------------------------------------------------------------
@@ -214,59 +186,67 @@ completion _ide _ complParams = do
214
186
= J. List $ map buildCompletion
215
187
(Fuzzy. simpleFilter (VFS. prefixText pfix) allPragmas)
216
188
| " {-# options_ghc" `T.isPrefixOf` line
217
- = J. List $ map mkExtCompl
189
+ = J. List $ map buildCompletion
218
190
(Fuzzy. simpleFilter (VFS. prefixText pfix) flags)
219
191
| " {-#" `T.isPrefixOf` line
220
- = J. List $ map (\ (a, b, c) -> mkPragmaCompl (a <> suffix) b c) validPragmas
192
+ = J. List $ [ mkPragmaCompl (a <> suffix) b c
193
+ | (a, b, c, w) <- validPragmas, w == NewLine ]
221
194
| otherwise
222
- = J. List []
195
+ = J. List $ [ mkPragmaCompl (prefix <> a <> suffix) b c
196
+ | (a, b, c, _) <- validPragmas, Fuzzy. test word b]
223
197
where
224
198
line = T. toLower $ VFS. fullLine pfix
199
+ word = VFS. prefixText pfix
200
+ -- Not completely correct, may fail if more than one "{-#" exist
201
+ -- , we can ignore it since it rarely happen.
202
+ prefix
203
+ | " {-# " `T.isInfixOf` line = " "
204
+ | " {-#" `T.isInfixOf` line = " "
205
+ | otherwise = " {-# "
225
206
suffix
226
- | " #-}" `T.isSuffixOf` line = " "
227
- | " -}" `T.isSuffixOf` line = " #"
228
- | " }" `T.isSuffixOf` line = " #-"
207
+ | " #-}" `T.isSuffixOf` line = " "
208
+ | " #-}" `T.isSuffixOf` line = " "
209
+ | " -}" `T.isSuffixOf` line = " #"
210
+ | " }" `T.isSuffixOf` line = " #-"
229
211
| otherwise = " #-}"
230
212
result Nothing = J. List []
231
- buildCompletion p =
232
- J. CompletionItem
233
- { _label = p,
234
- _kind = Just J. CiKeyword ,
235
- _tags = Nothing ,
236
- _detail = Nothing ,
237
- _documentation = Nothing ,
238
- _deprecated = Nothing ,
239
- _preselect = Nothing ,
240
- _sortText = Nothing ,
241
- _filterText = Nothing ,
242
- _insertText = Nothing ,
243
- _insertTextFormat = Nothing ,
244
- _insertTextMode = Nothing ,
245
- _textEdit = Nothing ,
246
- _additionalTextEdits = Nothing ,
247
- _commitCharacters = Nothing ,
248
- _command = Nothing ,
249
- _xdata = Nothing
250
- }
251
213
_ -> return $ J. List []
252
214
253
215
-----------------------------------------------------------------------
254
- validPragmas :: [(T. Text , T. Text , T. Text )]
216
+
217
+ -- | Pragma where exist
218
+ data AppearWhere =
219
+ NewLine
220
+ -- ^ Must be on a new line
221
+ | CanInline
222
+ -- ^ Can appear in the line
223
+ deriving (Show , Eq )
224
+
225
+ validPragmas :: [(T. Text , T. Text , T. Text , AppearWhere )]
255
226
validPragmas =
256
- [ (" LANGUAGE ${1:extension}" , " LANGUAGE" , " {-# LANGUAGE #-}" )
257
- , (" OPTIONS_GHC -${1:option}" , " OPTIONS_GHC" , " {-# OPTIONS_GHC #-}" )
258
- , (" INLINE ${1:function}" , " INLINE" , " {-# INLINE #-}" )
259
- , (" NOINLINE ${1:function}" , " NOINLINE" , " {-# NOINLINE #-}" )
260
- , (" INLINABLE ${1:function}" , " INLINABLE" , " {-# INLINABLE #-}" )
261
- , (" WARNING ${1:message}" , " WARNING" , " {-# WARNING #-}" )
262
- , (" DEPRECATED ${1:message}" , " DEPRECATED" , " {-# DEPRECATED #-}" )
263
- , (" ANN ${1:annotation}" , " ANN" , " {-# ANN #-}" )
264
- , (" RULES" , " RULES" , " {-# RULES #-}" )
265
- , (" SPECIALIZE ${1:function}" , " SPECIALIZE" , " {-# SPECIALIZE #-}" )
266
- , (" SPECIALIZE INLINE ${1:function}" , " SPECIALIZE INLINE" , " {-# SPECIALIZE INLINE #-}" )
227
+ [ (" LANGUAGE ${1:extension}" , " LANGUAGE" , " {-# LANGUAGE #-}" , NewLine )
228
+ , (" OPTIONS_GHC -${1:option}" , " OPTIONS_GHC" , " {-# OPTIONS_GHC #-}" , NewLine )
229
+ , (" INLINE ${1:function}" , " INLINE" , " {-# INLINE #-}" , NewLine )
230
+ , (" NOINLINE ${1:function}" , " NOINLINE" , " {-# NOINLINE #-}" , NewLine )
231
+ , (" INLINABLE ${1:function}" , " INLINABLE" , " {-# INLINABLE #-}" , NewLine )
232
+ , (" WARNING ${1:message}" , " WARNING" , " {-# WARNING #-}" , CanInline )
233
+ , (" DEPRECATED ${1:message}" , " DEPRECATED" , " {-# DEPRECATED #-}" , CanInline )
234
+ , (" ANN ${1:annotation}" , " ANN" , " {-# ANN #-}" , NewLine )
235
+ , (" RULES" , " RULES" , " {-# RULES #-}" , NewLine )
236
+ , (" SPECIALIZE ${1:function}" , " SPECIALIZE" , " {-# SPECIALIZE #-}" , NewLine )
237
+ , (" SPECIALIZE INLINE ${1:function}" , " SPECIALIZE INLINE" , " {-# SPECIALIZE INLINE #-}" , NewLine )
238
+ , (" SPECIALISE ${1:function}" , " SPECIALISE" , " {-# SPECIALISE #-}" , NewLine )
239
+ , (" SPECIALISE INLINE ${1:function}" , " SPECIALISE INLINE" , " {-# SPECIALISE INLINE #-}" , NewLine )
240
+ , (" MINIMAL ${1:functions}" , " MINIMAL" , " {-# MINIMAL #-}" , CanInline )
241
+ , (" UNPACK" , " UNPACK" , " {-# UNPACK #-}" , CanInline )
242
+ , (" NOUNPACK" , " NOUNPACK" , " {-# NOUNPACK #-}" , CanInline )
243
+ , (" COMPLETE ${1:function}" , " COMPLETE" , " {-# COMPLETE #-}" , NewLine )
244
+ , (" OVERLAPPING" , " OVERLAPPING" , " {-# OVERLAPPING #-}" , CanInline )
245
+ , (" OVERLAPPABLE" , " OVERLAPPABLE" , " {-# OVERLAPPABLE #-}" , CanInline )
246
+ , (" OVERLAPS" , " OVERLAPS" , " {-# OVERLAPS #-}" , CanInline )
247
+ , (" INCOHERENT" , " INCOHERENT" , " {-# INCOHERENT #-}" , CanInline )
267
248
]
268
249
269
-
270
250
mkPragmaCompl :: T. Text -> T. Text -> T. Text -> J. CompletionItem
271
251
mkPragmaCompl insertText label detail =
272
252
J. CompletionItem label (Just J. CiKeyword ) Nothing (Just detail)
@@ -281,8 +261,8 @@ stripLeading c (s:ss)
281
261
| otherwise = s: ss
282
262
283
263
284
- mkExtCompl :: T. Text -> J. CompletionItem
285
- mkExtCompl label =
264
+ buildCompletion :: T. Text -> J. CompletionItem
265
+ buildCompletion label =
286
266
J. CompletionItem label (Just J. CiKeyword ) Nothing Nothing
287
267
Nothing Nothing Nothing Nothing Nothing Nothing Nothing
288
268
Nothing Nothing Nothing Nothing Nothing Nothing
0 commit comments