diff --git a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/CabalFields.hs b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/CabalFields.hs index b8cb7ce0d6..58b36de7df 100644 --- a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/CabalFields.hs +++ b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/CabalFields.hs @@ -52,20 +52,24 @@ findStanzaForColumn col ctx = case NE.uncons ctx of -- -- This only looks at the row of the cursor and not at the cursor's -- position within the row. --- --- TODO: we do not handle braces correctly. Add more tests! findFieldSection :: Syntax.Position -> [Syntax.Field Syntax.Position] -> Maybe (Syntax.Field Syntax.Position) findFieldSection _cursor [] = Nothing -findFieldSection _cursor [x] = - -- Last field. We decide later, whether we are starting - -- a new section. - Just x +findFieldSection _cursor [x] = Just x findFieldSection cursor (x:y:ys) | Syntax.positionRow (getAnnotation x) <= cursorLine && cursorLine < Syntax.positionRow (getAnnotation y) = Just x + | Syntax.positionRow (getAnnotation x) == cursorLine && Syntax.positionRow (getAnnotation y) == cursorLine + = case (x, y) of + (Syntax.Field _ fieldLines, Syntax.Field _ nextFieldLines) -> + -- Handle multi-line fields with braces + if any (isBraceField . Syntax.fieldLineName) fieldLines + then Just x + else findFieldSection cursor (y:ys) + _ -> findFieldSection cursor (y:ys) | otherwise = findFieldSection cursor (y:ys) where cursorLine = Syntax.positionRow cursor + isBraceField name = name == "extra-libraries:" || name == "extra-frameworks:" || name == "extra-lib-dirs:" -- | Determine the field line the cursor is currently a part of. -- @@ -301,3 +305,7 @@ getFieldLSPRange field = LSP.Range startLSPPos endLSPPos where startLSPPos = cabalPositionToLSPPosition $ getAnnotation field endLSPPos = cabalPositionToLSPPosition $ getFieldEndPosition field + +-- | Helper function to check if a field line contains a brace +isBraceField :: T.Text -> Bool +isBraceField name = name `elem` ["extra-libraries:", "extra-frameworks:", "extra-lib-dirs:", "extra-framework-dirs:"] diff --git a/plugins/hls-cabal-plugin/test/Completer.hs b/plugins/hls-cabal-plugin/test/Completer.hs index 6b1f772af0..d04d383f14 100644 --- a/plugins/hls-cabal-plugin/test/Completer.hs +++ b/plugins/hls-cabal-plugin/test/Completer.hs @@ -69,6 +69,18 @@ basicCompleterTests = let complTexts = getTextEditTexts compls liftIO $ assertBool "suggests f2" $ "f2.hs" `elem` complTexts liftIO $ assertBool "does not suggest" $ "Content.hs" `notElem` complTexts + , runCabalTestCaseSession "Brace handling in multi-line fields" "brace-handling" $ do + doc <- openDoc "brace-handling.cabal" "cabal" + -- Test completion in a multi-line field with braces + compls <- getCompletions doc (Position 15 8) -- Position in extra-libraries field + let complTexts = getTextEditTexts compls + liftIO $ assertBool "suggests correct library names" $ + all (`elem` complTexts) ["pthread", "dl"] + -- Test completion in a field with multiple lines and braces + compls2 <- getCompletions doc (Position 25 8) -- Position in extra-frameworks field + let complTexts2 = getTextEditTexts compls2 + liftIO $ assertBool "suggests correct framework names" $ + all (`elem` complTexts2) ["CoreFoundation", "CoreServices"] ] where getTextEditTexts :: [CompletionItem] -> [T.Text] diff --git a/plugins/hls-cabal-plugin/test/testdata/brace-handling.cabal b/plugins/hls-cabal-plugin/test/testdata/brace-handling.cabal new file mode 100644 index 0000000000..c28c666e63 --- /dev/null +++ b/plugins/hls-cabal-plugin/test/testdata/brace-handling.cabal @@ -0,0 +1,31 @@ +name: brace-handling-test +version: 0.1.0.0 + +library + exposed-modules: + MyLib + build-depends: + base >= 4.7 && < 5 + , text + , containers + default-language: GHC2021 + ghc-options: -Wall + cpp-options: -DDEBUG + extra-libraries: + , pthread + , dl + extra-lib-dirs: + , /usr/local/lib + , /opt/local/lib + extra-framework-dirs: + , /Library/Frameworks + , /System/Library/Frameworks + extra-frameworks: + , CoreFoundation + , CoreServices + extra-lib-dirs: + , /usr/local/lib + , /opt/local/lib + extra-libraries: + , pthread + , dl \ No newline at end of file