@@ -21,28 +21,23 @@ import Control.Monad.Trans.Class (lift)
21
21
import Data.Char (isAlphaNum )
22
22
import Data.List.Extra (nubOrdOn )
23
23
import qualified Data.Map as M
24
- import Data.Maybe (fromMaybe ,
25
- listToMaybe ,
26
- mapMaybe )
24
+ import Data.Maybe (mapMaybe )
27
25
import qualified Data.Text as T
28
- import qualified Data.Text.Utf16.Rope.Mixed as Rope
29
26
import Development.IDE hiding (line )
30
27
import Development.IDE.Core.Compile (sourceParser ,
31
28
sourceTypecheck )
32
29
import Development.IDE.Core.PluginUtils
33
30
import Development.IDE.GHC.Compat
34
31
import Development.IDE.Plugin.Completions (ghcideCompletionsPluginPriority )
35
32
import Development.IDE.Plugin.Completions.Logic (getCompletionPrefix )
36
- import Development.IDE.Plugin.Completions.Types (PosPrefixInfo (.. ),
37
- prefixText )
33
+ import Development.IDE.Plugin.Completions.Types (PosPrefixInfo (.. ))
38
34
import qualified Development.IDE.Spans.Pragmas as Pragmas
39
35
import Ide.Plugin.Error
40
36
import Ide.Types
41
37
import qualified Language.LSP.Protocol.Lens as L
42
38
import qualified Language.LSP.Protocol.Message as LSP
43
39
import qualified Language.LSP.Protocol.Types as LSP
44
40
import qualified Language.LSP.Server as LSP
45
- import qualified Language.LSP.VFS as VFS
46
41
import qualified Text.Fuzzy as Fuzzy
47
42
48
43
-- ---------------------------------------------------------------------
@@ -135,7 +130,6 @@ suggestDisableWarning Diagnostic {_code}
135
130
136
131
-- Don't suggest disabling type errors as a solution to all type errors
137
132
warningBlacklist :: [T. Text ]
138
- -- warningBlacklist = []
139
133
warningBlacklist = [" deferred-type-errors" ]
140
134
141
135
-- ---------------------------------------------------------------------
@@ -204,26 +198,26 @@ flags = map T.pack $ flagsForCompletion False
204
198
completion :: PluginMethodHandler IdeState 'LSP.Method_TextDocumentCompletion
205
199
completion _ide _ complParams = do
206
200
let (LSP. TextDocumentIdentifier uri) = complParams ^. L. textDocument
207
- cursorPos @ (Position l c ) = complParams ^. L. position
201
+ position @ (Position ln col ) = complParams ^. L. position
208
202
contents <- lift $ LSP. getVirtualFile $ toNormalizedUri uri
209
203
fmap LSP. InL $ case (contents, uriToFilePath' uri) of
210
204
(Just cnts, Just _path) ->
211
- pure $ result $ getCompletionPrefix cursorPos cnts
205
+ pure $ result $ getCompletionPrefix position cnts
212
206
where
213
207
result pfix
214
208
| " {-# language" `T.isPrefixOf` line
215
209
= map mkLanguagePragmaCompl $
216
- Fuzzy. simpleFilter (prefixText pfix) allPragmas
210
+ Fuzzy. simpleFilter word allPragmas
217
211
| " {-# options_ghc" `T.isPrefixOf` line
218
- = let flagPrefix = getGhcOptionPrefix cursorPos cnts
219
- prefixLength = fromIntegral $ T. length flagPrefix
220
- prefixRange = LSP. Range (Position l (c - prefixLength)) cursorPos
221
- in map (mkGhcOptionCompl prefixRange) $ Fuzzy. simpleFilter flagPrefix flags
212
+ = let optionPrefix = getGhcOptionPrefix pfix
213
+ prefixLength = fromIntegral $ T. length optionPrefix
214
+ prefixRange = LSP. Range (Position ln (col - prefixLength)) position
215
+ in map (mkGhcOptionCompl prefixRange) $ Fuzzy. simpleFilter optionPrefix flags
222
216
| " {-#" `T.isPrefixOf` line
223
217
= [ mkPragmaCompl (a <> suffix) b c
224
218
| (a, b, c, w) <- validPragmas, w == NewLine
225
219
]
226
- | -- Do not suggest any pragmas any of these conditions:
220
+ | -- Do not suggest any pragmas under any of these conditions:
227
221
-- 1. Current line is an import
228
222
-- 2. There is a module name right before the current word.
229
223
-- Something like `Text.la` shouldn't suggest adding the
@@ -234,20 +228,21 @@ completion _ide _ complParams = do
234
228
| otherwise
235
229
= [ mkPragmaCompl (prefix <> pragmaTemplate <> suffix) matcher detail
236
230
| (pragmaTemplate, matcher, detail, appearWhere) <- validPragmas
237
- , -- Only suggest a pragma that needs its own line if the whole line
238
- -- fuzzily matches the pragma
239
- (appearWhere == NewLine && Fuzzy. test line matcher ) ||
240
- -- Only suggest a pragma that appears in the middle of a line when
241
- -- the current word is not the only thing in the line and the
242
- -- current word fuzzily matches the pragma
243
- (appearWhere == CanInline && line /= word && Fuzzy. test word matcher)
231
+ , case appearWhere of
232
+ -- Only suggest a pragma that needs its own line if the whole line
233
+ -- fuzzily matches the pragma
234
+ NewLine -> Fuzzy. test line matcher
235
+ -- Only suggest a pragma that appears in the middle of a line when
236
+ -- the current word is not the only thing in the line and the
237
+ -- current word fuzzily matches the pragma
238
+ CanInline -> line /= word && Fuzzy. test word matcher
244
239
]
245
240
where
246
241
line = T. toLower $ fullLine pfix
247
242
module_ = prefixScope pfix
248
243
word = prefixText pfix
249
- -- Not completely correct, may fail if more than one "{-#" exist
250
- -- , we can ignore it since it rarely happens.
244
+ -- Not completely correct, may fail if more than one "{-#" exist.
245
+ -- We can ignore it since it rarely happens.
251
246
prefix
252
247
| " {-# " `T.isInfixOf` line = " "
253
248
| " {-#" `T.isInfixOf` line = " "
@@ -301,30 +296,6 @@ mkPragmaCompl insertText label detail =
301
296
Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just LSP. InsertTextFormat_Snippet )
302
297
Nothing Nothing Nothing Nothing Nothing Nothing Nothing
303
298
304
- getGhcOptionPrefix :: Position -> VFS. VirtualFile -> T. Text
305
- getGhcOptionPrefix (Position l c) (VFS. VirtualFile _ _ ropetext) =
306
- fromMaybe " " $ do
307
- let lastMaybe = listToMaybe . reverse
308
-
309
- -- grab the entire line the cursor is at
310
- curLine <- listToMaybe
311
- $ Rope. lines
312
- $ fst $ Rope. splitAtLine 1
313
- $ snd $ Rope. splitAtLine (fromIntegral l) ropetext
314
- let beforePos = T. take (fromIntegral c) curLine
315
- -- the word getting typed, after previous space and before cursor
316
- curWord <-
317
- if | T. null beforePos -> Just " "
318
- | T. last beforePos == ' ' -> Just " " -- don't count abc as the curword in 'abc '
319
- | otherwise -> lastMaybe (T. words beforePos)
320
- pure $ T. takeWhileEnd isGhcOptionChar curWord
321
-
322
- -- | Is this character contained in some GHC flag? Based on:
323
- -- GHCi> nub . sort . concat $ GHC.Driver.Session.flagsForCompletion False
324
- -- "#-.01234589=ABCDEFGHIJKLMNOPQRSTUVWX_abcdefghijklmnopqrstuvwxyz"
325
- isGhcOptionChar :: Char -> Bool
326
- isGhcOptionChar c = isAlphaNum c || c `elem` (" #-.=_" :: String )
327
-
328
299
mkLanguagePragmaCompl :: T. Text -> LSP. CompletionItem
329
300
mkLanguagePragmaCompl label =
330
301
LSP. CompletionItem label Nothing (Just LSP. CompletionItemKind_Keyword ) Nothing Nothing
@@ -339,5 +310,18 @@ mkGhcOptionCompl editRange completedFlag =
339
310
where
340
311
insertCompleteFlag = LSP. InL $ LSP. TextEdit editRange completedFlag
341
312
313
+ -- The prefix extraction logic of getCompletionPrefix
314
+ -- doesn't consider '-' part of prefix which breaks completion
315
+ -- of flags like "-ddump-xyz". For OPTIONS_GHC completion we need the whole thing
316
+ -- to be considered completion prefix, but `prefixText posPrefixInfo` would return"xyz" in this case
317
+ getGhcOptionPrefix :: PosPrefixInfo -> T. Text
318
+ getGhcOptionPrefix PosPrefixInfo {cursorPos = Position _ col, fullLine}=
319
+ T. takeWhileEnd isGhcOptionChar beforePos
320
+ where
321
+ beforePos = T. take (fromIntegral col) fullLine
342
322
343
-
323
+ -- Is this character contained in some GHC flag? Based on:
324
+ -- >>> nub . sort . concat $ GHC.Driver.Session.flagsForCompletion False
325
+ -- "#-.01234589=ABCDEFGHIJKLMNOPQRSTUVWX_abcdefghijklmnopqrstuvwxyz"
326
+ isGhcOptionChar :: Char -> Bool
327
+ isGhcOptionChar c = isAlphaNum c || c `elem` (" #-.=_" :: String )
0 commit comments