Skip to content

Commit 4808791

Browse files
authored
Add default-extension completions in .cabal files (#4766)
Suggest all known language extensions for the `default-extensions` field in .cabal files. Also add a new variation, `mkParameterisedTestCaseM`, of `mkParameterisedTestCase` which takes an Assertion instead checking for equality of the given values.
1 parent 88ccebe commit 4808791

File tree

3 files changed

+69
-43
lines changed

3 files changed

+69
-43
lines changed

hls-test-utils/src/Test/Hls.hs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module Test.Hls
3636
runSessionWithTestConfig,
3737
-- * Running parameterised tests for a set of test configurations
3838
parameterisedCursorTest,
39+
parameterisedCursorTestM,
3940
-- * Helpful re-exports
4041
PluginDescriptor,
4142
IdeState,
@@ -383,8 +384,15 @@ goldenWithDocInTmpDir languageKind config plugin title tree path desc ext act =
383384
-- The quasi quoter '__i' is very helpful to define such tests, as it additionally
384385
-- allows to interpolate haskell values and functions. We reexport this quasi quoter
385386
-- for easier usage.
386-
parameterisedCursorTest :: (Show a, Eq a) => String -> T.Text -> [a] -> (T.Text -> PosPrefixInfo -> IO a) -> TestTree
387-
parameterisedCursorTest title content expectations act
387+
parameterisedCursorTest :: forall a . (Show a, Eq a) => String -> T.Text -> [a] -> (T.Text -> PosPrefixInfo -> IO a) -> TestTree
388+
parameterisedCursorTest title content expectations act = parameterisedCursorTestM title content assertions act
389+
where
390+
assertions = map testCaseAssertion expectations
391+
testCaseAssertion :: a -> PosPrefixInfo -> a -> Assertion
392+
testCaseAssertion expected info actual = assertEqual (mkParameterisedLabel info) expected actual
393+
394+
parameterisedCursorTestM :: String -> T.Text -> [(PosPrefixInfo -> a -> Assertion)] -> (T.Text -> PosPrefixInfo -> IO a) -> TestTree
395+
parameterisedCursorTestM title content expectations act
388396
| lenPrefs /= lenExpected = error $ "parameterisedCursorTest: Expected " <> show lenExpected <> " cursors but found: " <> show lenPrefs
389397
| otherwise = testGroup title $
390398
map singleTest testCaseSpec
@@ -395,9 +403,9 @@ parameterisedCursorTest title content expectations act
395403

396404
testCaseSpec = zip [1 ::Int ..] (zip expectations prefInfos)
397405

398-
singleTest (n, (expected, info)) = testCase (title <> " " <> show n) $ do
406+
singleTest (n, (assert, info)) = testCase (title <> " " <> show n) $ do
399407
actual <- act cleanText info
400-
assertEqual (mkParameterisedLabel info) expected actual
408+
assert info actual
401409

402410
-- ------------------------------------------------------------
403411
-- Helper function for initialising plugins under test

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import qualified Data.Text as T
88
import Development.IDE.GHC.Compat.Core (flagsForCompletion)
99
import Distribution.CabalSpecVersion (CabalSpecVersion (CabalSpecV2_2),
1010
showCabalSpecVersion)
11+
import Distribution.Pretty (prettyShow)
1112
import Ide.Plugin.Cabal.Completion.Completer.FilePath
1213
import Ide.Plugin.Cabal.Completion.Completer.Module
1314
import Ide.Plugin.Cabal.Completion.Completer.Paths
1415
import Ide.Plugin.Cabal.Completion.Completer.Simple
1516
import Ide.Plugin.Cabal.Completion.Completer.Types (Completer)
1617
import Ide.Plugin.Cabal.Completion.Types
1718
import Ide.Plugin.Cabal.LicenseSuggest (licenseNames)
18-
19+
import Language.Haskell.Extension
1920
-- | Ad-hoc data type for modelling the available top-level stanzas.
2021
-- Not intended right now for anything else but to avoid string
2122
-- comparisons in 'stanzaKeywordMap' and 'libExecTestBenchCommons'.
@@ -177,8 +178,8 @@ libExecTestBenchCommons st =
177178
[ ("import:", importCompleter),
178179
("build-depends:", noopCompleter),
179180
("hs-source-dirs:", directoryCompleter),
180-
("default-extensions:", noopCompleter),
181-
("other-extensions:", noopCompleter),
181+
("default-extensions:", constantCompleter $ map (T.pack . prettyShow) allExtensions),
182+
("other-extensions:", constantCompleter $ map (T.pack . prettyShow) allExtensions),
182183
("default-language:", constantCompleter ["GHC2021", "Haskell2010", "Haskell98"]),
183184
("other-languages:", noopCompleter),
184185
("build-tool-depends:", noopCompleter),
@@ -235,6 +236,19 @@ libExecTestBenchCommons st =
235236
-- but not have erased the "common" stanza.
236237
noopCompleter
237238

239+
-- | Returns all possible language extensions including disabled ones.
240+
allExtensions :: [Extension]
241+
allExtensions =
242+
concatMap
243+
( \e ->
244+
-- These pragmas cannot be negated as they are not reversible
245+
-- by prepending "No".
246+
if e `notElem` [Unsafe, Trustworthy, Safe]
247+
then [EnableExtension e, DisableExtension e]
248+
else [EnableExtension e]
249+
)
250+
knownExtensions
251+
238252
-- | Contains a map of the most commonly used licenses, weighted by their popularity.
239253
--
240254
-- The data was extracted by Kleidukos from the alternative hackage frontend flora.pm.

plugins/hls-cabal-plugin/test/Completer.hs

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import qualified Data.ByteString as ByteString
1212
import qualified Data.ByteString.Char8 as BS8
1313
import Data.Maybe (mapMaybe)
1414
import qualified Data.Text as T
15+
import Development.IDE.Plugin.Completions.Types (cursorPos)
1516
import qualified Development.IDE.Plugin.Completions.Types as Ghcide
1617
import qualified Distribution.Fields as Syntax
1718
import Distribution.PackageDescription (GenericPackageDescription)
@@ -29,6 +30,9 @@ import Ide.Plugin.Cabal.Completion.Types (CabalPrefixInfo
2930
import qualified Language.LSP.Protocol.Lens as L
3031
import System.FilePath
3132
import Test.Hls
33+
import Test.Hls.FileSystem (file,
34+
mkVirtualFileTree,
35+
text)
3236
import qualified Text.Fuzzy.Parallel as Fuzzy
3337
import Utils
3438

@@ -73,7 +77,20 @@ basicCompleterTests =
7377
let complTexts = getTextEditTexts compls
7478
liftIO $ assertBool "suggests f2" $ "f2.hs" `elem` complTexts
7579
liftIO $ assertBool "does not suggest" $ "Content.hs" `notElem` complTexts
76-
]
80+
, parameterisedCursorTestM "extensions completion" libraryStanzaData
81+
[ \_ actual -> assertBool "suggests FieldSelectors" $ "FieldSelectors" `elem` actual
82+
, \_ actual -> assertBool "suggests OverloadedStrings" $ "OverloadedStrings" `elem` actual
83+
, \_ actual -> assertBool "suggests something" $ not . null $ actual
84+
, \_ actual -> assertBool "suggests NoLambdaCase" $ "NoLambdaCase" `elem` actual
85+
, \_ actual -> assertBool "suggests RecordWildCards" $ "RecordWildCards" `elem` actual
86+
]
87+
$ \fileContent posPrefInfo -> do
88+
let vFileTree = mkVirtualFileTree "" $ [file "cabalFile.cabal" $ text fileContent]
89+
runCabalSessionVft vFileTree $ do
90+
doc <- openDoc "cabalFile.cabal" "cabal"
91+
compls <- getCompletions doc (cursorPos posPrefInfo)
92+
let complTexts = getTextEditTexts compls
93+
pure complTexts]
7794
where
7895
getTextEditTexts :: [CompletionItem] -> [T.Text]
7996
getTextEditTexts compls = mapMaybe (^? L.textEdit . _Just . _L . L.newText) compls
@@ -401,40 +418,27 @@ extract item = case item ^. L.textEdit of
401418
Just (InL v) -> v ^. L.newText
402419
_ -> error ""
403420

404-
importTestData :: T.Text
405-
importTestData = [__i|
406-
cabal-version: 3.0
407-
name: hls-cabal-plugin
408-
version: 0.1.0.0
409-
synopsis:
410-
homepage:
411-
license: MIT
412-
license-file: LICENSE
413-
author: Fendor
414-
maintainer: [email protected]
415-
category: Development
416-
extra-source-files: CHANGELOG.md
417-
418-
common defaults
419-
default-language: GHC2021
420-
-- Should have been in GHC2021, an oversight
421-
default-extensions: ExplicitNamespaces
422-
423-
common test-defaults
424-
ghc-options: -threaded -rtsopts -with-rtsopts=-N
425-
426-
library
427-
import:
428-
^
429-
exposed-modules: IDE.Plugin.Cabal
430-
build-depends: base ^>=4.14.3.0
431-
hs-source-dirs: src
432-
default-language: Haskell2010
433-
434-
common notForLib
435-
default-language: GHC2021
421+
-- ------------------------------------------------------------------------
422+
-- Test Data
423+
-- ------------------------------------------------------------------------
436424

437-
test-suite tests
438-
import:
439-
^
425+
libraryStanzaData :: T.Text
426+
libraryStanzaData = [__i|
427+
cabal-version: 3.0
428+
name: simple-cabal
429+
common mylib
430+
default-extensions: Field
431+
^
432+
library
433+
default-extensions: Ov
434+
^
435+
test-suite mysuite
436+
default-extensions:
437+
^
438+
executable myexe
439+
default-extensions: NoLam
440+
^
441+
benchmark mybench
442+
other-extensions: RecordW
443+
^
440444
|]

0 commit comments

Comments
 (0)