3
3
module Ide.Plugin.Cabal.Completion.Completer.Module where
4
4
5
5
import qualified Data.List as List
6
- import Data.Maybe (fromJust ,
7
- fromMaybe )
6
+ import Data.Maybe (fromMaybe )
8
7
import qualified Data.Text as T
9
8
import Development.IDE (IdeState (shakeExtras ))
10
9
import Development.IDE.Core.Shake (runIdeAction ,
@@ -15,11 +14,14 @@ import Distribution.PackageDescription (Benchmark (..),
15
14
Executable (.. ),
16
15
GenericPackageDescription (.. ),
17
16
Library (.. ),
18
- TestSuite ( testName ) ,
17
+ UnqualComponentName ,
19
18
mkUnqualComponentName ,
20
19
testBuildInfo )
21
20
import Distribution.Utils.Path (getSymbolicPath )
22
- import Ide.Plugin.Cabal.Completion.Completer.FilePath
21
+ import Ide.Plugin.Cabal.Completion.Completer.FilePath (PathCompletionInfo (.. ),
22
+ listFileCompletions ,
23
+ mkCompletionDirectory ,
24
+ mkPathCompletion )
23
25
import Ide.Plugin.Cabal.Completion.Completer.Types
24
26
import Ide.Plugin.Cabal.Completion.Types
25
27
@@ -33,15 +35,18 @@ import System.Directory (doesFileExist)
33
35
import qualified System.FilePath as FP
34
36
import qualified System.FilePath.Posix as Posix
35
37
import qualified Text.Fuzzy.Parallel as Fuzzy
38
+
36
39
{- | Completer to be used when module paths can be completed for the field.
37
40
38
41
Takes an extraction function which extracts the source directories
39
42
to be used by the completer.
40
43
-}
41
44
modulesCompleter :: (GenericPackageDescription -> [FilePath ]) -> Completer
42
45
modulesCompleter extractionFunction recorder cData = do
43
- maybeGpd <- runIdeAction " cabal-plugin.modulesCompleter.parseCabal" extras
44
- $ useWithStaleFast ParseCabal $ normalizedCabalFilePath prefInfo
46
+ maybeGpd <-
47
+ runIdeAction " cabal-plugin.modulesCompleter.parseCabal" extras $
48
+ useWithStaleFast ParseCabal $
49
+ normalizedCabalFilePath prefInfo
45
50
case maybeGpd of
46
51
Just (gpd, _) -> do
47
52
let sourceDirs = extractionFunction gpd
@@ -50,114 +55,91 @@ modulesCompleter extractionFunction recorder cData = do
50
55
Nothing -> do
51
56
logWith recorder Debug LogUseWithStaleFastNoResult
52
57
pure []
53
- where
54
- extras = shakeExtras (ideState cData)
55
- prefInfo = cabalPrefixInfo cData
58
+ where
59
+ extras = shakeExtras (ideState cData)
60
+ prefInfo = cabalPrefixInfo cData
56
61
57
- {- | Extracts the source directories of the library stanza.
58
- -}
59
- sourceDirsExtractionLibrary :: GenericPackageDescription -> [FilePath ]
60
- sourceDirsExtractionLibrary gpd =
62
+ -- | Extracts the source directories of the library stanza.
63
+ sourceDirsExtractionLibrary :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
64
+ sourceDirsExtractionLibrary Nothing gpd =
61
65
-- we use condLibrary to get the information contained in the library stanza
62
66
-- since the library in PackageDescription is not populated by us
63
67
case libM of
64
68
Just lib -> do
65
69
map getSymbolicPath $ hsSourceDirs $ libBuildInfo $ condTreeData lib
66
70
Nothing -> []
67
- where
68
- libM = condLibrary gpd
71
+ where
72
+ libM = condLibrary gpd
73
+ sourceDirsExtractionLibrary name gpd = extractRelativeDirsFromStanza name gpd condSubLibraries libBuildInfo
69
74
70
- {- | Extracts the source directories of the executable stanza with the given name.
71
- -}
75
+ -- | Extracts the source directories of the executable stanza with the given name.
72
76
sourceDirsExtractionExecutable :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
73
- sourceDirsExtractionExecutable Nothing _ = []
74
- sourceDirsExtractionExecutable (Just name) gpd
75
- | exeName executable == (mkUnqualComponentName $ T. unpack name) = map getSymbolicPath $ hsSourceDirs $ buildInfo executable
76
- | otherwise = []
77
- where
78
- executable = condTreeData $ snd $ fromJust res
79
- execsM = condExecutables gpd
80
- res =
81
- List. find
82
- (\ (_, cTree) -> do
83
- let execName = exeName $ condTreeData cTree
84
- execName == (mkUnqualComponentName $ T. unpack name)
85
- )
86
- execsM
77
+ sourceDirsExtractionExecutable name gpd = extractRelativeDirsFromStanza name gpd condExecutables buildInfo
87
78
88
- {- | Extracts the source directories of the test suite stanza with the given name.
89
- -}
90
- sourceDirsExtractionTestSuite :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
91
- sourceDirsExtractionTestSuite Nothing _ = []
92
- sourceDirsExtractionTestSuite (Just name) gpd
93
- | testName testSuite == (mkUnqualComponentName $ T. unpack name) = map getSymbolicPath $ hsSourceDirs $ testBuildInfo testSuite
94
- | otherwise = []
95
- where
96
- testSuite = condTreeData $ snd $ fromJust res
97
- testSuitesM = condTestSuites gpd
98
- res =
99
- List. find
100
- (\ (_, cTree) -> do
101
- let testsName = testName $ condTreeData cTree
102
- testsName == (mkUnqualComponentName $ T. unpack name)
103
- )
104
- testSuitesM
79
+ -- | Extracts the source directories of the test suite stanza with the given name.
80
+ sourceDirsExtractionTestSuite :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
81
+ sourceDirsExtractionTestSuite name gpd = extractRelativeDirsFromStanza name gpd condTestSuites testBuildInfo
105
82
106
- {- | Extracts the source directories of benchmark stanza with the given name.
107
- -}
108
- sourceDirsExtractionBenchmark :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
109
- sourceDirsExtractionBenchmark Nothing _ = []
110
- sourceDirsExtractionBenchmark (Just name) gpd
111
- | benchmarkName bMark == (mkUnqualComponentName $ T. unpack name) = map getSymbolicPath $ hsSourceDirs $ benchmarkBuildInfo bMark
83
+ -- | Extracts the source directories of benchmark stanza with the given name.
84
+ sourceDirsExtractionBenchmark :: Maybe T. Text -> GenericPackageDescription -> [FilePath ]
85
+ sourceDirsExtractionBenchmark name gpd = extractRelativeDirsFromStanza name gpd condBenchmarks benchmarkBuildInfo
86
+
87
+ extractRelativeDirsFromStanza ::
88
+ Maybe T. Text ->
89
+ GenericPackageDescription ->
90
+ (GenericPackageDescription -> [(UnqualComponentName , CondTree b c a )]) ->
91
+ (a -> BuildInfo ) ->
92
+ [FilePath ]
93
+ extractRelativeDirsFromStanza Nothing _ _ _ = []
94
+ extractRelativeDirsFromStanza (Just name) gpd getStanza getBuildInfo
95
+ | Just stanza <- stanzaM = map getSymbolicPath $ hsSourceDirs $ getBuildInfo stanza
112
96
| otherwise = []
113
- where
114
- bMark = condTreeData $ snd $ fromJust res
115
- bMarksM = condBenchmarks gpd
116
- res =
117
- List. find
118
- (\ (_, cTree) -> do
119
- let bMarkName = benchmarkName $ condTreeData cTree
120
- bMarkName == (mkUnqualComponentName $ T. unpack name)
121
- )
122
- bMarksM
97
+ where
98
+ stanzaM = fmap (condTreeData . snd ) res
99
+ allStanzasM = getStanza gpd
100
+ res =
101
+ List. find
102
+ ( \ (n, _) ->
103
+ n == (mkUnqualComponentName $ T. unpack name)
104
+ )
105
+ allStanzasM
123
106
124
107
{- | Extracts the source dirs from the library stanza in the cabal file using the GPD
125
108
and returns a list of path completions relative to any source dir which fit the passed prefix info.
126
109
-}
127
110
filePathsForExposedModules :: [FilePath ] -> Recorder (WithPriority Log ) -> CabalPrefixInfo -> IO [T. Text ]
128
111
filePathsForExposedModules srcDirs recorder prefInfo = do
129
- concatForM
130
- srcDirs
131
- ( \ dir -> do
132
- let pInfo =
133
- PathCompletionInfo
112
+ concatForM
113
+ srcDirs
114
+ ( \ dir -> do
115
+ let pInfo =
116
+ PathCompletionInfo
134
117
{ partialFileName = T. pack $ Posix. takeFileName prefix
135
- , partialFileDir = Posix. addTrailingPathSeparator $ Posix. takeDirectory prefix
118
+ , partialFileDir = Posix. addTrailingPathSeparator $ Posix. takeDirectory prefix
136
119
, workingDir = completionWorkingDir prefInfo FP. </> dir
137
120
}
138
- completions <- listFileCompletions recorder pInfo
139
- validExposedCompletions <- filterM (isValidExposedModulePath pInfo) completions
140
- let filePathCompletions = map (fpToExposedModulePath dir) validExposedCompletions
141
- toMatch = fromMaybe (partialFileName pInfo) $ T. stripPrefix " ./" $ partialFileName pInfo
142
- scored = Fuzzy. simpleFilter 1000 10 toMatch (map T. pack filePathCompletions)
143
- forM
144
- scored
145
- ( \ compl' -> do
146
- let compl = Fuzzy. original compl'
147
- fullFilePath <- mkExposedModulePathCompletion compl pInfo
148
- pure fullFilePath
149
- )
150
- )
151
- where
152
- prefix =
153
- exposedModulePathToFp
154
- $ completionPrefix prefInfo
155
- isValidExposedModulePath :: PathCompletionInfo -> FilePath -> IO Bool
156
- isValidExposedModulePath pInfo path = do
157
- let dir = mkCompletionDirectory pInfo
158
- fileExists <- doesFileExist (dir FP. </> path)
159
- pure $ not fileExists || FP. isExtensionOf " .hs" path
160
-
121
+ completions <- listFileCompletions recorder pInfo
122
+ validExposedCompletions <- filterM (isValidExposedModulePath pInfo) completions
123
+ let filePathCompletions = map (fpToExposedModulePath dir) validExposedCompletions
124
+ toMatch = fromMaybe (partialFileName pInfo) $ T. stripPrefix " ./" $ partialFileName pInfo
125
+ scored = Fuzzy. simpleFilter 1000 10 toMatch (map T. pack filePathCompletions)
126
+ forM
127
+ scored
128
+ ( \ compl' -> do
129
+ let compl = Fuzzy. original compl'
130
+ fullFilePath <- mkExposedModulePathCompletion compl pInfo
131
+ pure fullFilePath
132
+ )
133
+ )
134
+ where
135
+ prefix =
136
+ exposedModulePathToFp $
137
+ completionPrefix prefInfo
138
+ isValidExposedModulePath :: PathCompletionInfo -> FilePath -> IO Bool
139
+ isValidExposedModulePath pInfo path = do
140
+ let dir = mkCompletionDirectory pInfo
141
+ fileExists <- doesFileExist (dir FP. </> path)
142
+ pure $ not fileExists || FP. isExtensionOf " .hs" path
161
143
162
144
{- Takes a completed path and a pathCompletionInfo and generates the whole completed
163
145
filepath including the already written prefix using the cabal syntax for exposed modules.
@@ -177,11 +159,10 @@ mkExposedModulePathCompletion completion complInfo = do
177
159
path in exposed module syntax where the separators are '.' and the file ending is removed.
178
160
-}
179
161
fpToExposedModulePath :: FilePath -> FilePath -> FilePath
180
- fpToExposedModulePath srcDir cabalDir = T. unpack $ T. intercalate " ." $ fmap T. pack $ FP. splitDirectories fp
181
- where
182
- fp = fromMaybe cabalDir $ stripPrefix srcDir cabalDir
162
+ fpToExposedModulePath srcDir cabalDir = T. unpack $ T. intercalate " ." $ fmap T. pack $ FP. splitDirectories fp
163
+ where
164
+ fp = fromMaybe cabalDir $ stripPrefix srcDir cabalDir
183
165
184
- {- | Takes a path in the exposed module field and translates it to a filepath.
185
- -}
166
+ -- | Takes a path in the exposed module field and translates it to a filepath.
186
167
exposedModulePathToFp :: T. Text -> FilePath
187
168
exposedModulePathToFp fp = T. unpack $ T. replace " ." (T. singleton FP. pathSeparator) fp
0 commit comments