Fix non canonicalized paths

This commit is contained in:
Daniel Gröber 2015-04-11 16:41:17 +02:00
parent 523f43c3c9
commit 6f59f07f00
3 changed files with 31 additions and 27 deletions

View File

@ -24,13 +24,16 @@ module Language.Haskell.GhcMod.HomeModuleGraph (
, findModulePath , findModulePath
, findModulePathSet , findModulePathSet
, fileModuleName , fileModuleName
, canonicalizeModulePath
, homeModuleGraph , homeModuleGraph
, updateHomeModuleGraph , updateHomeModuleGraph
, canonicalizeModuleGraph
, reachable , reachable
, moduleGraphToDot , moduleGraphToDot
) where ) where
import DriverPipeline import DriverPipeline
import DynFlags
import ErrUtils import ErrUtils
import Exception import Exception
import Finder import Finder
@ -45,14 +48,17 @@ import Control.Monad.State.Strict (execStateT)
import Control.Monad.State.Class import Control.Monad.State.Class
import Data.Maybe import Data.Maybe
import Data.Monoid import Data.Monoid
import Data.Traversable as T (mapM)
import Data.Map (Map) import Data.Map (Map)
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Set (Set) import Data.Set (Set)
import qualified Data.Set as Set import qualified Data.Set as Set
import System.FilePath import System.FilePath
import System.Directory
import Language.Haskell.GhcMod.Logging import Language.Haskell.GhcMod.Logging
import Language.Haskell.GhcMod.Logger import Language.Haskell.GhcMod.Logger
import Language.Haskell.GhcMod.PathsAndFiles
import Language.Haskell.GhcMod.Monad.Types import Language.Haskell.GhcMod.Monad.Types
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Gap (parseModuleHeader) import Language.Haskell.GhcMod.Gap (parseModuleHeader)
@ -111,12 +117,8 @@ reachable smp0 GmModuleGraph {..} = go smp0
pruneUnreachable :: Set ModulePath -> GmModuleGraph -> GmModuleGraph pruneUnreachable :: Set ModulePath -> GmModuleGraph -> GmModuleGraph
pruneUnreachable smp0 gmg@GmModuleGraph {..} = let pruneUnreachable smp0 gmg@GmModuleGraph {..} = let
r = reachable smp0 gmg r = reachable smp0 gmg
rfn = Set.map mpPath r
rmn = Set.map mpModule r
in in
GmModuleGraph { GmModuleGraph {
gmgFileMap = Map.filterWithKey (\k _ -> k `Set.member` rfn) gmgFileMap,
gmgModuleMap = Map.filterWithKey (\k _ -> k `Set.member` rmn) gmgModuleMap,
gmgGraph = Map.filterWithKey (\k _ -> k `Set.member` r) gmgGraph gmgGraph = Map.filterWithKey (\k _ -> k `Set.member` r) gmgGraph
} }
@ -143,29 +145,37 @@ find env mn = liftIO $ do
res <- findHomeModule env mn res <- findHomeModule env mn
case res of case res of
-- TODO: handle SOURCE imports (hs-boot stuff): addBootSuffixLocn loc -- TODO: handle SOURCE imports (hs-boot stuff): addBootSuffixLocn loc
Found loc@ModLocation { ml_hs_file = Just _ } _mod -> do Found loc@ModLocation { ml_hs_file = Just _ } _mod ->
return $ normalise <$> ml_hs_file loc return $ normalise <$> ml_hs_file loc
_ -> return Nothing _ -> return Nothing
canonicalizeModulePath (ModulePath mn fp) = ModulePath mn <$> canonicalizePath fp
canonicalizeModuleGraph :: MonadIO m => GmModuleGraph -> m GmModuleGraph
canonicalizeModuleGraph GmModuleGraph {..} = liftIO $ do
GmModuleGraph . Map.fromList <$> mapM fmg (Map.toList gmgGraph)
where
fmg (mp, smp) = liftM2 (,) (canonicalizeModulePath mp) (Set.fromList <$> mapM canonicalizeModulePath (Set.toList smp))
updateHomeModuleGraph :: (IOish m, GmLog m, GmEnv m) updateHomeModuleGraph :: (IOish m, GmLog m, GmEnv m)
=> HscEnv => HscEnv
-> GmModuleGraph -> GmModuleGraph
-> Set ModulePath -- ^ Initial set of modules -> Set ModulePath -- ^ Initial set of modules
-> Set ModulePath -- ^ Updated set of modules -> Set ModulePath -- ^ Updated set of modules
-> m GmModuleGraph -> m GmModuleGraph
updateHomeModuleGraph env GmModuleGraph {..} smp usmp = do updateHomeModuleGraph env GmModuleGraph {..} smp sump = do
-- TODO: It would be good if we could retain information about modules that -- TODO: It would be good if we could retain information about modules that
-- stop to compile after we've already successfully parsed them at some -- stop to compile after we've already successfully parsed them at some
-- point. Figure out a way to delete the modules about to be updated only -- point. Figure out a way to delete the modules about to be updated only
-- after we're sure they won't fail to parse .. or something. Should probably -- after we're sure they won't fail to parse .. or something. Should probably
-- push this whole prune logic deep into updateHomeModuleGraph' -- push this whole prune logic deep into updateHomeModuleGraph'
(pruneUnreachable smp . sGraph) `liftM` runS (updateHomeModuleGraph' env usmp) (pruneUnreachable smp . sGraph) `liftM` runS (updateHomeModuleGraph' env sump)
where where
runS = flip execStateT defaultS { sGraph = graph' } runS = flip execStateT defaultS { sGraph = graph' }
graph' = GmModuleGraph { graph' = GmModuleGraph {
gmgFileMap = Set.foldr (Map.delete . mpPath) gmgFileMap usmp, gmgGraph = Set.foldr Map.delete gmgGraph sump
gmgModuleMap = Set.foldr (Map.delete . mpModule) gmgModuleMap usmp,
gmgGraph = Set.foldr Map.delete gmgGraph usmp
} }
mkFileMap :: Set ModulePath -> Map FilePath ModulePath mkFileMap :: Set ModulePath -> Map FilePath ModulePath
@ -181,7 +191,6 @@ updateHomeModuleGraph'
-> m () -> m ()
updateHomeModuleGraph' env smp0 = do updateHomeModuleGraph' env smp0 = do
go `mapM_` Set.toList smp0 go `mapM_` Set.toList smp0
where where
go :: ModulePath -> m () go :: ModulePath -> m ()
go mp = do go mp = do
@ -192,8 +201,6 @@ updateHomeModuleGraph' env smp0 = do
smp <- collapseMaybeSet `liftM` step mp smp <- collapseMaybeSet `liftM` step mp
graphUnion GmModuleGraph { graphUnion GmModuleGraph {
gmgFileMap = mkFileMap smp,
gmgModuleMap = mkModuleMap smp,
gmgGraph = Map.singleton mp smp gmgGraph = Map.singleton mp smp
} }

View File

@ -142,15 +142,15 @@ runGmlTWith efnmns' mdf wrapper action = do
let (fns, mns) = partitionEithers efnmns' let (fns, mns) = partitionEithers efnmns'
ccfns = map (cradleCurrentDir crdl </>) fns ccfns = map (cradleCurrentDir crdl </>) fns
cfns <- liftIO $ mapM canonicalizePath ccfns cfns <- liftIO $ mapM canonicalizePath ccfns
let rfns = map (makeRelative $ cradleRootDir crdl) cfns let serfnmn = Set.fromList $ map Right mns ++ map Left cfns
serfnmn = Set.fromList $ map Right mns ++ map Left rfns
opts <- targetGhcOptions crdl serfnmn opts <- targetGhcOptions crdl serfnmn
let opts' = opts ++ ghcUserOptions let opts' = opts ++ ghcUserOptions
initSession opts' $ initSession opts' $
setModeSimple >>> setEmptyLogger >>> mdf setModeSimple >>> setEmptyLogger >>> mdf
let rfns = map (makeRelative $ cradleRootDir crdl) cfns
unGmlT $ wrapper $ do unGmlT $ wrapper $ do
loadTargets (map moduleNameString mns ++ rfns) loadTargets (map moduleNameString mns ++ rfns)
action action
@ -268,7 +268,7 @@ resolveGmComponent mums c@GmComponent {..} = do
Nothing -> return simp Nothing -> return simp
Just ums -> Set.fromList . catMaybes <$> mapM (resolveModule env srcDirs) ums Just ums -> Set.fromList . catMaybes <$> mapM (resolveModule env srcDirs) ums
mg' <- updateHomeModuleGraph env mg simp sump mg' <- canonicalizeModuleGraph =<< updateHomeModuleGraph env mg simp sump
return $ c { gmcEntrypoints = simp, gmcHomeModuleGraph = mg' } return $ c { gmcEntrypoints = simp, gmcHomeModuleGraph = mg' }
@ -285,13 +285,14 @@ resolveEntrypoint Cradle {..} c@GmComponent {..} =
resolveModule :: MonadIO m => resolveModule :: MonadIO m =>
HscEnv -> [FilePath] -> Either FilePath ModuleName -> m (Maybe ModulePath) HscEnv -> [FilePath] -> Either FilePath ModuleName -> m (Maybe ModulePath)
resolveModule env _srcDirs (Right mn) = liftIO $ findModulePath env mn resolveModule env _srcDirs (Right mn) =
liftIO $ traverse canonicalizeModulePath =<< findModulePath env mn
resolveModule env srcDirs (Left fn') = liftIO $ do resolveModule env srcDirs (Left fn') = liftIO $ do
mfn <- findFile' srcDirs fn' mfn <- findFile' srcDirs fn'
case mfn of case mfn of
Nothing -> return Nothing Nothing -> return Nothing
Just fn'' -> do Just fn'' -> do
let fn = normalise fn'' fn <- canonicalizePath fn''
emn <- fileModuleName env fn emn <- fileModuleName env fn
return $ case emn of return $ case emn of
Left _ -> Nothing Left _ -> Nothing

View File

@ -177,8 +177,6 @@ data GmLogLevel = GmPanic
type PkgDb = (Map Package PackageConfig) type PkgDb = (Map Package PackageConfig)
data GmModuleGraph = GmModuleGraph { data GmModuleGraph = GmModuleGraph {
gmgFileMap :: Map FilePath ModulePath,
gmgModuleMap :: Map ModuleName ModulePath,
gmgGraph :: Map ModulePath (Set ModulePath) gmgGraph :: Map ModulePath (Set ModulePath)
} deriving (Eq, Ord, Show, Read, Generic, Typeable) } deriving (Eq, Ord, Show, Read, Generic, Typeable)
@ -204,14 +202,12 @@ instance Serialize GmModuleGraph where
intToMp i = fromJust $ Map.lookup i impm intToMp i = fromJust $ Map.lookup i impm
mpGraph :: Map ModulePath (Set ModulePath) mpGraph :: Map ModulePath (Set ModulePath)
mpGraph = Map.map (Set.map intToMp) $ Map.mapKeys intToMp graph mpGraph = Map.map (Set.map intToMp) $ Map.mapKeys intToMp graph
mpFm = Map.fromList $ map (mpPath &&& id) $ Map.keys mpim return $ GmModuleGraph mpGraph
mpMn = Map.fromList $ map (mpModule &&& id) $ Map.keys mpim
return $ GmModuleGraph mpFm mpMn mpGraph
instance Monoid GmModuleGraph where instance Monoid GmModuleGraph where
mempty = GmModuleGraph mempty mempty mempty mempty = GmModuleGraph mempty
mappend (GmModuleGraph a b c) (GmModuleGraph a' b' c') = mappend (GmModuleGraph a) (GmModuleGraph a') =
GmModuleGraph (a <> a') (b <> b') (Map.unionWith Set.union c c') GmModuleGraph (Map.unionWith Set.union a a')
data GmComponentType = GMCRaw data GmComponentType = GMCRaw
| GMCResolved | GMCResolved