on 1433e40 help sign in
elk/src/Reporting/Error/Syntax.hs
342 lines 13 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 , ParseError(..)
6 , Problem(..), Theory(..)
7 , toReport
8 )
9 where
11import Data.Text (Text)
13import qualified Reporting.Render.Type as RenderType
14import qualified Reporting.Region as Region
15import qualified Reporting.Report as Report
16import qualified Reporting.Helpers as Help
17import Reporting.Helpers ((<>), dullyellow, hsep, i2t, text)
21-- ALL SYNTAX ERRORS
24data Error
25 = Parse Problem
26 | BadFunctionName Int
27 | BadPattern Text
29 | CommentOnNothing
31 | SettingsOnNormalModule
32 | SettingsOnPortModule
33 | DuplicateSettingOnEffectModule Text
34 | BadSettingOnEffectModule Text
35 | NoSettingsOnEffectModule
36 | MissingManagerOnEffectModule Text
37 | UnexpectedPort Text
39 | TypeWithoutDefinition Text
41 | DuplicateArgument Text Text
42 | DuplicateFieldName Region.Region Text
43 | DuplicateValueDeclaration Text
44 | DuplicateTypeDeclaration Text
45 | DuplicateDefinition Text
46 | UnboundTypeVarsInUnion Text [Text] [Text]
47 | UnboundTypeVarsInAlias Text [Text] [Text]
48 | UnusedTypeVarsInAlias Text [Text] [Text]
49 | MessyTypeVarsInAlias Text [Text] [Text] [Text]
53-- PARSE ERRORS
56data ParseError
57 = ParseError !Int !Int !Problem
60data Problem
61 = Tab
62 | EndOfFile Text
63 | NewLineInString
64 | BadEscape
65 | BadChar
66 | BadNumberDot
67 | BadNumberEnd
68 | BadNumberExp
69 | BadNumberHex
70 | BadNumberZero
71 | BadChunkInQualifiedCapVar
72 | HasType -- "A single colon is for type annotations. Maybe you want :: instead? Or maybe you are defining a type annotation, but there is whitespace before it?"
73 | Equals -- "The = operator is reserved for defining variables. Maybe you want == instead? Or maybe you are defining a variable, but there is whitespace before it?"
74 | Arrow -- "Arrows are reserved for cases and anonymous functions. Maybe you want > or >= instead?"
75 | Pipe -- "Vertical bars are reserved for use in union type declarations. Maybe you want || instead?"
76 | Dot -- "Dots are for record access. They cannot float around on their own!"
77 | Theories [Theory]
80data Theory
81 = Keyword Text
82 | Symbol Text
83 | Variable
84 | InfixOp
85 | Digit
86 | BadIndent
87 | FreshLine
88 | Expecting Text
92-- TO REPORT
95toReport :: RenderType.Localizer -> Error -> Report.Report
96toReport _localizer err =
97 case err of
98 Parse _ ->
99 Report.report "PARSE ERROR" Nothing "Something is wrong." (text "TODO")
101 BadFunctionName arity ->
102 Report.report
103 "BAD FUNCTION DEFINITION"
104 Nothing
105 "Complex patterns cannot be used as function names."
106 ( Help.reflowParagraph $
107 "This function definition has " <> i2t arity <> " arguments, but instead\
108 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
109 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
110 \ be changed to a normal name."
111 )
113 BadPattern name ->
114 Report.report
115 "BAD PATTERN"
116 Nothing
117 ("The free variable `" <> name <> "` appears more than once in this pattern.")
118 ( Help.stack
119 [ text "Rename the variables so there are no duplicates."
120 , Help.reflowParagraph $
121 "In Elm, pattern matching works by binding these free variables to subsections\
122 \ of the matching value. It does not make sense to have the same name for two\
123 \ different subsections though! When you say `" <> name <> "` in some code, there\
124 \ is no way for me to know which subsection you mean!"
125 ]
126 )
128 CommentOnNothing ->
129 Report.report
130 "STRAY COMMENT"
131 Nothing
132 ("This documentation comment is not followed by anything.")
133 ( Help.reflowParagraph $
134 "All documentation comments need to be right above the declaration they\
135 \ describe. Maybe some code got deleted or commented out by accident? Or\
136 \ maybe this comment is here by accident?"
137 )
139 SettingsOnNormalModule ->
140 Report.report
141 "BAD MODULE DECLARATION"
142 Nothing
143 "A normal module can expose values, but not settings like this."
144 ( Help.reflowParagraph $
145 "If you want a normal module, just remove this stuff. If you want to create\
146 \ an `effect module` you just forgot to use the `effect` keyword. In that\
147 \ case, just change `module` to `effect module` and you should be headed in\
148 \ the right direction!"
149 )
151 SettingsOnPortModule ->
152 Report.report
153 "BAD MODULE DECLARATION"
154 Nothing
155 "A port module can expose values, but not have settings like this."
156 ( Help.reflowParagraph $
157 "If you want a port module, just remove this stuff. If you want to create\
158 \ a custom effect module instead (which is rare) just change `port module`\
159 \ to `effect module` and you should be headed in the right direction!"
160 )
162 DuplicateSettingOnEffectModule name ->
163 Report.report
164 "EFFECT MODULE PROBLEM"
165 Nothing
166 ("You have defined " <> Help.functionName name <> " multiple times.")
167 ( Help.reflowParagraph $
168 "There can only be one " <> Help.functionName name
169 <> " though! Remove until there is one left."
170 )
172 BadSettingOnEffectModule name ->
173 Report.report
174 "EFFECT MODULE PROBLEM"
175 Nothing
176 ("Setting " <> Help.functionName name <> " is not recognized.")
177 ( Help.reflowParagraph $
178 "Remove this entry and you should be all set!"
179 )
181 NoSettingsOnEffectModule ->
182 Report.report
183 "EFFECT MODULE PROBLEM"
184 Nothing
185 ("You are defining an effect module, but it has no settings.")
186 ( Help.reflowParagraph $
187 "If you just wanted a normal module, change the keywords `effect module`\
188 \ to `module` and you should be all set. If you want a proper effect module,\
189 \ you need to specify your commands and/or subscriptions. Read more about this\
190 \ here: <http://guide.elm-lang.org/effect_managers/>"
191 )
193 MissingManagerOnEffectModule name ->
194 Report.report
195 "EFFECT MODULE PROBLEM"
196 Nothing
197 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
198 ( Help.reflowParagraph $
199 "There is a small set of top-level functions and values that must be defined\
200 \ in any complete effect module. The best thing is probably to just read more\
201 \ about effect modules here:\
202 \ <http://guide.elm-lang.org/effect_managers/>"
203 )
205 UnexpectedPort name ->
206 Report.report
207 "BAD PORT"
208 Nothing
209 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
210 ( Help.reflowParagraph $
211 "All ports must be defined in a `port module`. You should probably have just\
212 \ one of these for your project. This way all of your foreign interactions\
213 \ stay relatively organized."
214 )
216 TypeWithoutDefinition valueName ->
217 Report.report
218 "MISSING DEFINITION"
219 Nothing
220 ("There is a type annotation for `" <> valueName <> "` but there"
221 <> " is no corresponding definition!"
222 )
223 ( text $
224 "Directly below the type annotation, put a definition like:\n\n"
225 <> " " <> valueName <> " = 42"
226 )
228 DuplicateArgument funcName argName ->
229 Report.report
230 "DUPLICATE ARGUMENT"
231 Nothing
232 ( "The name `" <> argName
233 <> "` is used more than once in the arguments of "
234 <> Help.functionName funcName <> "."
235 )
236 ( Help.reflowParagraph $
237 "Rename things until `" <> argName <> "` is used only once.\
238 \ Otherwise how can we tell which one you want when you\
239 \ say `" <> argName <> "` it in the body of your function?"
240 )
242 DuplicateFieldName region name ->
243 Report.report
244 "DUPLICATE FIELD"
245 (Just region)
246 ("This record has more than one field named `" <> name <> "`.")
247 (text "There can only be one. Do some renaming to make sure the names are distinct!")
249 DuplicateValueDeclaration name ->
250 Report.report
251 "DUPLICATE DEFINITION"
252 Nothing
253 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
254 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
255 )
256 ( Help.reflowParagraph $
257 "Find all the top-level values named " <> Help.functionName name
258 <> " and do some renaming. Make sure the names are distinct!"
259 )
261 DuplicateTypeDeclaration name ->
262 Report.report
263 "DUPLICATE DEFINITION"
264 Nothing
265 ( "There are multiple types named `" <> name <> "` in this module."
266 )
267 ( Help.reflowParagraph $
268 "Search through this module, find all the types named `"
269 <> name <> "`, and give each of them a unique name."
270 )
272 DuplicateDefinition name ->
273 Report.report
274 "DUPLICATE DEFINITION"
275 Nothing
276 ("There are multiple values named `" <> name <> "` in this let-expression."
277 )
278 ( Help.reflowParagraph $
279 "Search through this let-expression, find all the values named `"
280 <> name <> "`, and give each of them a unique name."
281 )
283 UnboundTypeVarsInUnion typeName givenVars unbound ->
284 unboundTypeVars "type" typeName givenVars unbound
286 UnboundTypeVarsInAlias typeName givenVars unbound ->
287 unboundTypeVars "type alias" typeName givenVars unbound
289 UnusedTypeVarsInAlias typeName givenVars unused ->
290 Report.report
291 "UNUSED TYPE VARIABLES"
292 Nothing
293 ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
294 <> Help.commaSep unused
295 )
296 ( Help.stack
297 [ text "You probably need to change the declaration like this:"
298 , dullyellow $ hsep $
299 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
300 ]
301 )
303 MessyTypeVarsInAlias typeName givenVars unused unbound ->
304 Report.report
305 "TYPE VARIABLE PROBLEMS"
306 Nothing
307 ( "Type alias `" <> typeName <> "` has some problems with type variables."
308 )
309 ( Help.stack
310 [ Help.reflowParagraph $
311 "The declaration says it uses certain type variables ("
312 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
313 <> "Furthermore, the aliased type says it uses type variables ("
314 <> Help.commaSep unbound
315 <> ") that do not appear in the declaration."
316 , text "You probably need to change the declaration like this:"
317 , dullyellow $ hsep $
318 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
319 ]
320 )
323unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
324unboundTypeVars declKind typeName givenVars unboundVars =
325 Report.report
326 "UNBOUND TYPE VARIABLES"
327 Nothing
328 ( Help.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
329 <> Help.commaSep unboundVars
330 )
331 ( Help.stack
332 [ text "You probably need to change the declaration like this:"
333 , hsep $
334 map text (declKind : typeName : givenVars)
335 ++ map (dullyellow . text) unboundVars
336 ++ map text ["=", "..."]
337 , Help.reflowParagraph $
338 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
339 "` is an Int and another where it is a Bool. When we explicitly list the type\
340 \ variables, the type checker can see that they are actually different types."
341 ]
342 )