@@ -75,6 +75,7 @@ import SrcLoc
75
75
import TcEnv
76
76
import Type
77
77
import Var
78
+ import System.IO (hPutStrLn , stderr )
78
79
79
80
-- ---------------------------------------------------------------------
80
81
@@ -103,13 +104,16 @@ data CompItem = CI
103
104
, importedFrom :: T. Text
104
105
, thingType :: Maybe Type
105
106
, label :: T. Text
107
+ , isInfix :: Maybe Backtick
106
108
}
107
109
110
+ data Backtick = Surrounded | LeftSide
111
+
108
112
instance Eq CompItem where
109
- ( CI n1 _ _ _) == ( CI n2 _ _ _) = n1 == n2
113
+ ci1 == ci2 = origName ci1 == origName ci2
110
114
111
115
instance Ord CompItem where
112
- compare ( CI n1 _ _ _) ( CI n2 _ _ _) = compare n1 n2
116
+ compare ci1 ci2 = origName ci1 ` compare` origName ci2
113
117
114
118
occNameToComKind :: OccName -> J. CompletionItemKind
115
119
occNameToComKind oc
@@ -125,16 +129,21 @@ mkQuery name importedFrom = name <> " module:" <> importedFrom
125
129
<> " is:exact"
126
130
127
131
mkCompl :: CompItem -> J. CompletionItem
128
- mkCompl CI {origName,importedFrom,thingType,label} =
132
+ mkCompl CI {origName,importedFrom,thingType,label,isInfix } =
129
133
J. CompletionItem label kind (Just $ maybe " " (<> " \n " ) typeText <> importedFrom)
130
134
Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just J. Snippet )
131
135
Nothing Nothing Nothing Nothing hoogleQuery
132
136
where kind = Just $ occNameToComKind $ occName origName
133
137
hoogleQuery = Just $ toJSON $ mkQuery label importedFrom
134
138
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
+
138
147
argText :: T. Text
139
148
argText = mconcat $ List. intersperse " " $ zipWith snippet [1 .. ] argTypes
140
149
stripForall t
@@ -224,17 +233,20 @@ instance ModuleCache CachedCompletions where
224
233
225
234
typeEnv = md_types $ snd $ tm_internals_ tm
226
235
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
228
239
where
229
240
typ = Just $ varType var
230
241
name = Var. varName var
231
242
label = T. pack $ showGhc name
232
243
244
+ toplevelCompls :: [CompItem ]
233
245
toplevelCompls = map varToCompl toplevelVars
234
246
235
247
toCompItem :: ModuleName -> Name -> CompItem
236
248
toCompItem mn n =
237
- CI n (showModName mn) Nothing (T. pack $ showGhc n)
249
+ CI n (showModName mn) Nothing (T. pack $ showGhc n) Nothing
238
250
239
251
allImportsInfo :: [(Bool , T. Text , ModuleName , Maybe (Bool , [Name ]))]
240
252
allImportsInfo = map getImpInfo importDeclerations
@@ -369,6 +381,26 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
369
381
d = T. length fullLine - T. length (stripTypeStuff partialLine)
370
382
in Position l (c - d)
371
383
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
+
372
404
filtModNameCompls =
373
405
map mkModCompl
374
406
$ mapMaybe (T. stripPrefix enteredQual)
@@ -378,13 +410,23 @@ getCompletions uri prefixInfo (WithSnippets withSnippets) =
378
410
where
379
411
isTypeCompl = isTcOcc . occName . origName
380
412
-- completions specific to the current context
381
- ctxCompls = case context of
413
+ ctxCompls' = case context of
382
414
TypeContext -> filter isTypeCompl compls
383
415
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
+
384
425
compls = if T. null prefixModule
385
426
then unqualCompls
386
427
else Map. findWithDefault [] prefixModule qualCompls
387
428
429
+
388
430
mkImportCompl label = (J. detail ?~ label) . mkModCompl $ fromMaybe
389
431
" "
390
432
(T. stripPrefix enteredQual label)
0 commit comments