Skip to content

Commit c856c6a

Browse files
committed
fix: find module not yet written on disk but are part of known files
1 parent e6ce0e1 commit c856c6a

File tree

4 files changed

+75
-18
lines changed

4 files changed

+75
-18
lines changed

ghcide-test/exe/CompletionTests.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import Test.Hls.FileSystem (file, text)
3232
import Test.Hls.Util
3333
import Test.Tasty
3434
import Test.Tasty.HUnit
35+
import Debug.Pretty.Simple
3536

3637
tests :: TestTree
3738
tests

ghcide/src/Development/IDE/Core/Rules.hs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ module Development.IDE.Core.Rules(
5656
GhcSessionDepsConfig(..),
5757
Log(..),
5858
DisplayTHWarning(..),
59+
extendModuleMapWithKnownTargets,
5960
) where
6061

6162
import Control.Applicative
@@ -176,11 +177,10 @@ import System.Info.Extra (isWindows)
176177

177178
import qualified Data.IntMap as IM
178179
import GHC.Fingerprint
179-
import Text.Pretty.Simple
180180
import qualified Data.Map.Strict as Map
181181
import System.FilePath (takeExtension, takeFileName, normalise, dropTrailingPathSeparator, dropExtension, splitDirectories)
182182
import Data.Char (isUpper)
183-
import System.Directory.Extra (listFilesRecursive, listFilesInside)
183+
import System.Directory.Extra (listFilesInside)
184184
import System.IO.Unsafe
185185

186186
data Log
@@ -331,7 +331,10 @@ getLocatedImportsRule recorder =
331331
let dflags = hsc_dflags env
332332
opt <- getIdeOptions
333333

334-
moduleMaps <- use_ GetModulesPaths file
334+
moduleMaps' <- use_ GetModulesPaths file
335+
336+
moduleMaps <- extendModuleMapWithKnownTargets file moduleMaps'
337+
335338
(diags, imports') <- fmap unzip $ forM imports $ \(isSource, (mbPkgName, modName)) -> do
336339

337340
diagOrImp <- locateModule moduleMaps (hscSetFlags dflags env) import_dirs (optExtensions opt) modName mbPkgName isSource
@@ -663,16 +666,64 @@ getModulesPathsRule recorder = defineEarlyCutoff (cmapWithPrio LogShake recorder
663666
let res = (mconcat a, mconcat b)
664667
liftIO $ atomically $ modifyTVar' cacheVar (Map.insert (envUnique env_eq) res)
665668

666-
pure (mempty, ([], Just $ (mconcat a, mconcat b)))
669+
pure (mempty, ([], Just res))
670+
671+
-- | Extend the map from module name to filepath (exiting on the drive) with
672+
-- the list of known targets provided by HLS
673+
--
674+
-- These known targets are files which were recently created and not yet saved
675+
-- to the filesystem.
676+
--
677+
-- TODO: for now the implementation is O(number_of_known_files *
678+
-- number_of_include_path) which is inacceptable and should be addressed.
679+
extendModuleMapWithKnownTargets
680+
:: NormalizedFilePath -> (Map.Map ModuleName (UnitId, NormalizedFilePath), Map.Map ModuleName (UnitId, NormalizedFilePath))
681+
-> Action (Map.Map ModuleName (UnitId, NormalizedFilePath), Map.Map ModuleName (UnitId, NormalizedFilePath))
682+
extendModuleMapWithKnownTargets file (notSourceModules, sourceModules) = do
683+
KnownTargets targetsMap <- useNoFile_ GetKnownTargets
684+
env_eq <- use_ GhcSession file
685+
let env = hscEnv env_eq
686+
let import_dirs = map (second homeUnitEnv_dflags) $ hugElts $ hsc_HUG env
687+
opt <- getIdeOptions
688+
let exts = (optExtensions opt)
689+
let acceptedExtensions = concatMap (\x -> ['.':x, '.':x <> "-boot"]) exts
690+
691+
let notSourceModuleP = Map.fromList $ do
692+
(u, dyn) <- import_dirs
693+
-- TODO: avoid using so much `FilePath` logic AND please please,
694+
-- normalize earlier.
695+
--
696+
-- The normalise here is in order to remove the trailing `.` which
697+
-- could break the comparison later.
698+
(normalise -> dir') <- importPaths dyn
699+
let dirComponents = splitDirectories dir'
700+
let dir_number_directories = length dirComponents
701+
-- TODO: the _target may represents something different than the path
702+
-- stored in paths. This need to be investigated.
703+
(_target, paths) <- HM.toList targetsMap
704+
-- TODO: I have no idea why there is multiple path here
705+
guard $ length paths > 0
706+
let path = head $ toList paths
707+
let pathString = fromNormalizedFilePath path
708+
let pathComponents = splitDirectories pathString
709+
710+
-- Ensure this file is in the directory
711+
guard $ dirComponents `isPrefixOf` pathComponents
712+
713+
-- Ensure that this extension is accepted
714+
guard $ takeExtension pathString `elem` acceptedExtensions
715+
let modName = mkModuleName (intercalate "." $ drop dir_number_directories (splitDirectories (dropExtension pathString)))
716+
pure (modName, (u, path))
717+
718+
let notSourceModules' = notSourceModules <> notSourceModuleP
719+
720+
pure $!! (notSourceModules', sourceModules)
721+
667722

668723
dependencyInfoForFiles :: [NormalizedFilePath] -> Action (BS.ByteString, DependencyInformation)
669724
dependencyInfoForFiles fs = do
670-
-- liftIO $ print ("fs length", length fs)
671725
(rawDepInfo, bm) <- rawDependencyInformation fs
672-
-- liftIO $ print ("ok with raw deps")
673-
-- liftIO $ pPrint rawDepInfo
674726
let (all_fs, _all_ids) = unzip $ HM.toList $ pathToIdMap $ rawPathIdMap rawDepInfo
675-
-- liftIO $ print ("all_fs length", length all_fs)
676727
msrs <- uses GetModSummaryWithoutTimestamps all_fs
677728
let mss = map (fmap msrModSummary) msrs
678729
let deps = map (\i -> IM.lookup (getFilePathId i) (rawImports rawDepInfo)) _all_ids

ghcide/src/Development/IDE/Import/FindImports.hs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import GHC.Types.PkgQual
2626
import GHC.Unit.State
2727
import Data.Map.Strict (Map)
2828
import qualified Data.Map.Strict as Map
29+
import qualified Data.HashMap.Strict as HM
30+
import qualified Data.HashSet as HashSet
31+
import qualified Development.IDE.Types.KnownTargets as Shake
2932

3033

3134
#if MIN_VERSION_ghc(9,11,0)
@@ -85,7 +88,7 @@ mkImportDirs _env (i, flags) = Just (i, (importPaths flags, reexportedModules fl
8588
locateModule
8689
:: MonadIO m
8790
=> (Map ModuleName (UnitId, NormalizedFilePath),Map ModuleName (UnitId, NormalizedFilePath))
88-
-> HscEnv
91+
-> HscEnv
8992
-> [(UnitId, DynFlags)] -- ^ Import directories
9093
-> [String] -- ^ File extensions
9194
-> Located ModuleName -- ^ Module name
@@ -161,15 +164,15 @@ locateModule moduleMaps@(moduleMap, moduleMapSource) env comp_info exts modName
161164
return $ Right $ FileImport $ ArtifactsLocation file (Just loc) (not isSource) (Just genMod)
162165

163166
lookupLocal moduleMaps@(moduleMapSource, moduleMap) uid dirs reexports = do
164-
-- mbFile <- locateModuleFile [(uid, dirs, reexports)] exts targetFor isSource $ unLoc modName
165-
let mbFile = case Map.lookup (unLoc modName) (if isSource then moduleMapSource else moduleMap) of
166-
Nothing -> LocateNotFound
167-
Just (uid, file) -> LocateFoundFile uid file
168-
case mbFile of
169-
LocateNotFound -> return $ Left $ notFoundErr env modName $ LookupNotFound []
170-
-- Lookup again with the perspective of the unit reexporting the file
171-
LocateFoundReexport uid' -> locateModule moduleMaps (hscSetActiveUnitId uid' env) comp_info exts modName noPkgQual isSource
172-
LocateFoundFile uid' file -> toModLocation uid' file
167+
-- mbFile <- locateModuleFile [(uid, dirs, reexports)] exts targetFor isSource $ unLoc modName
168+
let mbFile = case Map.lookup (unLoc modName) (if isSource then moduleMapSource else moduleMap) of
169+
Nothing -> LocateNotFound
170+
Just (uid, file) -> LocateFoundFile uid file
171+
case mbFile of
172+
LocateNotFound -> return $ Left $ notFoundErr env modName $ LookupNotFound []
173+
-- Lookup again with the perspective of the unit reexporting the file
174+
LocateFoundReexport uid' -> locateModule moduleMaps (hscSetActiveUnitId uid' env) comp_info exts modName noPkgQual isSource
175+
LocateFoundFile uid' file -> toModLocation uid' file
173176

174177
lookupInPackageDB = do
175178
case Compat.lookupModuleWithSuggestions env (unLoc modName) mbPkgName of

haskell-language-server.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,6 +2190,8 @@ test-suite ghcide-tests
21902190
, text-rope
21912191
, unordered-containers
21922192
, hls-test-utils == 2.12.0.0
2193+
, pretty-simple
2194+
, lsp-test
21932195

21942196
if impl(ghc <9.3)
21952197
build-depends: ghc-typelits-knownnat

0 commit comments

Comments
 (0)