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
15import qualified Json.Decode.Internals as Json
16import qualified Json.Encode as E
17import Reporting.Doc ((<+>), (<>))
18import qualified Reporting.Doc as D
19import qualified Reporting.Error.Syntax as Syntax
20import qualified Reporting.Render.Code as Code
21import qualified Reporting.Report as Report
29 = BadJson Syntax.Error
30 | BadContent (Json.Error e)
37toDoc :: String -> Code.Source -> (e -> [D.Doc]) -> Error e -> D.Doc
38toDoc rootName source userErrorToDocs err =
40 BadJson syntaxError ->
41 case Syntax.toReport source syntaxError of
42 Report.Report _ _ _ doc ->
45 BadContent jsonError ->
46 case flatten jsonError of
49 "I am not sure what is wrong with this JSON. Please create an <http://sscce.org>\
50 \ and share it at <https://github.com/elm/compiler/issues> so I can\
51 \ provide a helpful hint here!"
54 flatErrorToDoc rootName [] userErrorToDocs flatError
58 toNumberedDoc index flatErr =
59 D.dullcyan ("(" <> D.fromInt index <> ")") <+> flatErrorToDoc rootName [] userErrorToDocs flatErr
63 "I have " ++ show (length flatErrors) ++ " theories on what is going wrong:"
65 ++ zipWith toNumberedDoc [1..] flatErrors
72flatErrorToDoc :: String -> [D.Doc] -> (e -> [D.Doc]) -> FlatError e -> D.Doc
73flatErrorToDoc rootName starter userErrorToDocs (FlatError accesses json theory theories) =
80 userErrorToDocs userError
83 ["I","was","expecting"] ++ anExpectedThing tipe
87 D.fillSep (starter ++ explanation)
91 [ D.fillSep $ starter ++ ["The"] ++ actualThing json ++ ["at",accessToDoc rootName accesses,"is","causing","issues."]
92 , D.fillSep explanation
100 ["I","am","having","trouble","with","the"]
102 ++ ["here","because:"]
105 ["I","am","having","trouble","with","the"]
107 ++ ["at",accessToDoc rootName accesses,"because:"]
110 [ D.fillSep (starter ++ introduction)
111 , D.stack (toBullet [] userErrorToDocs theory : map (toBullet ["OR"] userErrorToDocs) theories)
112 , D.reflow "I accept any of these things."
116accessToDoc :: String -> [String] -> D.Doc
117accessToDoc rootName accesses =
118 D.dullyellow (D.fromString (rootName ++ concat accesses))
121actualThing :: E.Value -> [D.Doc]
124 E.Array _ -> [D.red "array"]
125 E.Object _ -> [D.red "object"]
126 E.String _ -> [D.red "string"]
127 E.Boolean b -> [D.red (if b then "true" else "false"),"value"]
128 E.Integer n -> ["number",D.red (D.fromInt n)]
129 E.Number _ -> [D.red "number"]
130 E.Null -> [D.red "null","value"]
133anExpectedThing :: Json.Type -> [D.Doc]
134anExpectedThing tipe =
136 Json.TObject -> ["an", D.green "OBJECT" <> "."]
137 Json.TArray -> ["an", D.green "ARRAY" <> "."]
138 Json.TString -> ["a", D.green "STRING" <> "."]
139 Json.TBool -> ["a", D.green "BOOLEAN" <> "."]
140 Json.TInt -> ["an", D.green "INT" <> "."]
141 Json.TObjectWith field -> ["an",D.green "OBJECT","with","a",D.green ("\"" <> D.fromString (Text.unpack field) <> "\""),"field."]
142 Json.TArrayWith i len ->
143 ["a",D.green "longer",D.green "ARRAY" <> "."
144 ,"I","need","index",D.fromInt i <> ",","but","this","array"
145 ,"only","has",D.fromInt len,"elements."
149toBullet :: [D.Doc] -> (e -> [D.Doc]) -> Theory e -> D.Doc
150toBullet intro userErrorToDocs theory =
151 D.indent 4 $ D.fillSep $ (++) intro $
154 userErrorToDocs userError
157 ["I","was","expecting"] ++ anExpectedThing tipe
165 FlatError [String] E.Value (Theory e) [Theory e]
170 | Expecting Json.Type
173flatten :: Json.Error e -> [FlatError e]
176 depth (FlatError accesses _ _ _) =
179 List.sortOn depth $ flattenTree (toErrorTree jsonError)
182flattenTree :: ErrorTree e -> [FlatError e]
183flattenTree (ErrorTree theories subTrees) =
185 addAccess access (FlatError accesses json t ts) =
186 FlatError (access:accesses) json t ts
188 toFlats (name, tree) =
189 map (addAccess name) (flattenTree tree)
192 concatMap toFlats (Map.toList subTrees)
198 (json, theory) : rest ->
199 FlatError [] json theory (map snd rest) : subErrors
208 { _theories :: [(E.Value, Theory e)]
209 , _subErrors :: Map.Map String (ErrorTree e)
213toErrorTree :: Json.Error e -> ErrorTree e
214toErrorTree jsonError =
220 ErrorTree [] Map.empty
223add :: Json.Error e -> ErrorTree e -> ErrorTree e
224add jsonError tree@(ErrorTree theories subErrors) =
226 Json.Field field subErr ->
227 ErrorTree theories (addName (fieldToName field) subErr subErrors)
229 Json.Index index subErr ->
230 ErrorTree theories (addName (indexToName index) subErr subErrors)
233 foldr add tree errors
235 Json.Expecting json tipe ->
236 ErrorTree ((json, Expecting tipe) : theories) subErrors
238 Json.Failure json err ->
239 ErrorTree ((json, Failure err) : theories) subErrors
242addName :: String -> Json.Error e -> Map.Map String (ErrorTree e) -> Map.Map String (ErrorTree e)
243addName name err subErrors =
246 Just (add err (maybe empty id maybeCrush))
248 Map.alter subAdd name subErrors
251fieldToName :: Text.Text -> String
253 case Text.unpack field of
257 string@(char : rest) ->
258 if Char.isAlpha char && all Char.isAlphaNum rest then
261 "['" ++ string ++ "']"
264indexToName :: Int -> String
266 "[" ++ 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