Skip to content

Commit b759787

Browse files
committed
User-friendly error message when modules aren't listed in other-modules or exposed-modules
+ only show if isCabaltype + show prefixes
1 parent feb5965 commit b759787

File tree

1 file changed

+78
-4
lines changed

1 file changed

+78
-4
lines changed

ghcide/session-loader/Development/IDE/Session.hs

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ import Data.Bifunctor
3535
import qualified Data.ByteString.Base16 as B16
3636
import qualified Data.ByteString.Char8 as B
3737
import Data.Default
38+
import Data.Char (isLower)
3839
import Data.Either.Extra
3940
import Data.Function
4041
import Data.Hashable
4142
import qualified Data.HashMap.Strict as HM
4243
import Data.IORef
4344
import Data.List
45+
import Data.List.Extra (dropPrefix, split)
4446
import qualified Data.Map.Strict as Map
4547
import Data.Maybe
4648
import Data.Proxy
@@ -75,6 +77,7 @@ import Development.IDE.Types.Logger (Pretty (pretty),
7577
import Development.IDE.Types.Options
7678
import GHC.Check
7779
import qualified HIE.Bios as HieBios
80+
import qualified HIE.Bios.Cradle as HieBios
7881
import HIE.Bios.Environment hiding (getCacheDir)
7982
import HIE.Bios.Types hiding (Log)
8083
import qualified HIE.Bios.Types as HieBios
@@ -662,7 +665,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
662665
Left err -> do
663666
dep_info <- getDependencyInfo (maybeToList hieYaml)
664667
let ncfp = toNormalizedFilePath' cfp
665-
let res = (map (renderCradleError ncfp) err, Nothing)
668+
let res = (map (renderCradleError cradle ncfp) err, Nothing)
666669
void $ modifyVar' fileToFlags $
667670
Map.insertWith HM.union hieYaml (HM.singleton ncfp (res, dep_info))
668671
void $ modifyVar' filesMap $ HM.insert ncfp hieYaml
@@ -905,9 +908,80 @@ setCacheDirs recorder CacheDirs{..} dflags = do
905908
& maybe id setODir oCacheDir
906909

907910

908-
renderCradleError :: NormalizedFilePath -> CradleError -> FileDiagnostic
909-
renderCradleError nfp (CradleError _ _ec t) =
910-
ideErrorWithSource (Just "cradle") (Just DiagnosticSeverity_Error) nfp (T.unlines (map T.pack t))
911+
renderCradleError :: Cradle a -> NormalizedFilePath -> CradleError -> FileDiagnostic
912+
renderCradleError cradle nfp (CradleError _ _ec ms) =
913+
ideErrorWithSource (Just "cradle") (Just DiagnosticSeverity_Error) nfp $ T.unlines $ map T.pack userFriendlyMessage
914+
where
915+
916+
userFriendlyMessage :: [String]
917+
userFriendlyMessage
918+
| HieBios.isCabalCradle cradle = fromMaybe ms fileMissingMessage
919+
| otherwise = ms
920+
921+
fileMissingMessage :: Maybe [String]
922+
fileMissingMessage =
923+
multiCradleErrMessage <$> parseMultiCradleErr ms
924+
925+
-- | Information included in Multi Cradle error messages
926+
data MultiCradleErr = MultiCradleErr
927+
{ mcPwd :: FilePath
928+
, mcFilePath :: FilePath
929+
, mcPrefixes :: [(FilePath, String)]
930+
} deriving (Show)
931+
932+
-- | Attempt to parse a multi-cradle message
933+
parseMultiCradleErr :: [String] -> Maybe MultiCradleErr
934+
parseMultiCradleErr ms = do
935+
_ <- lineAfter "Multi Cradle: "
936+
wd <- lineAfter "pwd: "
937+
fp <- lineAfter "filepath: "
938+
ps <- prefixes
939+
pure $ MultiCradleErr wd fp ps
940+
941+
where
942+
lineAfter :: String -> Maybe String
943+
lineAfter pre = listToMaybe $ mapMaybe (stripPrefix pre) ms
944+
945+
prefixes :: Maybe [(FilePath, String)]
946+
prefixes = do
947+
pure $ mapMaybe tuple ms
948+
949+
tuple :: String -> Maybe (String, String)
950+
tuple line = do
951+
line' <- surround '(' line ')'
952+
[f, s] <- pure $ split (==',') line'
953+
pure (f, s)
954+
955+
-- extracts the string surrounded by required characters
956+
surround :: Char -> String -> Char -> Maybe String
957+
surround start s end = do
958+
guard (listToMaybe s == Just start)
959+
guard (listToMaybe (reverse s) == Just end)
960+
pure $ drop 1 $ take (length s - 1) s
961+
962+
963+
964+
965+
966+
967+
multiCradleErrMessage :: MultiCradleErr -> [String]
968+
multiCradleErrMessage e =
969+
[ "Loading the module '" <> moduleFileName <> "' failed. It seems that it is not listed in your .cabal file!"
970+
, "Perhaps you need to add `"<> moduleName <> "` to other-modules or exposed-modules" -- named 'example' in example.cabal."
971+
, "For more information, visit: https://cabal.readthedocs.io/en/3.4/developing-packages.html#modules-included-in-the-package"
972+
, ""
973+
] <> map prefix (mcPrefixes e)
974+
where
975+
localFilePath f = dropWhile (==pathSeparator) $ dropPrefix (mcPwd e) f
976+
moduleFileName = localFilePath $ mcFilePath e
977+
moduleName = intercalate "." $ map dropExtension $ dropWhile isSourceFolder $ splitDirectories moduleFileName
978+
isSourceFolder p = all isLower $ take 1 p
979+
prefix (f, r) = f <> " - " <> r
980+
981+
982+
983+
984+
911985

912986
-- See Note [Multi Cradle Dependency Info]
913987
type DependencyInfo = Map.Map FilePath (Maybe UTCTime)

0 commit comments

Comments
 (0)