Skip to content

Commit 6a98874

Browse files
seanhessfendor
authored andcommitted
User-friendly error message when modules aren't listed in other-modules or exposed-modules
+ only show if isCabaltype + show prefixes
1 parent 2aecda9 commit 6a98874

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
@@ -68,6 +70,7 @@ import Development.IDE.Types.Location
6870
import Development.IDE.Types.Options
6971
import GHC.Check
7072
import qualified HIE.Bios as HieBios
73+
import qualified HIE.Bios.Cradle as HieBios
7174
import HIE.Bios.Environment hiding (getCacheDir)
7275
import HIE.Bios.Types hiding (Log)
7376
import qualified HIE.Bios.Types as HieBios
@@ -681,7 +684,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
681684
Left err -> do
682685
dep_info <- getDependencyInfo (maybeToList hieYaml)
683686
let ncfp = toNormalizedFilePath' cfp
684-
let res = (map (renderCradleError ncfp) err, Nothing)
687+
let res = (map (renderCradleError cradle ncfp) err, Nothing)
685688
void $ modifyVar' fileToFlags $
686689
Map.insertWith HM.union hieYaml (HM.singleton ncfp (res, dep_info))
687690
void $ modifyVar' filesMap $ HM.insert ncfp hieYaml
@@ -924,9 +927,80 @@ setCacheDirs recorder CacheDirs{..} dflags = do
924927
& maybe id setODir oCacheDir
925928

926929

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

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

0 commit comments

Comments
 (0)