@@ -1,14 +1,28 @@
11{-# OPTIONS_GHC -Wall #-}
22{-# LANGUAGE OverloadedStrings #-}
33module Reporting.Error
4− ( Error(..)
5− , toReports
4+ ( Module(..)
5+ , Error(..)
6+ , toDoc
7+ , toJson
68 )
79 where
810
911
12+import qualified Data.ByteString as B
13+import qualified Data.Name as Name
14+import qualified Data.NonEmptyList as NE
15+import qualified Data.OneOrMore as OneOrMore
16+import qualified Data.Utf8 as Utf8
17+
18+import qualified Elm.ModuleName as ModuleName
19+import qualified File
20+import qualified Json.Encode as E
21+import Json.Encode ((==>))
22+import qualified Reporting.Annotation as A
23+import qualified Reporting.Doc as D
1024import qualified Reporting.Error.Canonicalize as Canonicalize
11−import qualified Reporting.Error.Docs as Docs
25+import qualified Reporting.Error.Import as Import
1226import qualified Reporting.Error.Main as Main
1327import qualified Reporting.Error.Pattern as Pattern
1428import qualified Reporting.Error.Syntax as Syntax
@@ -19,39 +33,176 @@ import qualified Reporting.Report as Report
1933
2034
2135
22−-- ALL POSSIBLE ERRORS
36+-- MODULE
37+
38+
39+data Module =
40+ Module
41+ { _name :: ModuleName.Raw
42+ , _path :: FilePath
43+ , _time :: File.Time
44+ , _source :: B.ByteString
45+ , _error :: Error
46+ , _localizer :: L.Localizer
47+ }
48+
49+
50+
51+-- ERRORS
2352
2453
2554data Error
26− = Syntax Syntax.Error
27− | Canonicalize Canonicalize.Error
28− | Type L.Localizer [Type.Error]
29− | Main L.Localizer Main.Error
30− | Pattern [Pattern.Error]
31− | Docs Docs.Error
55+ = BadSyntax Syntax.Error
56+ | BadImports (NE.List Import.Error)
57+ | BadNames (OneOrMore.OneOrMore Canonicalize.Error)
58+ | BadTypes (NE.List Type.Error)
59+ | BadPatterns (NE.List Pattern.Error)
60+ | BadMains (OneOrMore.OneOrMore Main.Error)
3261
3362
3463
3564-- TO REPORT
3665
3766
38−toReports :: Code.Source -> Error -> [Report.Report]
39−toReports source err =
67+toReports :: L.Localizer -> Code.Source -> Error -> NE.List Report.Report
68+toReports localizer source err =
4069 case err of
41− Syntax syntaxError ->
42− [Syntax.toReport source syntaxError]
70+ BadSyntax syntaxError ->
71+ NE.List (Syntax.toReport source syntaxError) []
72+
73+ BadImports errs ->
74+ fmap Import.toReport errs
75+
76+ BadNames errs ->
77+ fmap (Canonicalize.toReport source) (OneOrMore.destruct NE.List errs)
78+
79+ BadTypes errs ->
80+ fmap (Type.toReport source localizer) errs
81+
82+ BadPatterns errs ->
83+ fmap (Pattern.toReport source) errs
84+
85+ BadMains errs ->
86+ fmap (Main.toReport localizer source) (OneOrMore.destruct NE.List errs)
87+
88+
89+
90+-- TO DOC
91+
92+
93+toDoc :: NE.List Module -> D.Doc
94+toDoc modules =
95+ let
96+ timeCompare m1 m2 = compare (_time m1) (_time m2)
97+ (NE.List m ms) = NE.sortBy timeCompare modules
98+ in
99+ D.vcat (toDocHelp m ms)
100+
101+
102+toDocHelp :: Module -> [Module] -> [D.Doc]
103+toDocHelp module1 modules =
104+ case modules of
105+ [] ->
106+ [moduleToDoc module1]
107+
108+ module2 : otherModules ->
109+ moduleToDoc module1
110+ : toSeparator module1 module2
111+ : toDocHelp module2 otherModules
112+
113+
114+toSeparator :: Module -> Module -> D.Doc
115+toSeparator beforeModule afterModule =
116+ let
117+ before = ModuleName.toChars (_name beforeModule) ++ " ↑ "
118+ after = " ↓ " ++ ModuleName.toChars (_name afterModule)
119+ in
120+ D.dullred $ D.vcat $
121+ [ D.indent (80 - length before) (D.fromChars before)
122+ , "====o======================================================================o===="
123+ , D.fromChars after
124+ , ""
125+ , ""
126+ ]
127+
128+
129+
130+-- MODULE TO DOC
131+
132+
133+moduleToDoc :: Module -> D.Doc
134+moduleToDoc (Module _ path _ source err localizer) =
135+ let
136+ reports =
137+ toReports localizer (Code.toSource source) err
138+ in
139+ D.vcat $ map (reportToDoc path) (NE.toList reports)
140+
141+
142+reportToDoc :: FilePath -> Report.Report -> D.Doc
143+reportToDoc path (Report.Report title _ _ message) =
144+ D.vcat
145+ [ toMessageBar title path
146+ , ""
147+ , message
148+ , ""
149+ ]
150+
151+
152+toMessageBar :: String -> FilePath -> D.Doc
153+toMessageBar title filePath =
154+ let
155+ usedSpace =
156+ 4 + length title + 1 + length filePath
157+ in
158+ D.dullcyan $ D.fromChars $
159+ "-- " ++ title
160+ ++ " " ++ replicate (max 1 (80 - usedSpace)) '-'
161+ ++ " " ++ filePath
162+
163+
164+
165+-- TO JSON
43166
44− Canonicalize canonicalizeError ->
45− [Canonicalize.toReport source canonicalizeError]
46167
47− Type localizer typeErrors ->
48− map (Type.toReport source localizer) typeErrors
168+toJson :: NE.List Module -> E.Value
169+toJson modules =
170+ E.array (map moduleToJson (NE.toList modules))
49171
50− Main localizer mainError ->
51− [Main.toReport localizer source mainError]
52172
53− Pattern patternErrors ->
54− map (Pattern.toReport source) patternErrors
173+moduleToJson :: Module -> E.Value
174+moduleToJson (Module name path _ source err localizer) =
175+ let
176+ reports =
177+ toReports localizer (Code.toSource source) err
178+ in
179+ E.object
180+ [ "path" ==> E.string (Utf8.fromChars path)
181+ , "name" ==> E.string (Name.toUtf8 name)
182+ , "problems" ==> E.array (map reportToJson (NE.toList reports))
183+ ]
55184
56− Docs docsError ->
57− [Docs.toReport source docsError]
185+
186+reportToJson :: Report.Report -> E.Value
187+reportToJson (Report.Report title region _sgstns message) =
188+ E.object
189+ [ "title" ==> E.string (Utf8.fromChars title)
190+ , "region" ==> encodeRegion region
191+ , "message" ==> D.encode message
192+ ]
193+
194+
195+encodeRegion :: A.Region -> E.Value
196+encodeRegion (A.Region (A.Position sr sc) (A.Position er ec)) =
197+ E.object
198+ [ "start" ==>
199+ E.object
200+ [ ("line", E.int (fromIntegral sr))
201+ , ("column", E.int (fromIntegral sc))
202+ ]
203+ , "end" ==>
204+ E.object
205+ [ ("line", E.int (fromIntegral er))
206+ , ("column", E.int (fromIntegral ec))
207+ ]
208+ ]