Skip to content

Commit 3eec5ed

Browse files
Jana ChadtVeryMilkyJoe
Jana Chadt
authored andcommitted
Refactor and document code
1 parent 78a3168 commit 3eec5ed

File tree

1 file changed

+66
-47
lines changed
  • plugins/hls-cabal-plugin/src/Ide/Plugin

1 file changed

+66
-47
lines changed

plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal.hs

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import Language.LSP.VFS (VirtualFile)
5050
import qualified Language.LSP.VFS as VFS
5151
import qualified Text.Fuzzy.Parallel as Fuzzy
5252

53+
5354
data Log
5455
= LogModificationTime NormalizedFilePath FileVersion
5556
| LogShake Shake.Log
@@ -288,56 +289,68 @@ completion _ide _ complParams = do
288289
result Nothing _ = J.List []
289290
result (Just pfix) cnts
290291
| pos ^. JL.line == 0 = J.List [buildCompletion (fst cabalVersionKeyword)]
291-
| Just ctx@(Stanza s kwContext) <- context =
292-
case (Map.lookup s stanzaKeywordMap) of
293-
Nothing ->
294-
case kwContext of
295-
None ->
296-
J.List $
297-
makeCompletionItems pfix topLevelKeywords
298-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
299-
Just m ->
300-
case kwContext of
301-
None -> J.List $ (makeCompletionItems pfix (Map.keys m)) ++ (makeCompletionItems pfix $ Map.keys stanzaKeywordMap)
302-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
303-
| Just ctx@(TopLevel kwContext) <- context =
304-
case kwContext of
305-
None -> J.List $ makeCompletionItems pfix topLevelKeywords
306-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
292+
| Just ctx <- context = J.List $ makeCompletionItems pfix (getCompletionsForContext ctx)
307293
| otherwise = J.List []
308294
where
309295
pos = VFS.cursorPos pfix
310-
topLevelKeywords = Map.keys cabalKeywords ++ Map.keys stanzaKeywordMap
311-
context = findCurrentContext pos (cnts ^. VFS.file_text)
312-
313-
getPossibleValuesForKeyWord :: T.Text -> Context -> [T.Text]
314-
getPossibleValuesForKeyWord kw (TopLevel _) =
296+
context = getContext pos (Rope.lines $ cnts ^. VFS.file_text)
297+
298+
-- | Takes a context and returns all possible completions within that context
299+
getCompletionsForContext :: Context -> [T.Text]
300+
-- if we are in the top level of the cabal file and not in a keyword context,
301+
-- we can write any toplevel keywords or a stanza declaration
302+
getCompletionsForContext (TopLevel, None) =
303+
Map.keys cabalKeywords ++ Map.keys stanzaKeywordMap
304+
-- if we are in a keyword context in the toplevel,
305+
-- we look up that keyword in the toplevel context and can complete its possible values
306+
getCompletionsForContext (TopLevel, KeyWord kw) =
315307
case Map.lookup kw cabalKeywords of
316308
Nothing -> []
317309
Just l -> l
318-
getPossibleValuesForKeyWord kw (Stanza s _) =
310+
-- if we are in a stanza and not in a keyword context,
311+
-- we can write any of the stanza's keywords or a stanza declaration
312+
getCompletionsForContext (Stanza s, None) =
313+
case Map.lookup s stanzaKeywordMap of
314+
Nothing -> []
315+
Just l -> Map.keys l ++ Map.keys stanzaKeywordMap
316+
-- if we are in a stanza's keyword's context we can complete possible values of that keyword
317+
getCompletionsForContext (Stanza s, KeyWord kw) =
319318
case Map.lookup s stanzaKeywordMap of
320319
Nothing -> []
321320
Just m -> case Map.lookup kw m of
322321
Nothing -> []
323322
Just l -> l
324323

325-
findCurrentContext :: Position -> Rope.Rope -> Maybe Context
326-
findCurrentContext pos rope =
327-
case outerContext of
328-
TopLevel _ -> TopLevel <$> getKeyWordContext cabalKeywords
329-
Stanza s _ ->
330-
case traceShowId (Map.lookup (traceShowId s) stanzaKeywordMap) of
331-
Nothing -> pure $ Stanza s None
332-
Just m -> traceShowId $ Stanza s <$> getKeyWordContext m
333-
where
334-
outerContext = findCurrentLevel (getPreviousLines pos rope) None
335-
currentLine = traceShowId $ (Rope.lines rope) Extra.!? (fromIntegral $ pos ^. JL.line)
336-
getKeyWordContext keywords = do
324+
-- | Takes a position and a list of lines (representing a file)
325+
-- and returns the context of the current position
326+
-- can return Nothing if an error occurs
327+
getContext :: Position -> [T.Text] -> Maybe Context
328+
getContext pos ls =
329+
case lvlContext of
330+
TopLevel -> do
331+
kwContext <- getKeyWordContext pos ls cabalKeywords
332+
pure (TopLevel, kwContext)
333+
Stanza s ->
334+
case Map.lookup (traceShowId s) stanzaKeywordMap of
335+
Nothing -> do
336+
pure (Stanza s, None)
337+
Just m -> do
338+
kwContext <- getKeyWordContext pos ls m
339+
pure (Stanza s, kwContext)
340+
where
341+
lvlContext = findCurrentLevel (ls)
342+
343+
-- | Takes a position, a list of lines (representing a file) and a map of keywords as keys
344+
-- and returns a keyword context if there is a keyword from the map before the current position
345+
-- in the given line list
346+
getKeyWordContext :: Position -> [T.Text] -> Map T.Text a -> Maybe KeyWordContext
347+
getKeyWordContext pos ls keywords = do
337348
curLine <- fmap T.stripStart currentLine
338-
case List.find (\kw -> traceShowId kw `T.isPrefixOf` curLine) (traceShowId $ Map.keys keywords) of
349+
case List.find (`T.isPrefixOf` curLine) (Map.keys keywords) of
339350
Nothing -> Just None
340351
Just kw -> Just $ KeyWord kw
352+
where
353+
currentLine = ls Extra.!? (fromIntegral $ pos ^. JL.line)
341354

342355
-- | Takes info about the current cursor position and a set of possible keywords
343356
-- and creates completion suggestions that fit the current input from the given list
@@ -350,11 +363,11 @@ makeCompletionItems pfix l =
350363
-- | Parse the given set of lines (starting before current cursor position
351364
-- up to the start of the file) to find the nearest stanza declaration,
352365
-- if none is found we are in the top level
353-
findCurrentLevel :: [T.Text] -> KeyWordContext -> Context
354-
findCurrentLevel [] kwContext = TopLevel kwContext
355-
findCurrentLevel (cur : xs) kwContext
356-
| Just s <- stanza = Stanza s kwContext
357-
| otherwise = findCurrentLevel xs kwContext
366+
findCurrentLevel :: [T.Text] -> LevelContext
367+
findCurrentLevel [] = TopLevel
368+
findCurrentLevel (cur : xs)
369+
| Just s <- stanza = Stanza s
370+
| otherwise = findCurrentLevel xs
358371
where
359372
stanza = List.find (`T.isPrefixOf` cur) (Map.keys stanzaKeywordMap)
360373

@@ -366,19 +379,25 @@ getPreviousLines pos rope = reverse $ take (fromIntegral currentLine) allLines
366379
allLines = Rope.lines rope
367380
currentLine = pos ^. JL.line
368381

369-
data Context
370-
= TopLevel KeyWordContext
371-
-- ^ top level context in a cabal file such as 'author'
372-
| Stanza T.Text KeyWordContext
373-
-- ^ nested context in a cabal file, such as 'library', which has nested keywords, specific to the stanza
382+
-- | The context a cursor can be in within a cabal file,
383+
-- we can be in stanzas or the toplevel,
384+
-- and additionally we can be in a context where we have already written a keyword
385+
-- but no value for it yet
386+
type Context = (LevelContext, KeyWordContext)
387+
388+
data LevelContext
389+
= TopLevel
390+
-- ^ Top level context in a cabal file such as 'author'
391+
| Stanza T.Text
392+
-- ^ Nested context in a cabal file, such as 'library', which has nested keywords, specific to the stanza
374393
deriving (Eq, Show)
375394

376395
-- | Keyword context in cabal file
377396
data KeyWordContext
378397
= KeyWord T.Text
379-
-- ^ we are in a line with the given keyword before our cursor
398+
-- ^ We are in a line with the given keyword before our cursor
380399
| None
381-
-- ^ we are in a line with no keyword context
400+
-- ^ We are in a line with no keyword context
382401
deriving (Eq, Show)
383402

384403
-- | Keyword for cabal version required to be the top line in a cabal file

0 commit comments

Comments
 (0)