summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstuebinm2021-09-17 23:50:45 +0200
committerstuebinm2021-09-17 23:50:45 +0200
commitbfe45dc4996537b72436f4041d0ca819aa3444e1 (patch)
tree70e4966273b5447159bf39b4556e02affe911801
parent7a9226d84cf9dde33d0fc3e7852a22c36ab1c39b (diff)
(somewhat) reasonable representation of parse errors
This makes map loading (and parsing) part of the linter, and also makes it return "general lints" and nothing else in case that failed. Possibly a sum type would be nicer here, but I guess it's not really important since everything ends up as json anyways?
-rw-r--r--lib/CheckMap.hs47
-rw-r--r--lib/LintWriter.hs11
-rw-r--r--src/Main.hs9
3 files changed, 44 insertions, 23 deletions
diff --git a/lib/CheckMap.hs b/lib/CheckMap.hs
index af80295..97e6a8c 100644
--- a/lib/CheckMap.hs
+++ b/lib/CheckMap.hs
@@ -1,36 +1,54 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Module that contains the high-level checking functions
-module CheckMap where
+module CheckMap (loadAndLintMap) where
+import Control.Monad.Trans.Writer (WriterT (runWriterT))
+import Data.Aeson (ToJSON)
+import Data.Map (Map, fromList, toList)
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Vector as V
-
-import Control.Monad.Trans.Writer
-import Data.Aeson (ToJSON)
-import Data.Map (Map, fromList, toList)
import GHC.Generics (Generic)
+
import LintWriter (Hint (..), Level (..),
- LintResult (..), LintWriter)
+ LintResult (..), LintWriter, hint)
import Properties (checkProperty)
-import Tiled2
+import Tiled2 (Layer (layerName, layerProperties),
+ Tiledmap (tiledmapLayers),
+ loadTiledmap)
import Util (showText)
--- | What this linter produces
+-- | What this linter produces: lints for a single map
data MapResult a = MapResult
- { mapresultLayer :: Map Text (LintResult a)
+ { mapresultLayer :: Maybe (Map Text (LintResult a))
, mapresultGeneral :: [Hint]
} deriving (Generic, ToJSON)
--- | the main thing. runs the linter and everything
+
+
+-- | this module's raison d'ĂȘtre
+loadAndLintMap :: FilePath -> IO (MapResult ())
+loadAndLintMap path = loadTiledmap path >>= pure . \case
+ Left err -> MapResult
+ { mapresultLayer = Nothing
+ , mapresultGeneral =
+ [ hint Fatal . T.pack $
+ path <> ": parse error (probably invalid json/not a tiled map): " <> err
+ ]
+ }
+ Right waMap ->
+ runLinter waMap
+
+-- | lint a loaded map
runLinter :: Tiledmap -> MapResult ()
runLinter tiledmap = MapResult
- { mapresultLayer = layer
+ { mapresultLayer = Just layer
, mapresultGeneral = [] -- no general lints for now
}
where
@@ -47,12 +65,15 @@ checkLayer layer =
-- this instance of show produces a reasonably human-readable
-- list of lints that can be shown e.g. on a console
instance Show a => Show (MapResult a) where
- show mapResult = concat prettyLayer
+ show mapResult = concat $ prettyGeneral <> prettyLayer
where
+ -- TODO: this can be simplified further
prettyLayer :: [String]
prettyLayer = mapMaybe
(\(name, lints) -> T.unpack <$> showResult name lints)
- (toList . mapresultLayer $ mapResult)
+ (maybe [] toList . mapresultLayer $ mapResult)
+ prettyGeneral :: [String]
+ prettyGeneral = show <$> mapresultGeneral mapResult
-- TODO: possibly expand this to something more detailed?
diff --git a/lib/LintWriter.hs b/lib/LintWriter.hs
index ca7ff08..8e45812 100644
--- a/lib/LintWriter.hs
+++ b/lib/LintWriter.hs
@@ -10,20 +10,23 @@ import Control.Monad.Trans.Maybe ()
import Control.Monad.Writer (MonadTrans (lift),
MonadWriter (tell), WriterT)
import Data.Aeson (ToJSON (toJSON))
-import Data.Text (Text)
+import Data.Text (Text, unpack)
import GHC.Generics (Generic)
-
-- | Levels of errors and warnings, collectively called
-- "Hints" until I can think of some better name
-data Level = Warning | Suggestion | Info | Forbidden | Error
+data Level = Warning | Suggestion | Info | Forbidden | Error | Fatal
deriving (Show, Generic, ToJSON)
-- | a hint comes with an explanation (and a level)
data Hint = Hint
{ hintLevel :: Level
, hintMsg :: Text }
- deriving (Show, Generic, ToJSON)
+ deriving (Generic, ToJSON)
+
+instance Show Hint where
+ show Hint { hintMsg, hintLevel } =
+ show hintLevel <> ": " <> unpack hintMsg
-- shorter constructor
hint :: Level -> Text -> Hint
diff --git a/src/Main.hs b/src/Main.hs
index f0af6c1..7884cf9 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NamedFieldPuns #-}
@@ -8,14 +9,13 @@ module Main where
import Data.Maybe (fromMaybe)
import WithCli
-import CheckMap (runLinter)
+import CheckMap (loadAndLintMap)
import Data.Aeson (encode)
import Data.Aeson.Encode.Pretty (encodePretty)
import qualified Data.ByteString.Lazy as LB
import qualified Data.ByteString.Lazy.Encoding as LB
import Data.Text.Lazy as T
import System.IO (utf8)
-import Tiled2
-- | the options this cli tool can take
data Options = Options
@@ -39,10 +39,7 @@ main = withCli run
run :: Options -> IO ()
run options = do
- -- TODO: what if parsing fails and we get Left err?
- Right waMap <- loadTiledmap $ fromMaybe "example.json" (inpath options)
-
- let lints = runLinter waMap
+ lints <- loadAndLintMap (fromMaybe "example.json" (inpath options))
if json options
then printLB