Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Distribution.PackageDescription (Benchmark (..),
BuildInfo (..),
CondTree (condTreeData),
Executable (..),
ForeignLib (..),
GenericPackageDescription (..),
Library (..),
UnqualComponentName,
Expand Down Expand Up @@ -118,6 +119,10 @@ sourceDirsExtractionTestSuite name gpd = extractRelativeDirsFromStanza name gpd
sourceDirsExtractionBenchmark :: Maybe StanzaName -> GenericPackageDescription -> [FilePath]
sourceDirsExtractionBenchmark name gpd = extractRelativeDirsFromStanza name gpd condBenchmarks benchmarkBuildInfo

-- | Extracts the source directories of foreign-lib stanza with the given name.
sourceDirsExtractionForeignLib :: Maybe StanzaName -> GenericPackageDescription -> [FilePath]
sourceDirsExtractionForeignLib name gpd = extractRelativeDirsFromStanza name gpd condForeignLibs foreignLibBuildInfo

{- | Takes a possible stanza name, a GenericPackageDescription,
a function to access the stanza information we are interested in
and a function to access the build info from the specific stanza.
Expand Down
53 changes: 42 additions & 11 deletions plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}

{-# HLINT ignore "Redundant bracket" #-}

module Ide.Plugin.Cabal.Completion.Data where

Expand All @@ -19,6 +16,17 @@ import Ide.Plugin.Cabal.Completion.Completer.Types (Completer)
import Ide.Plugin.Cabal.Completion.Types
import Ide.Plugin.Cabal.LicenseSuggest (licenseNames)

-- | Ad-hoc data type for modelling the available top-level stanzas.
-- Not intended right now for anything else but to avoid string
-- comparisons in 'stanzaKeywordMap' and 'libExecTestBenchCommons'.
data TopLevelStanza
= Library
| Executable
| TestSuite
| Benchmark
| ForeignLib
| Common

-- ----------------------------------------------------------------
-- Completion Data
-- ----------------------------------------------------------------
Expand Down Expand Up @@ -71,12 +79,13 @@ cabalKeywords =
stanzaKeywordMap :: Map StanzaType (Map KeyWordName Completer)
stanzaKeywordMap =
Map.fromList
[ ("library", libraryFields <> libExecTestBenchCommons),
("executable", executableFields <> libExecTestBenchCommons),
("test-suite", testSuiteFields <> libExecTestBenchCommons),
("benchmark", benchmarkFields <> libExecTestBenchCommons),
("foreign-library", foreignLibraryFields <> libExecTestBenchCommons),
("common", libExecTestBenchCommons),
[ ("library", libraryFields <> libExecTestBenchCommons Library),
("executable", executableFields <> libExecTestBenchCommons Executable),
("test-suite", testSuiteFields <> libExecTestBenchCommons TestSuite),
("benchmark", benchmarkFields <> libExecTestBenchCommons Benchmark),
("foreign-library", foreignLibraryFields <> libExecTestBenchCommons ForeignLib),
("common", libExecTestBenchCommons Library),
("common", libExecTestBenchCommons Common),
("flag", flagFields),
("source-repository", sourceRepositoryFields)
]
Expand Down Expand Up @@ -162,8 +171,8 @@ flagFields =
("lib-version-linux:", noopCompleter)
]

libExecTestBenchCommons :: Map KeyWordName Completer
libExecTestBenchCommons =
libExecTestBenchCommons :: TopLevelStanza -> Map KeyWordName Completer
libExecTestBenchCommons st =
Map.fromList
[ ("import:", importCompleter),
("build-depends:", noopCompleter),
Expand All @@ -183,6 +192,8 @@ libExecTestBenchCommons =
("includes:", filePathCompleter),
("install-includes:", filePathCompleter),
("include-dirs:", directoryCompleter),
("autogen-includes:", filePathCompleter),
("autogen-modules:", moduleCompleterByTopLevelStanza),
("c-sources:", filePathCompleter),
("cxx-sources:", filePathCompleter),
("asm-sources:", filePathCompleter),
Expand All @@ -203,6 +214,26 @@ libExecTestBenchCommons =
("extra-framework-dirs:", directoryCompleter),
("mixins:", noopCompleter)
]
where
--
moduleCompleterByTopLevelStanza = case st of
Library -> modulesCompleter sourceDirsExtractionLibrary
Executable -> modulesCompleter sourceDirsExtractionExecutable
TestSuite -> modulesCompleter sourceDirsExtractionTestSuite
Benchmark -> modulesCompleter sourceDirsExtractionBenchmark
ForeignLib -> modulesCompleter sourceDirsExtractionForeignLib
Common ->
-- TODO: We can't provide a module completer because we provide
-- module completions based on the "hs-source-dirs" after parsing the file,
-- i.e. based on the 'PackageDescription'.
-- "common" stanzas are erased in the 'PackageDescription' representation,
-- thus we can't provide accurate module completers right now, as we don't
-- know what the 'hs-source-dirs' in the "common" stanza are.
--
-- A potential fix would be to introduce an intermediate representation that
-- parses the '.cabal' file s.t. that we have access to the 'hs-source-dirs',
-- but not have erased the "common" stanza.
noopCompleter

-- | Contains a map of the most commonly used licenses, weighted by their popularity.
--
Expand Down
24 changes: 23 additions & 1 deletion plugins/hls-cabal-plugin/test/Completer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Completer where

import Control.Lens ((^.), (^?))
import Control.Lens.Prism
import Control.Monad (forM_)
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as BS8
import Data.Maybe (mapMaybe)
Expand Down Expand Up @@ -40,7 +41,8 @@ completerTests =
completionHelperTests,
filePathExposedModulesTests,
exposedModuleCompleterTests,
importCompleterTests
importCompleterTests,
autogenFieldCompletionTests
]

basicCompleterTests :: TestTree
Expand Down Expand Up @@ -336,6 +338,26 @@ importCompleterTests =
[Syntax.SecArgName (Syntax.Position row (col + 7)) (BS8.pack name)]
[]

autogenFieldCompletionTests :: TestTree
autogenFieldCompletionTests =
testGroup "Autogen Field Completer Tests"
[ testAutogenField "library" "completion/autogen-completion.cabal" (Position 6 9) ["autogen-modules:", "autogen-includes:"]
, testAutogenField "executable" "completion/autogen-completion.cabal" (Position 11 9) ["autogen-modules:", "autogen-includes:"]
, testAutogenField "test-suite" "completion/autogen-completion.cabal" (Position 16 9) ["autogen-modules:", "autogen-includes:"]
, testAutogenField "benchmark" "completion/autogen-completion.cabal" (Position 21 9) ["autogen-modules:", "autogen-includes:"]
, testAutogenField "common" "completion/autogen-completion.cabal" (Position 24 9) ["autogen-modules:", "autogen-includes:"]
]

where
testAutogenField :: String -> FilePath -> Position -> [T.Text] -> TestTree
testAutogenField section file pos expected = runCabalTestCaseSession ("autogen-modules completion in " <> section) "" $ do
doc <- openDoc file "cabal"
items <- getCompletions doc pos
let labels = map (^. L.label) items
liftIO $ forM_ expected $ \expect ->
assertBool (T.unpack expect <> " not found in " <> section) $
any (expect `T.isInfixOf`) labels

simpleCompleterData :: Maybe StanzaName -> FilePath -> T.Text -> CompleterData
simpleCompleterData sName dir pref = do
CompleterData
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cabal-version: 3.0
name: autogen-completion
version: 0.1.0.0

library
hs-source-dirs: src
autogen-

executable autoexe
main-is: Main.hs
hs-source-dirs: src
autogen-

test-suite autotest
type: exitcode-stdio-1.0
hs-source-dirs: src
autogen-

benchmark autobench
type: exitcode-stdio-1.0
hs-source-dirs: src
autogen-

common defaults
autogen-
Loading