@@ -13,11 +13,11 @@ import Distribution.Helper (Package, projectPackages, pUnits,
1313 unChModuleName , Ex (.. ), ProjLoc (.. ),
1414 QueryEnv , mkQueryEnv , runQuery ,
1515 Unit , unitInfo , uiComponents ,
16- ChEntrypoint (.. ))
16+ ChEntrypoint (.. ), uComponentName )
1717import Distribution.Helper.Discover (findProjects , getDefaultDistDir )
1818import Data.Char (toLower )
1919import Data.Function ((&) )
20- import Data.List (isPrefixOf , isInfixOf , sortOn , find )
20+ import Data.List (isPrefixOf , isInfixOf , sortOn , find , intercalate )
2121import qualified Data.List.NonEmpty as NonEmpty
2222import Data.List.NonEmpty (NonEmpty )
2323import qualified Data.Map as M
@@ -45,10 +45,13 @@ import System.Process (readCreateProcessWithExitCode, shell)
4545findLocalCradle :: FilePath -> IO Cradle
4646findLocalCradle fp = do
4747 cradleConf <- BIOS. findCradle fp
48- case cradleConf of
49- Just yaml -> BIOS. loadCradle yaml
48+ crdl <- case cradleConf of
49+ Just yaml -> do
50+ debugm $ " Found \" " ++ yaml ++ " \" for \" " ++ fp ++ " \" "
51+ BIOS. loadCradle yaml
5052 Nothing -> cabalHelperCradle fp
51-
53+ logm $ " Module \" " ++ fp ++ " \" is loaded by Cradle: " ++ show crdl
54+ return crdl
5255-- | Check if the given cradle is a stack cradle.
5356-- This might be used to determine the GHC version to use on the project.
5457-- If it is a stack-cradle, we have to use `stack path --compiler-exe`
@@ -508,7 +511,7 @@ cabalHelperCradle file = do
508511 debugm $ " Relative Module FilePath: " ++ relativeFp
509512 getComponent env (toList units) relativeFp
510513 >>= \ case
511- Just comp -> do
514+ Right comp -> do
512515 let fs' = getFlags comp
513516 let fs = map (fixImportDirs root) fs'
514517 let targets = getTargets comp relativeFp
@@ -520,11 +523,11 @@ cabalHelperCradle file = do
520523 ComponentOptions { componentOptions = ghcOptions
521524 , componentDependencies = []
522525 }
523- Nothing -> return
526+ Left err -> return
524527 $ CradleFail
525528 $ CradleError
526529 (ExitFailure 2 )
527- [" Could not obtain flags for " ++ fp ]
530+ [err ]
528531
529532-- | Get the component the given FilePath most likely belongs to.
530533-- Lazily ask units whether the given FilePath is part of one of their
@@ -534,25 +537,59 @@ cabalHelperCradle file = do
534537-- The given FilePath must be relative to the Root of the project
535538-- the given units belong to.
536539getComponent
537- :: QueryEnv pt -> [Unit pt ] -> FilePath -> IO (Maybe ChComponentInfo )
538- getComponent _env [] _fp = return Nothing
539- getComponent env (unit : units) fp =
540- try (runQuery (unitInfo unit) env) >>= \ case
541- Left (e :: IOException ) -> do
542- warningm $ " Catching and swallowing an IOException: " ++ show e
543- warningm
544- $ " The Exception was thrown in the context of finding"
545- ++ " a component for \" "
546- ++ fp
547- ++ " \" in the unit: "
548- ++ show unit
549- getComponent env units fp
550- Right ui -> do
551- let components = M. elems (uiComponents ui)
552- debugm $ " Unit Info: " ++ show ui
553- case find (fp `partOfComponent` ) components of
554- Nothing -> getComponent env units fp
555- comp -> return comp
540+ :: forall pt . QueryEnv pt -> [Unit pt ] -> FilePath -> IO (Either String ChComponentInfo )
541+ getComponent env unitCandidates fp = getComponent' [] [] unitCandidates >>=
542+ \ case
543+ (tried, failed, Nothing ) -> return (Left $ buildErrorMsg tried failed)
544+ (_, _, Just comp) -> return (Right comp)
545+ where
546+ getComponent' :: [Unit pt ] -> [Unit pt ] -> [Unit pt ] -> IO ([Unit pt ], [Unit pt ], Maybe ChComponentInfo )
547+ getComponent' triedUnits failedUnits [] = return (triedUnits, failedUnits, Nothing )
548+ getComponent' triedUnits failedUnits (unit : units) =
549+ try (runQuery (unitInfo unit) env) >>= \ case
550+ Left (e :: IOException ) -> do
551+ warningm $ " Catching and swallowing an IOException: " ++ show e
552+ warningm
553+ $ " The Exception was thrown in the context of finding"
554+ ++ " a component for \" "
555+ ++ fp
556+ ++ " \" in the unit: "
557+ ++ show unit
558+ getComponent' triedUnits (unit: failedUnits) units
559+ Right ui -> do
560+ let components = M. elems (uiComponents ui)
561+ debugm $ " Unit Info: " ++ show ui
562+ case find (fp `partOfComponent` ) components of
563+ Nothing -> getComponent' (unit: triedUnits) failedUnits units
564+ comp -> return (triedUnits, failedUnits, comp)
565+
566+ buildErrorMsg :: [Unit pt ] -> [Unit pt ] -> String
567+ buildErrorMsg triedUnits failedUnits = unlines $
568+ [ " Could not obtain flags for: \" " ++ fp ++ " \" ." ]
569+ ++
570+ [ unlines
571+ [ " The given File was not part of any component."
572+ , " No component exposes this module, we tried the following:"
573+ , intercalate " ," (map showUnitInfo triedUnits)
574+ , " If you dont know how to expose a module take a look at: "
575+ , " https://www.haskell.org/cabal/users-guide/developing-packages.html"
576+ ]
577+ | not ( null triedUnits)
578+ ]
579+ ++
580+ [ unlines
581+ [ " We could not build all components."
582+ , " If one of these components exposes the module, make sure these compile."
583+ , " The following components failed to compile:"
584+ , intercalate " ," (map showUnitInfo failedUnits)
585+ ]
586+ | not (null failedUnits)
587+ ]
588+
589+ -- TODO: this is terrible
590+ showUnitInfo :: Unit pt -> String
591+ showUnitInfo unit = maybe (show unit) show (uComponentName unit)
592+
556593
557594-- | Check whether the given FilePath is part of the Component.
558595-- A FilePath is part of the Component if and only if:
0 commit comments