Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 503b4bd

Browse files
authored
Refactor backtick aware completion (#1377)
1 parent 22a61da commit 503b4bd

File tree

1 file changed

+50
-33
lines changed

1 file changed

+50
-33
lines changed

src/Haskell/Ide/Engine/LSP/Completions.hs

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ import Haskell.Ide.Engine.PluginUtils
5858
import Haskell.Ide.Engine.Context
5959

6060
data CompItem = CI
61-
{ origName :: Name
62-
, importedFrom :: T.Text
63-
, thingType :: Maybe Type
64-
, label :: T.Text
65-
, isInfix :: Maybe Backtick
61+
{ origName :: Name -- ^ Original name, such as Maybe, //, or find.
62+
, importedFrom :: T.Text -- ^ From where this item is imported from.
63+
, thingType :: Maybe Type -- ^ Available type information.
64+
, label :: T.Text -- ^ Label to display to the user.
65+
, isInfix :: Maybe Backtick -- ^ Did the completion happen
66+
-- in the context of an infix notation.
6667
}
6768

6869
data Backtick = Surrounded | LeftSide
@@ -210,10 +211,12 @@ instance Monoid QualCompls where
210211
mappend = (<>)
211212

212213
data CachedCompletions = CC
213-
{ allModNamesAsNS :: [T.Text]
214-
, unqualCompls :: [CompItem]
215-
, qualCompls :: QualCompls
216-
, importableModules :: [T.Text]
214+
{ allModNamesAsNS :: [T.Text] -- ^ All module names in scope.
215+
-- Prelude is a single module
216+
, unqualCompls :: [CompItem] -- ^ All Possible completion items
217+
, qualCompls :: QualCompls -- ^ Completion items associated to
218+
-- to a specific module name.
219+
, importableModules :: [T.Text] -- ^ All modules that may be imported.
217220
} deriving (Typeable)
218221

219222
-- The supported languages and extensions
@@ -341,26 +344,6 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
341344
d = T.length fullLine - T.length (stripTypeStuff partialLine)
342345
in Position l (c - d)
343346

344-
hasTrailingBacktick =
345-
if T.length fullLine <= trailingBacktickIndex
346-
then False
347-
else (fullLine `T.index` trailingBacktickIndex) == '`'
348-
349-
trailingBacktickIndex = let Position _ cursorColumn = VFS.cursorPos prefixInfo in cursorColumn
350-
351-
isUsedAsInfix = if backtickIndex < 0
352-
then False
353-
else (fullLine `T.index` backtickIndex) == '`'
354-
355-
backtickIndex =
356-
let Position _ cursorColumn = VFS.cursorPos prefixInfo
357-
prefixLength = T.length prefixText
358-
moduleLength = if prefixModule == ""
359-
then 0
360-
else T.length prefixModule + 1 {- Because of "." -}
361-
in
362-
cursorColumn - (prefixLength + moduleLength) - 1 {- Points to the first letter of either the module or prefix text -}
363-
364347
filtModNameCompls =
365348
map mkModCompl
366349
$ mapMaybe (T.stripPrefix enteredQual)
@@ -378,10 +361,7 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
378361
ctxCompls = map (\comp -> comp { isInfix = infixCompls }) ctxCompls'
379362

380363
infixCompls :: Maybe Backtick
381-
infixCompls = case (isUsedAsInfix, hasTrailingBacktick) of
382-
(True, False) -> Just LeftSide
383-
(True, True) -> Just Surrounded
384-
_ -> Nothing
364+
infixCompls = isUsedAsInfix fullLine prefixModule prefixText (VFS.cursorPos prefixInfo)
385365

386366
compls = if T.null prefixModule
387367
then unqualCompls
@@ -448,6 +428,43 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
448428
| "}" `T.isSuffixOf` fullLine = mempty
449429
| otherwise = " #-}"
450430

431+
-- ---------------------------------------------------------------------
432+
-- helper functions for infix backticks
433+
-- ---------------------------------------------------------------------
434+
435+
hasTrailingBacktick :: T.Text -> Position -> Bool
436+
hasTrailingBacktick line pos
437+
| T.length line > cursorIndex = (line `T.index` cursorIndex) == '`'
438+
| otherwise = False
439+
where cursorIndex = pos ^. J.character
440+
441+
isUsedAsInfix :: T.Text -> T.Text -> T.Text -> Position -> Maybe Backtick
442+
isUsedAsInfix line prefixMod prefixText pos
443+
| hasClosingBacktick && hasOpeningBacktick = Just Surrounded
444+
| hasOpeningBacktick = Just LeftSide
445+
| otherwise = Nothing
446+
where
447+
hasOpeningBacktick = openingBacktick line prefixMod prefixText pos
448+
hasClosingBacktick = hasTrailingBacktick line pos
449+
450+
openingBacktick :: T.Text -> T.Text -> T.Text -> Position -> Bool
451+
openingBacktick line prefixModule prefixText pos
452+
| backtickIndex < 0 = False
453+
| otherwise = (line `T.index` backtickIndex) == '`'
454+
where
455+
column = pos ^. J.character
456+
457+
backtickIndex :: Int
458+
backtickIndex =
459+
let
460+
prefixLength = T.length prefixText
461+
moduleLength = if prefixModule == ""
462+
then 0
463+
else T.length prefixModule + 1 {- Because of "." -}
464+
in
465+
-- Points to the first letter of either the module or prefix text
466+
column - (prefixLength + moduleLength) - 1
467+
451468

452469
-- ---------------------------------------------------------------------
453470

0 commit comments

Comments
 (0)