1{-# LANGUAGE OverloadedStrings #-}
2module Json.Decode.Error
9import Prelude hiding (userError)
10import qualified Data.Char as Char
11import qualified Data.List as List
12import qualified Data.Map as Map
13import qualified Data.Text as Text
14import Text.PrettyPrint.ANSI.Leijen ((<+>), (<>))
15import qualified Text.PrettyPrint.ANSI.Leijen as P
17import qualified Json.Decode.Internals as Json
18import qualified Json.Encode as E
19import qualified Reporting.Error.Syntax as Syntax
20import qualified Reporting.Helpers as H
21import qualified Reporting.Render.Code as Code
22import qualified Reporting.Report as Report
30 = BadJson Syntax.Error
31 | BadContent (Json.Error e)
38toDoc :: String -> Code.Source -> (e -> [H.Doc]) -> Error e -> H.Doc
39toDoc rootName source userErrorToDocs err =
41 BadJson syntaxError ->
42 case Syntax.toReport source syntaxError of
43 Report.Report _ _ _ doc ->
46 BadContent jsonError ->
47 case flatten jsonError of
50 "I am not sure what is wrong with this JSON. Please create an <http://sscce.org>\
51 \ and share it at <https://github.com/elm-lang/elm-compiler/issues> so I can\
52 \ provide a helpful hint here!"
55 flatErrorToDoc rootName [] userErrorToDocs flatError
59 toNumberedDoc index flatErr =
60 P.dullcyan ("(" <> P.int index <> ")") <+> flatErrorToDoc rootName [] userErrorToDocs flatErr
64 "I have " ++ show (length flatErrors) ++ " theories on what is going wrong:"
66 ++ zipWith toNumberedDoc [1..] flatErrors
73flatErrorToDoc :: String -> [H.Doc] -> (e -> [H.Doc]) -> FlatError e -> H.Doc
74flatErrorToDoc rootName starter userErrorToDocs (FlatError accesses json theory theories) =
81 userErrorToDocs userError
84 ["I","was","expecting"] ++ anExpectedThing tipe
88 H.fillSep (starter ++ explanation)
92 [ H.fillSep $ starter ++ ["The"] ++ actualThing json ++ ["at",accessToDoc rootName accesses,"is","causing","issues."]
93 , H.fillSep explanation
101 ["I","am","having","trouble","with","the"]
103 ++ ["here","because:"]
106 ["I","am","having","trouble","with","the"]
108 ++ ["at",accessToDoc rootName accesses,"because:"]
111 [ H.fillSep (starter ++ introduction)
112 , H.stack (toBullet [] userErrorToDocs theory : map (toBullet ["OR"] userErrorToDocs) theories)
113 , H.reflow "I accept any of these things."
117accessToDoc :: String -> [String] -> H.Doc
118accessToDoc rootName accesses =
119 P.dullyellow (P.text (rootName ++ concat accesses))
122actualThing :: E.Value -> [H.Doc]
125 E.Array _ -> [H.red "array"]
126 E.Object _ -> [H.red "object"]
127 E.String _ -> [H.red "string"]
128 E.Boolean b -> [H.red (if b then "true" else "false"),"value"]
129 E.Integer n -> ["number",H.red (H.text (show n))]
130 E.Number _ -> [H.red "number"]
131 E.Null -> [H.red "null","value"]
134anExpectedThing :: Json.Type -> [H.Doc]
135anExpectedThing tipe =
137 Json.TObject -> ["an", P.green "OBJECT" <> "."]
138 Json.TArray -> ["an", P.green "ARRAY" <> "."]
139 Json.TString -> ["a", P.green "STRING" <> "."]
140 Json.TBool -> ["a", P.green "BOOLEAN" <> "."]
141 Json.TInt -> ["an", P.green "INT" <> "."]
142 Json.TObjectWith field -> ["an",P.green "OBJECT","with","a",P.green ("\"" <> P.text (Text.unpack field) <> "\""),"field."]
143 Json.TArrayWith i len ->
144 ["a",H.green "longer",P.green "ARRAY" <> "."
145 ,"I","need","index",P.text (show i) <> ",","but","this","array"
146 ,"only","has",P.text (show len),"elements."
150toBullet :: [H.Doc] -> (e -> [H.Doc]) -> Theory e -> H.Doc
151toBullet intro userErrorToDocs theory =
152 H.indent 4 $ H.fillSep $ (++) intro $
155 userErrorToDocs userError
158 ["I","was","expecting"] ++ anExpectedThing tipe
166 FlatError [String] E.Value (Theory e) [Theory e]
171 | Expecting Json.Type
174flatten :: Json.Error e -> [FlatError e]
177 depth (FlatError accesses _ _ _) =
180 List.sortOn depth $ flattenTree (toErrorTree jsonError)
183flattenTree :: ErrorTree e -> [FlatError e]
184flattenTree (ErrorTree theories subTrees) =
186 addAccess access (FlatError accesses json t ts) =
187 FlatError (access:accesses) json t ts
189 toFlats (name, tree) =
190 map (addAccess name) (flattenTree tree)
193 concatMap toFlats (Map.toList subTrees)
199 (json, theory) : rest ->
200 FlatError [] json theory (map snd rest) : subErrors
209 { _theories :: [(E.Value, Theory e)]
210 , _subErrors :: Map.Map String (ErrorTree e)
214toErrorTree :: Json.Error e -> ErrorTree e
215toErrorTree jsonError =
221 ErrorTree [] Map.empty
224add :: Json.Error e -> ErrorTree e -> ErrorTree e
225add jsonError tree@(ErrorTree theories subErrors) =
227 Json.Field field subErr ->
228 ErrorTree theories (addName (fieldToName field) subErr subErrors)
230 Json.Index index subErr ->
231 ErrorTree theories (addName (indexToName index) subErr subErrors)
234 foldr add tree errors
236 Json.Expecting json tipe ->
237 ErrorTree ((json, Expecting tipe) : theories) subErrors
239 Json.Failure json err ->
240 ErrorTree ((json, Failure err) : theories) subErrors
243addName :: String -> Json.Error e -> Map.Map String (ErrorTree e) -> Map.Map String (ErrorTree e)
244addName name err subErrors =
247 Just (add err (maybe empty id maybeCrush))
249 Map.alter subAdd name subErrors
252fieldToName :: Text.Text -> String
254 case Text.unpack field of
258 string@(char : rest) ->
259 if Char.isAlpha char && all Char.isAlphaNum rest then
262 "['" ++ string ++ "']"
265indexToName :: Int -> String
267 "[" ++ show index ++ "]"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list