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

Commit ef51319

Browse files
committed
Support infix completions
1 parent 33d4581 commit ef51319

File tree

1 file changed

+51
-9
lines changed

1 file changed

+51
-9
lines changed

src/Haskell/Ide/Engine/Support/HieExtras.hs

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import SrcLoc
7575
import TcEnv
7676
import Type
7777
import Var
78+
import System.IO (hPutStrLn, stderr)
7879

7980
-- ---------------------------------------------------------------------
8081

@@ -103,13 +104,16 @@ data CompItem = CI
103104
, importedFrom :: T.Text
104105
, thingType :: Maybe Type
105106
, label :: T.Text
107+
, isInfix :: Maybe Backtick
106108
}
107109

110+
data Backtick = Surrounded | LeftSide
111+
108112
instance Eq CompItem where
109-
(CI n1 _ _ _) == (CI n2 _ _ _) = n1 == n2
113+
ci1 == ci2 = origName ci1 == origName ci2
110114

111115
instance Ord CompItem where
112-
compare (CI n1 _ _ _) (CI n2 _ _ _) = compare n1 n2
116+
compare ci1 ci2 = origName ci1 `compare` origName ci2
113117

114118
occNameToComKind :: OccName -> J.CompletionItemKind
115119
occNameToComKind oc
@@ -125,16 +129,21 @@ mkQuery name importedFrom = name <> " module:" <> importedFrom
125129
<> " is:exact"
126130

127131
mkCompl :: CompItem -> J.CompletionItem
128-
mkCompl CI{origName,importedFrom,thingType,label} =
132+
mkCompl CI{origName,importedFrom,thingType,label,isInfix} =
129133
J.CompletionItem label kind (Just $ maybe "" (<>"\n") typeText <> importedFrom)
130134
Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just J.Snippet)
131135
Nothing Nothing Nothing Nothing hoogleQuery
132136
where kind = Just $ occNameToComKind $ occName origName
133137
hoogleQuery = Just $ toJSON $ mkQuery label importedFrom
134138
argTypes = maybe [] getArgs thingType
135-
insertText
136-
| [] <- argTypes = label
137-
| otherwise = label <> " " <> argText
139+
insertText = case isInfix of
140+
Nothing -> case argTypes of
141+
[] -> label
142+
_ -> label <> " " <> argText
143+
Just LeftSide -> label <> "`"
144+
145+
Just Surrounded -> label
146+
138147
argText :: T.Text
139148
argText = mconcat $ List.intersperse " " $ zipWith snippet [1..] argTypes
140149
stripForall t
@@ -224,17 +233,20 @@ instance ModuleCache CachedCompletions where
224233

225234
typeEnv = md_types $ snd $ tm_internals_ tm
226235
toplevelVars = mapMaybe safeTyThingId $ typeEnvElts typeEnv
227-
varToCompl var = CI name (showModName curMod) typ label
236+
237+
varToCompl :: Var -> CompItem
238+
varToCompl var = CI name (showModName curMod) typ label Nothing
228239
where
229240
typ = Just $ varType var
230241
name = Var.varName var
231242
label = T.pack $ showGhc name
232243

244+
toplevelCompls :: [CompItem]
233245
toplevelCompls = map varToCompl toplevelVars
234246

235247
toCompItem :: ModuleName -> Name -> CompItem
236248
toCompItem mn n =
237-
CI n (showModName mn) Nothing (T.pack $ showGhc n)
249+
CI n (showModName mn) Nothing (T.pack $ showGhc n) Nothing
238250

239251
allImportsInfo :: [(Bool, T.Text, ModuleName, Maybe (Bool, [Name]))]
240252
allImportsInfo = map getImpInfo importDeclerations
@@ -369,6 +381,26 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
369381
d = T.length fullLine - T.length (stripTypeStuff partialLine)
370382
in Position l (c - d)
371383

384+
hasTrailingBacktick =
385+
if T.length fullLine <= trailingBacktickIndex
386+
then False
387+
else (fullLine `T.index` trailingBacktickIndex) == '`'
388+
389+
trailingBacktickIndex = let Position _ cursorColumn = VFS.cursorPos prefixInfo in cursorColumn
390+
391+
isUsedAsInfix = if backtickIndex < 0
392+
then False
393+
else (fullLine `T.index` backtickIndex) == '`'
394+
395+
backtickIndex =
396+
let Position _ cursorColumn = VFS.cursorPos prefixInfo
397+
prefixLength = T.length prefixText
398+
moduleLength = if prefixModule == ""
399+
then 0
400+
else T.length prefixModule + 1 {- Because of "." -}
401+
in
402+
cursorColumn - (prefixLength + moduleLength) - 1 {- Points to the first letter of either the module or prefix text -}
403+
372404
filtModNameCompls =
373405
map mkModCompl
374406
$ mapMaybe (T.stripPrefix enteredQual)
@@ -378,13 +410,23 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
378410
where
379411
isTypeCompl = isTcOcc . occName . origName
380412
-- completions specific to the current context
381-
ctxCompls = case context of
413+
ctxCompls' = case context of
382414
TypeContext -> filter isTypeCompl compls
383415
ValueContext -> filter (not . isTypeCompl) compls
416+
-- Add whether the text to insert has backticks
417+
ctxCompls = map (\comp -> comp { isInfix = infixCompls }) ctxCompls'
418+
419+
infixCompls :: Maybe Backtick
420+
infixCompls = case (isUsedAsInfix, hasTrailingBacktick) of
421+
(True, False) -> Just LeftSide
422+
(True, True) -> Just Surrounded
423+
_ -> Nothing
424+
384425
compls = if T.null prefixModule
385426
then unqualCompls
386427
else Map.findWithDefault [] prefixModule qualCompls
387428

429+
388430
mkImportCompl label = (J.detail ?~ label) . mkModCompl $ fromMaybe
389431
""
390432
(T.stripPrefix enteredQual label)

0 commit comments

Comments
 (0)