Commit a3fb5d8e authored by Oleg Grenrus's avatar Oleg Grenrus
Browse files

Improve printing of parsing .cabal files even further

- Separate the logic into own module
- Use same function in `cabal check` codepath
- Tweak the output a little more
parent 86f5e0c7
......@@ -16,9 +16,11 @@ module Distribution.Client.Check (
check
) where
import Distribution.Client.Compat.Prelude
import Prelude ()
import Distribution.Client.Utils.Parsec (renderParseError)
import Distribution.PackageDescription (GenericPackageDescription)
import Distribution.PackageDescription.Check
import Distribution.PackageDescription.Configuration (flattenPackageDescription)
......@@ -42,7 +44,7 @@ readGenericPackageDescriptionCheck verbosity fpath = do
case result of
Left (_, errors) -> do
traverse_ (warn verbosity . showPError fpath) errors
die' verbosity $ "Failed parsing \"" ++ fpath ++ "\"."
die' verbosity $ renderParseError fpath bs errors warnings
Right x -> return (warnings, x)
-- | Note: must be called with the CWD set to the directory containing
......
......@@ -74,6 +74,7 @@ import Distribution.Client.Config
import Distribution.Client.HttpUtils
( HttpTransport, configureTransport, transportCheckHttps
, downloadURI )
import Distribution.Client.Utils.Parsec (renderParseError)
import Distribution.Solver.Types.SourcePackage
import Distribution.Solver.Types.Settings
......@@ -93,7 +94,7 @@ import Distribution.PackageDescription.Parsec
import Distribution.Parsec.ParseResult
( runParseResult )
import Distribution.Parsec.Common as NewParser
( PError (..), PWarning, showPError, showPWarning, Position (..), zeroPos)
( PError, PWarning, showPWarning)
import Distribution.Pretty ()
import Distribution.Types.SourceRepo
( SourceRepo(..), RepoType(..), )
......@@ -110,7 +111,7 @@ import Distribution.Simple.InstallDirs
( PathTemplate, fromPathTemplate
, toPathTemplate, substPathTemplate, initialPathTemplateEnv )
import Distribution.Simple.Utils
( die', warn, notice, info, createDirectoryIfMissingVerbose, fromUTF8BS )
( die', warn, notice, info, createDirectoryIfMissingVerbose )
import Distribution.Client.Utils
( determineNumJobs )
import Distribution.Utils.NubList
......@@ -133,7 +134,6 @@ import Control.Monad.Trans (liftIO)
import Control.Exception
import Data.Either
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as Map
import Data.Set (Set)
......@@ -1245,33 +1245,9 @@ instance Exception CabalFileParseError
displayException = renderCabalFileParseError
#endif
renderCabalFileParseError :: CabalFileParseError -> String
renderCabalFileParseError (CabalFileParseError filePath contents errors _ warnings) =
"Errors encountered when parsing cabal file " <> filePath <> ":\n\n"
<> renderedErrors
<> renderedWarnings
where
ls = BS8.lines contents
nths :: Int -> [a] -> [a]
nths n | n <= 0 = take 2
nths n = take 3 . drop (n - 1)
renderedErrors = concatMap renderError errors
renderedWarnings = concatMap (NewParser.showPWarning filePath) warnings
renderError e@(PError pos@(Position row _col) _)
-- if position is 0:0, then it doens't make sense to show input
| pos == zeroPos = NewParser.showPError filePath e
| otherwise = NewParser.showPError filePath e ++ "\n" ++
unlines (zipWith formatInputLine (nths (row - 1) ls) [row - 1 ..])
formatInputLine bs l =
showN l ++ " | " ++ fromUTF8BS bs
showN n = let s = show n in replicate (5 - length s) ' ' ++ s
renderParseError filePath contents errors warnings
-- | Wrapper for the @.cabal@ file parser. It reports warnings on higher
-- verbosity levels and throws 'CabalFileParseError' on failure.
......
module Distribution.Client.Utils.Parsec (
renderParseError,
) where
import Distribution.Client.Compat.Prelude
import Prelude ()
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
import Distribution.Parsec.Common
(PError (..), PWarning (..), Position (..), showPError, showPWarning, zeroPos)
import Distribution.Simple.Utils (fromUTF8BS)
-- | Render parse error highlighting the part of the input file.
renderParseError
:: FilePath
-> BS.ByteString
-> [PError]
-> [PWarning]
-> String
renderParseError filepath contents errors warnings = unlines $
[ "Errors encountered when parsing cabal file " <> filepath <> ":"
]
++ renderedErrors
++ renderedWarnings
where
-- lines of the input file.
ls = BS8.lines contents
nths :: Int -> [a] -> [a]
nths n | n <= 0 = take 2
nths n = take 3 . drop (n - 1)
-- empty line before each error and warning
renderedErrors = concatMap (prepend . renderError) errors
renderedWarnings = concatMap (prepend . renderWarning) warnings
prepend = ("" :)
renderError :: PError -> [String]
renderError e@(PError pos@(Position row _col) _)
-- if position is 0:0, then it doesn't make sense to show input
-- looks like, Parsec errors have line-feed in them
| pos == zeroPos = [trim $ showPError filepath e]
| otherwise = [trim $ showPError filepath e, ""] ++
zipWith formatInputLine (nths (row - 1) ls) [row - 1 ..]
-- sometimes there are (especially trailing) newlines.
trim = dropWhile (== '\n') . reverse . dropWhile (== '\n') . reverse
renderWarning :: PWarning -> [String]
renderWarning w@(PWarning _ pos@(Position row _col) _)
| pos == zeroPos = [showPWarning filepath w]
| otherwise = [showPWarning filepath w, ""] ++
zipWith formatInputLine (nths (row - 1) ls) [row - 1 ..]
-- format line: prepend the given line number
formatInputLine :: BS.ByteString -> Int -> String
formatInputLine bs l =
showN l ++ " | " ++ fromUTF8BS bs
-- hopefully we don't need to work with over 99999 lines .cabal files
-- at that point small glitches in error messages are hopefully fine.
showN n = let s = show n in replicate (5 - length s) ' ' ++ s
......@@ -243,6 +243,7 @@ executable cabal
Distribution.Client.Utils
Distribution.Client.Utils.Assertion
Distribution.Client.Utils.Json
Distribution.Client.Utils.Parsec
Distribution.Client.VCS
Distribution.Client.Win32SelfUpgrade
Distribution.Client.World
......
......@@ -169,6 +169,7 @@ Version: 2.5.0.0
Distribution.Client.Utils
Distribution.Client.Utils.Assertion
Distribution.Client.Utils.Json
Distribution.Client.Utils.Parsec
Distribution.Client.VCS
Distribution.Client.Win32SelfUpgrade
Distribution.Client.World
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment