Skip to content

Commit 2b5c0dd

Browse files
author
Jana Chadt
committed
Refactor and document code
1 parent 3818404 commit 2b5c0dd

File tree

1 file changed

+65
-49
lines changed
  • plugins/hls-cabal-plugin/src/Ide/Plugin

1 file changed

+65
-49
lines changed

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

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ import qualified Data.Map as Map
4343
import Language.LSP.VFS (VirtualFile)
4444
import qualified Data.Text.Utf16.Rope as Rope
4545
import qualified Data.List as List
46-
import qualified Language.LSP.Types.Lens as Map
47-
import Development.IDE.GHC.Compat (getContext)
4846
import Debug.Trace
4947
import qualified Data.List.Extra as Extra
5048
data Log
@@ -186,56 +184,68 @@ completion _ide _ complParams = do
186184
result Nothing _ = J.List []
187185
result (Just pfix) cnts
188186
| pos ^. JL.line == 0 = J.List [buildCompletion (fst cabalVersionKeyword)]
189-
| Just ctx@(Stanza s kwContext) <- context =
190-
case (Map.lookup s stanzaKeywordMap) of
191-
Nothing ->
192-
case kwContext of
193-
None ->
194-
J.List $
195-
makeCompletionItems pfix topLevelKeywords
196-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
197-
Just m ->
198-
case kwContext of
199-
None -> J.List $ (makeCompletionItems pfix (Map.keys m)) ++ (makeCompletionItems pfix $ Map.keys stanzaKeywordMap)
200-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
201-
| Just ctx@(TopLevel kwContext) <- context =
202-
case kwContext of
203-
None -> J.List $ makeCompletionItems pfix topLevelKeywords
204-
KeyWord kw -> J.List $ makeCompletionItems pfix (getPossibleValuesForKeyWord kw ctx)
187+
| Just ctx <- context = J.List $ makeCompletionItems pfix (getCompletionsForContext ctx)
205188
| otherwise = J.List []
206189
where
207190
pos = VFS.cursorPos pfix
208-
topLevelKeywords = Map.keys cabalKeywords ++ Map.keys stanzaKeywordMap
209-
context = findCurrentContext pos (cnts ^. VFS.file_text)
210-
211-
getPossibleValuesForKeyWord :: T.Text -> Context -> [T.Text]
212-
getPossibleValuesForKeyWord kw (TopLevel _) =
191+
context = getContext pos (Rope.lines $ cnts ^. VFS.file_text)
192+
193+
-- | Takes a context and returns all possible completions within that context
194+
getCompletionsForContext :: Context -> [T.Text]
195+
-- if we are in the top level of the cabal file and not in a keyword context,
196+
-- we can write any toplevel keywords or a stanza declaration
197+
getCompletionsForContext (TopLevel, None) =
198+
Map.keys cabalKeywords ++ Map.keys stanzaKeywordMap
199+
-- if we are in a keyword context in the toplevel,
200+
-- we look up that keyword in the toplevel context and can complete its possible values
201+
getCompletionsForContext (TopLevel, KeyWord kw) =
213202
case Map.lookup kw cabalKeywords of
214203
Nothing -> []
215204
Just l -> l
216-
getPossibleValuesForKeyWord kw (Stanza s _) =
205+
-- if we are in a stanza and not in a keyword context,
206+
-- we can write any of the stanza's keywords or a stanza declaration
207+
getCompletionsForContext (Stanza s, None) =
208+
case Map.lookup s stanzaKeywordMap of
209+
Nothing -> []
210+
Just l -> Map.keys l ++ Map.keys stanzaKeywordMap
211+
-- if we are in a stanza's keyword's context we can complete possible values of that keyword
212+
getCompletionsForContext (Stanza s, KeyWord kw) =
217213
case Map.lookup s stanzaKeywordMap of
218214
Nothing -> []
219215
Just m -> case Map.lookup kw m of
220216
Nothing -> []
221217
Just l -> l
222218

223-
findCurrentContext :: Position -> Rope.Rope -> Maybe Context
224-
findCurrentContext pos rope =
225-
case outerContext of
226-
TopLevel _ -> TopLevel <$> getKeyWordContext cabalKeywords
227-
Stanza s _ ->
228-
case traceShowId (Map.lookup (traceShowId s) stanzaKeywordMap) of
229-
Nothing -> pure $ Stanza s None
230-
Just m -> traceShowId $ Stanza s <$> getKeyWordContext m
231-
where
232-
outerContext = findCurrentLevel (getPreviousLines pos rope) None
233-
currentLine = traceShowId $ (Rope.lines rope) Extra.!? (fromIntegral $ pos ^. JL.line)
234-
getKeyWordContext keywords = do
219+
-- | Takes a position and a list of lines (representing a file)
220+
-- and returns the context of the current position
221+
-- can return Nothing if an error occurs
222+
getContext :: Position -> [T.Text] -> Maybe Context
223+
getContext pos ls =
224+
case lvlContext of
225+
TopLevel -> do
226+
kwContext <- getKeyWordContext pos ls cabalKeywords
227+
pure (TopLevel, kwContext)
228+
Stanza s ->
229+
case Map.lookup (traceShowId s) stanzaKeywordMap of
230+
Nothing -> do
231+
pure (Stanza s, None)
232+
Just m -> do
233+
kwContext <- getKeyWordContext pos ls m
234+
pure (Stanza s, kwContext)
235+
where
236+
lvlContext = findCurrentLevel (ls)
237+
238+
-- | Takes a position, a list of lines (representing a file) and a map of keywords as keys
239+
-- and returns a keyword context if there is a keyword from the map before the current position
240+
-- in the given line list
241+
getKeyWordContext :: Position -> [T.Text] -> Map T.Text a -> Maybe KeyWordContext
242+
getKeyWordContext pos ls keywords = do
235243
curLine <- fmap T.stripStart currentLine
236-
case List.find (\kw -> traceShowId kw `T.isPrefixOf` curLine) (traceShowId $ Map.keys keywords) of
244+
case List.find (`T.isPrefixOf` curLine) (Map.keys keywords) of
237245
Nothing -> Just None
238246
Just kw -> Just $ KeyWord kw
247+
where
248+
currentLine = ls Extra.!? (fromIntegral $ pos ^. JL.line)
239249

240250
-- | Takes info about the current cursor position and a set of possible keywords
241251
-- and creates completion suggestions that fit the current input from the given list
@@ -248,11 +258,11 @@ makeCompletionItems pfix l =
248258
-- | Parse the given set of lines (starting before current cursor position
249259
-- up to the start of the file) to find the nearest stanza declaration,
250260
-- if none is found we are in the top level
251-
findCurrentLevel :: [T.Text] -> KeyWordContext -> Context
252-
findCurrentLevel [] kwContext = TopLevel kwContext
253-
findCurrentLevel (cur : xs) kwContext
254-
| Just s <- stanza = Stanza s kwContext
255-
| otherwise = findCurrentLevel xs kwContext
261+
findCurrentLevel :: [T.Text] -> LevelContext
262+
findCurrentLevel [] = TopLevel
263+
findCurrentLevel (cur : xs)
264+
| Just s <- stanza = Stanza s
265+
| otherwise = findCurrentLevel xs
256266
where
257267
stanza = List.find (`T.isPrefixOf` cur) (Map.keys stanzaKeywordMap)
258268

@@ -264,19 +274,25 @@ getPreviousLines pos rope = reverse $ take (fromIntegral currentLine) allLines
264274
allLines = Rope.lines rope
265275
currentLine = pos ^. JL.line
266276

267-
data Context
268-
= TopLevel KeyWordContext
269-
-- ^ top level context in a cabal file such as 'author'
270-
| Stanza T.Text KeyWordContext
271-
-- ^ nested context in a cabal file, such as 'library', which has nested keywords, specific to the stanza
277+
-- | The context a cursor can be in within a cabal file,
278+
-- we can be in stanzas or the toplevel,
279+
-- and additionally we can be in a context where we have already written a keyword
280+
-- but no value for it yet
281+
type Context = (LevelContext, KeyWordContext)
282+
283+
data LevelContext
284+
= TopLevel
285+
-- ^ Top level context in a cabal file such as 'author'
286+
| Stanza T.Text
287+
-- ^ Nested context in a cabal file, such as 'library', which has nested keywords, specific to the stanza
272288
deriving (Eq, Show)
273289

274290
-- | Keyword context in cabal file
275291
data KeyWordContext
276292
= KeyWord T.Text
277-
-- ^ we are in a line with the given keyword before our cursor
293+
-- ^ We are in a line with the given keyword before our cursor
278294
| None
279-
-- ^ we are in a line with no keyword context
295+
-- ^ We are in a line with no keyword context
280296
deriving (Eq, Show)
281297

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

0 commit comments

Comments
 (0)