on ee58906 help sign in
elk/src/Reporting/Error/Syntax.hs
294 lines 11 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax where
5import Data.Text (Text)
7import qualified Reporting.Render.Type as RenderType
8import qualified Reporting.Region as Region
9import qualified Reporting.Report as Report
10import qualified Reporting.Helpers as Help
11import Reporting.Helpers ((<>), dullyellow, hsep, i2t, text)
14data Error
15 = Parse
16 | BadFunctionName Int
17 | BadPattern Text
19 | CommentOnNothing
21 | SettingsOnNormalModule
22 | SettingsOnPortModule
23 | DuplicateSettingOnEffectModule Text
24 | BadSettingOnEffectModule Text
25 | NoSettingsOnEffectModule
26 | MissingManagerOnEffectModule Text
27 | UnexpectedPort Text
29 | TypeWithoutDefinition Text
31 | DuplicateArgument Text Text
32 | DuplicateFieldName Region.Region Text
33 | DuplicateValueDeclaration Text
34 | DuplicateTypeDeclaration Text
35 | DuplicateDefinition Text
36 | UnboundTypeVarsInUnion Text [Text] [Text]
37 | UnboundTypeVarsInAlias Text [Text] [Text]
38 | UnusedTypeVarsInAlias Text [Text] [Text]
39 | MessyTypeVarsInAlias Text [Text] [Text] [Text]
40 deriving (Show)
44-- TO REPORT
47toReport :: RenderType.Localizer -> Error -> Report.Report
48toReport _localizer err =
49 case err of
50 Parse ->
51 Report.report "PARSE ERROR" Nothing "Something is wrong." (text "TODO")
53 BadFunctionName arity ->
54 Report.report
55 "BAD FUNCTION DEFINITION"
56 Nothing
57 "Complex patterns cannot be used as function names."
58 ( Help.reflowParagraph $
59 "This function definition has " <> i2t arity <> " arguments, but instead\
60 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
61 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
62 \ be changed to a normal name."
63 )
65 BadPattern name ->
66 Report.report
67 "BAD PATTERN"
68 Nothing
69 ("The free variable `" <> name <> "` appears more than once in this pattern.")
70 ( Help.stack
71 [ text "Rename the variables so there are no duplicates."
72 , Help.reflowParagraph $
73 "In Elm, pattern matching works by binding these free variables to subsections\
74 \ of the matching value. It does not make sense to have the same name for two\
75 \ different subsections though! When you say `" <> name <> "` in some code, there\
76 \ is no way for me to know which subsection you mean!"
77 ]
78 )
80 CommentOnNothing ->
81 Report.report
82 "STRAY COMMENT"
83 Nothing
84 ("This documentation comment is not followed by anything.")
85 ( Help.reflowParagraph $
86 "All documentation comments need to be right above the declaration they\
87 \ describe. Maybe some code got deleted or commented out by accident? Or\
88 \ maybe this comment is here by accident?"
89 )
91 SettingsOnNormalModule ->
92 Report.report
93 "BAD MODULE DECLARATION"
94 Nothing
95 "A normal module can expose values, but not settings like this."
96 ( Help.reflowParagraph $
97 "If you want a normal module, just remove this stuff. If you want to create\
98 \ an `effect module` you just forgot to use the `effect` keyword. In that\
99 \ case, just change `module` to `effect module` and you should be headed in\
100 \ the right direction!"
101 )
103 SettingsOnPortModule ->
104 Report.report
105 "BAD MODULE DECLARATION"
106 Nothing
107 "A port module can expose values, but not have settings like this."
108 ( Help.reflowParagraph $
109 "If you want a port module, just remove this stuff. If you want to create\
110 \ a custom effect module instead (which is rare) just change `port module`\
111 \ to `effect module` and you should be headed in the right direction!"
112 )
114 DuplicateSettingOnEffectModule name ->
115 Report.report
116 "EFFECT MODULE PROBLEM"
117 Nothing
118 ("You have defined " <> Help.functionName name <> " multiple times.")
119 ( Help.reflowParagraph $
120 "There can only be one " <> Help.functionName name
121 <> " though! Remove until there is one left."
122 )
124 BadSettingOnEffectModule name ->
125 Report.report
126 "EFFECT MODULE PROBLEM"
127 Nothing
128 ("Setting " <> Help.functionName name <> " is not recognized.")
129 ( Help.reflowParagraph $
130 "Remove this entry and you should be all set!"
131 )
133 NoSettingsOnEffectModule ->
134 Report.report
135 "EFFECT MODULE PROBLEM"
136 Nothing
137 ("You are defining an effect module, but it has no settings.")
138 ( Help.reflowParagraph $
139 "If you just wanted a normal module, change the keywords `effect module`\
140 \ to `module` and you should be all set. If you want a proper effect module,\
141 \ you need to specify your commands and/or subscriptions. Read more about this\
142 \ here: <http://guide.elm-lang.org/effect_managers/>"
143 )
145 MissingManagerOnEffectModule name ->
146 Report.report
147 "EFFECT MODULE PROBLEM"
148 Nothing
149 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
150 ( Help.reflowParagraph $
151 "There is a small set of top-level functions and values that must be defined\
152 \ in any complete effect module. The best thing is probably to just read more\
153 \ about effect modules here:\
154 \ <http://guide.elm-lang.org/effect_managers/>"
155 )
157 UnexpectedPort name ->
158 Report.report
159 "BAD PORT"
160 Nothing
161 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
162 ( Help.reflowParagraph $
163 "All ports must be defined in a `port module`. You should probably have just\
164 \ one of these for your project. This way all of your foreign interactions\
165 \ stay relatively organized."
166 )
168 TypeWithoutDefinition valueName ->
169 Report.report
170 "MISSING DEFINITION"
171 Nothing
172 ("There is a type annotation for `" <> valueName <> "` but there"
173 <> " is no corresponding definition!"
174 )
175 ( text $
176 "Directly below the type annotation, put a definition like:\n\n"
177 <> " " <> valueName <> " = 42"
178 )
180 DuplicateArgument funcName argName ->
181 Report.report
182 "DUPLICATE ARGUMENT"
183 Nothing
184 ( "The name `" <> argName
185 <> "` is used more than once in the arguments of "
186 <> Help.functionName funcName <> "."
187 )
188 ( Help.reflowParagraph $
189 "Rename things until `" <> argName <> "` is used only once.\
190 \ Otherwise how can we tell which one you want when you\
191 \ say `" <> argName <> "` it in the body of your function?"
192 )
194 DuplicateFieldName region name ->
195 Report.report
196 "DUPLICATE FIELD"
197 (Just region)
198 ("This record has more than one field named `" <> name <> "`.")
199 (text "There can only be one. Do some renaming to make sure the names are distinct!")
201 DuplicateValueDeclaration name ->
202 Report.report
203 "DUPLICATE DEFINITION"
204 Nothing
205 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
206 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
207 )
208 ( Help.reflowParagraph $
209 "Find all the top-level values named " <> Help.functionName name
210 <> " and do some renaming. Make sure the names are distinct!"
211 )
213 DuplicateTypeDeclaration name ->
214 Report.report
215 "DUPLICATE DEFINITION"
216 Nothing
217 ( "There are multiple types named `" <> name <> "` in this module."
218 )
219 ( Help.reflowParagraph $
220 "Search through this module, find all the types named `"
221 <> name <> "`, and give each of them a unique name."
222 )
224 DuplicateDefinition name ->
225 Report.report
226 "DUPLICATE DEFINITION"
227 Nothing
228 ("There are multiple values named `" <> name <> "` in this let-expression."
229 )
230 ( Help.reflowParagraph $
231 "Search through this let-expression, find all the values named `"
232 <> name <> "`, and give each of them a unique name."
233 )
235 UnboundTypeVarsInUnion typeName givenVars unbound ->
236 unboundTypeVars "type" typeName givenVars unbound
238 UnboundTypeVarsInAlias typeName givenVars unbound ->
239 unboundTypeVars "type alias" typeName givenVars unbound
241 UnusedTypeVarsInAlias typeName givenVars unused ->
242 Report.report
243 "UNUSED TYPE VARIABLES"
244 Nothing
245 ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
246 <> Help.commaSep unused
247 )
248 ( Help.stack
249 [ text "You probably need to change the declaration like this:"
250 , dullyellow $ hsep $
251 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
252 ]
253 )
255 MessyTypeVarsInAlias typeName givenVars unused unbound ->
256 Report.report
257 "TYPE VARIABLE PROBLEMS"
258 Nothing
259 ( "Type alias `" <> typeName <> "` has some problems with type variables."
260 )
261 ( Help.stack
262 [ Help.reflowParagraph $
263 "The declaration says it uses certain type variables ("
264 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
265 <> "Furthermore, the aliased type says it uses type variables ("
266 <> Help.commaSep unbound
267 <> ") that do not appear in the declaration."
268 , text "You probably need to change the declaration like this:"
269 , dullyellow $ hsep $
270 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
271 ]
272 )
275unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
276unboundTypeVars declKind typeName givenVars unboundVars =
277 Report.report
278 "UNBOUND TYPE VARIABLES"
279 Nothing
280 ( Help.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
281 <> Help.commaSep unboundVars
282 )
283 ( Help.stack
284 [ text "You probably need to change the declaration like this:"
285 , hsep $
286 map text (declKind : typeName : givenVars)
287 ++ map (dullyellow . text) unboundVars
288 ++ map text ["=", "..."]
289 , Help.reflowParagraph $
290 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
291 "` is an Int and another where it is a Bool. When we explicitly list the type\
292 \ variables, the type checker can see that they are actually different types."
293 ]
294 )