@@ -11,15 +11,16 @@ module Reporting.Error.Syntax
14−import qualified Data.Set as Set
15+import Data.Monoid ((<>))
15import qualified Data.Text as Text
16import qualified Data.Text as Text
16import Data.Text (Text)
17import Data.Text (Text)
18−import qualified Reporting.Render.Type as RenderType
19+import qualified Elm.Name as N
19import qualified Reporting.Region as R
20import qualified Reporting.Region as R
21+import qualified Reporting.Render.Code as Code
20import qualified Reporting.Report as Report
22import qualified Reporting.Report as Report
21−import qualified Reporting.Helpers as Help
23+import qualified Reporting.Helpers as H
22−import Reporting.Helpers ((<>), dullyellow, green, hsep, i2t, reflowParagraph, text)
@@ -27,31 +28,10 @@ import Reporting.Helpers ((<>), dullyellow, green, hsep, i2t, reflowParagraph, t
31+ = CommentOnNothing R.Region
32+ | UnexpectedPort R.Region N.Name
33+ | TypeWithoutDefinition R.Region N.Name
30− = Parse (Maybe R.Region) Problem
34+ | Parse R.Region (Maybe R.Region) Problem
31− | BadFunctionName Int
36− | SettingsOnNormalModule
37− | SettingsOnPortModule
38− | DuplicateSettingOnEffectModule Text
39− | BadSettingOnEffectModule Text
40− | NoSettingsOnEffectModule
41− | MissingManagerOnEffectModule Text
42− | UnexpectedPort Text
44− | TypeWithoutDefinition Text
46− | DuplicateArgument Text Text
47− | DuplicateFieldName R.Region Text
48− | DuplicateValueDeclaration Text
49− | DuplicateTypeDeclaration Text
50− | DuplicateDefinition Text
51− | UnboundTypeVarsInUnion Text [Text] [Text]
52− | UnboundTypeVarsInAlias Text [Text] [Text]
53− | UnusedTypeVarsInAlias Text [Text] [Text]
54− | MessyTypeVarsInAlias Text [Text] [Text] [Text]
@@ -72,13 +52,14 @@ data Problem
72 | NewLineInChar
52 | NewLineInChar
73 | BadEscape Int EscapeProblem
53 | BadEscape Int EscapeProblem
74 | BadChar Int
54 | BadChar Int
75− | BadNumberDot
55+ | BadNumberDot Int
76 | BadNumberEnd
56 | BadNumberEnd
77 | BadNumberExp
57 | BadNumberExp
78 | BadNumberHex
58 | BadNumberHex
79 | BadNumberZero
59 | BadNumberZero
80 | BadShader Text
61 | BadShader Text
81− | BadUnderscore Char
62+ | BadUnderscore Int
82 | BadOp BadOp ContextStack
63 | BadOp BadOp ContextStack
83 | Theories ContextStack [Theory]
64 | Theories ContextStack [Theory]
@@ -87,15 +68,15 @@ data EscapeProblem
87 = UnknownEscape
68 = UnknownEscape
88 | UnicodeSyntax
69 | UnicodeSyntax
89 | UnicodeRange
70 | UnicodeRange
90− | UnicodeLength Int Text
71+ | UnicodeLength Int String
93data BadOp = HasType | Equals | Arrow | Pipe | Dot
74data BadOp = HasType | Equals | Arrow | Pipe | Dot
96data Theory
77data Theory
97− = Keyword Text
78+ = Keyword String
98− | Symbol Text
79+ | Symbol String
99 | Expecting Next
80 | Expecting Next
@@ -130,8 +111,8 @@ data Context
130 | ExprTuple
111 | ExprTuple
131 | ExprRecord
112 | ExprRecord
132 ----------------
113 ----------------
133− | Definition Text
114+ | Definition N.Name
134− | Annotation Text
115+ | Annotation N.Name
135 ----------------
116 ----------------
136 | TypeTuple
117 | TypeTuple
137 | TypeRecord
118 | TypeRecord
@@ -153,599 +134,406 @@ data Context
153-- TO REPORT
134-- TO REPORT
156−toReport :: RenderType.Localizer -> Error -> Report.Report
137+toReport :: Code.Source -> Error -> Report.Report
157−toReport _localizer err =
138+toReport source err =
158 case err of
139 case err of
159− Parse subRegion problem ->
160− problemToReport subRegion problem
162− BadFunctionName arity ->
164− "BAD FUNCTION DEFINITION"
166− "Complex patterns cannot be used as function names."
168− "This function definition has " <> i2t arity <> " arguments, but instead\
169− \ of a normal name like `add` or `reverse` it has a pattern. There is no\
170− \ way to \"deconstruct\" a function with pattern matching, so this needs to\
171− \ be changed to a normal name."
178− ("The free variable `" <> name <> "` appears more than once in this pattern.")
180− [ text "Rename the variables so there are no duplicates."
182− "In Elm, pattern matching works by binding these free variables to subsections\
183− \ of the matching value. It does not make sense to have the same name for two\
184− \ different subsections though! When you say `" <> name <> "` in some code, there\
185− \ is no way for me to know which subsection you mean!"
189− CommentOnNothing ->
140+ CommentOnNothing region ->
191− "STRAY COMMENT"
141+ Report.Report "STRAY COMMENT" region [] $
192− Nothing
142+ Report.toCodeSnippet source region Nothing
193− ("This documentation comment is not followed by anything.")
144+ "This documentation comment is not followed by anything."
194− ( reflowParagraph $
145+ ,
195 "All documentation comments need to be right above the declaration they\
147 "All documentation comments need to be right above the declaration they\
196 \ describe. Maybe some code got deleted or commented out by accident? Or\
148 \ describe. Maybe some code got deleted or commented out by accident? Or\
197 \ maybe this comment is here by accident?"
149 \ maybe this comment is here by accident?"
200− SettingsOnNormalModule ->
202− "BAD MODULE DECLARATION"
204− "A normal module can expose values, but not settings like this."
206− "If you want a normal module, just remove this stuff. If you want to create\
207− \ an `effect module` you forgot to use the `effect` keyword. In that\
208− \ case, change `module` to `effect module` and you should be headed in\
209− \ the right direction!"
212− SettingsOnPortModule ->
214− "BAD MODULE DECLARATION"
216− "A port module can expose values, but not have settings like this."
218− "If you want a port module, just remove this stuff. If you want to create\
219− \ a custom effect module instead (which is rare) change `port module`\
220− \ to `effect module` and you should be headed in the right direction!"
223− DuplicateSettingOnEffectModule name ->
225− "EFFECT MODULE PROBLEM"
227− ("You have defined " <> Help.functionName name <> " multiple times.")
229− "There can only be one " <> Help.functionName name
230− <> " though! Remove until there is one left."
233− BadSettingOnEffectModule name ->
235− "EFFECT MODULE PROBLEM"
237− ("Setting " <> Help.functionName name <> " is not recognized.")
239− "Remove this entry and you should be all set!"
242− NoSettingsOnEffectModule ->
244− "EFFECT MODULE PROBLEM"
246− ("You are defining an effect module, but it has no settings.")
248− "If you just wanted a normal module, change the keywords `effect module`\
249− \ to `module` and you should be all set. If you want a proper effect module,\
250− \ you need to specify your commands and/or subscriptions. Read more about this\
251− \ here: <http://guide.elm-lang.org/effect_managers/>"
254− MissingManagerOnEffectModule name ->
256− "EFFECT MODULE PROBLEM"
258− ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
260− "There is a small set of top-level functions and values that must be defined\
261− \ in any complete effect module. The best thing is probably to just read more\
262− \ about effect modules here:\
263− \ <http://guide.elm-lang.org/effect_managers/>"
266− UnexpectedPort name ->
152+ UnexpectedPort region name ->
268− "BAD PORT"
153+ Report.Report "BAD PORT" region [] $
269− Nothing
154+ Report.toCodeSnippet source region Nothing
270− ("You are declaring port " <> Help.functionName name <> " in a normal module.")
157+ "You are declaring port `" <> N.toString name <> "` in a normal module."
271− ( reflowParagraph $
158+ ,
272− "All ports must be defined in a `port module`. You should probably have only\
159+ H.stack
273− \ one of these for your project. This way all of your foreign interactions\
160+ [ "It needs to be in a `port` module."
274− \ stay relatively organized."
161+ , H.link "Hint"
275− )
162+ "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
277− TypeWithoutDefinition valueName ->
164+ "to learn how to use ports effectively."
279− "MISSING DEFINITION"
281− ("There is a type annotation for `" <> valueName <> "` but there"
282− <> " is no corresponding definition!"
285− "Directly below the type annotation, put a definition like:\n\n"
286− <> " " <> valueName <> " = 42"
289− DuplicateArgument funcName argName ->
291− "DUPLICATE ARGUMENT"
293− ( "The name `" <> argName
294− <> "` is used more than once in the arguments of "
295− <> Help.functionName funcName <> "."
298− "Rename things until `" <> argName <> "` is used only once.\
299− \ Otherwise how can we tell which one you want when you\
300− \ say `" <> argName <> "` it in the body of your function?"
303− DuplicateFieldName region name ->
307− ("This record has more than one field named `" <> name <> "`.")
308− (text "There can only be one. Do some renaming to make sure the names are distinct!")
310− DuplicateValueDeclaration name ->
312− "DUPLICATE DEFINITION"
314− ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
315− <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
318− "Find all the top-level values named " <> Help.functionName name
319− <> " and do some renaming. Make sure the names are distinct!"
322− DuplicateTypeDeclaration name ->
324− "DUPLICATE DEFINITION"
326− ( "There are multiple types named `" <> name <> "` in this module."
329− "Search through this module, find all the types named `"
330− <> name <> "`, and give each of them a unique name."
333− DuplicateDefinition name ->
335− "DUPLICATE DEFINITION"
337− ("There are multiple values named `" <> name <> "` in this let-expression."
340− "Search through this let-expression, find all the values named `"
341− <> name <> "`, and give each of them a unique name."
344− UnboundTypeVarsInUnion typeName givenVars unbound ->
345− unboundTypeVars "type" typeName givenVars unbound
347− UnboundTypeVarsInAlias typeName givenVars unbound ->
348− unboundTypeVars "type alias" typeName givenVars unbound
350− UnusedTypeVarsInAlias typeName givenVars unused ->
352− "UNUSED TYPE VARIABLES"
354− ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
355− <> Help.commaSep unused
358− [ text "You probably need to change the declaration like this:"
359− , dullyellow $ hsep $
360− map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
364− MessyTypeVarsInAlias typeName givenVars unused unbound ->
168+ TypeWithoutDefinition region valueName ->
365− Report.report
169+ Report.Report "MISSING DEFINITION" region [] $
366− "TYPE VARIABLE PROBLEMS"
170+ Report.toCodeSnippet source region Nothing
368− ( "Type alias `" <> typeName <> "` has some problems with type variables."
172+ H.reflow $
173+ "There is a type annotation for `" <> N.toString valueName
174+ <> "` but there is no corresponding definition!"
176+ "Directly below the type annotation, put a definition like:\n\n"
177+ <> " " <> H.nameToDoc valueName <> " = 42"
372− "The declaration says it uses certain type variables ("
373− <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
374− <> "Furthermore, the aliased type says it uses type variables ("
375− <> Help.commaSep unbound
376− <> ") that do not appear in the declaration."
377− , text "You probably need to change the declaration like this:"
378− , dullyellow $ hsep $
379− map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
384−unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
385−unboundTypeVars declKind typeName givenVars unboundVars =
387− "UNBOUND TYPE VARIABLES"
389− ( Help.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
390− <> Help.commaSep unboundVars
393− [ text "You probably need to change the declaration like this:"
395− map text (declKind : typeName : givenVars)
396− ++ map (dullyellow . text) unboundVars
397− ++ map text ["=", "..."]
399− "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
400− "` is an Int and another where it is a Bool. When we explicitly list the type\
401− \ variables, the type checker can see that they are actually different types."
180+ Parse region subRegion problem ->
181+ Report.Report "PARSE ERROR" (maybe region id subRegion) [] $
182+ Report.toCodeSnippet source region subRegion $
183+ problemToDocs problem
407−-- PARSE ERROR TO REPORT
187+-- PARSE ERROR TO DOCS
410−makeParseReport :: Maybe R.Region -> Text -> Help.Doc -> Report.Report
411−makeParseReport subRegion pre post =
412− Report.report "PARSE ERROR" subRegion pre post
414−
190+problemToDocs :: Problem -> (H.Doc, H.Doc)
415−problemToReport :: Maybe R.Region -> Problem -> Report.Report
191+problemToDocs problem =
416−problemToReport subRegion problem =
417− let parseReport = makeParseReport subRegion in
418 case problem of
192 case problem of
421 "I ran into a tab, but tabs are not allowed in Elm files."
195 "I ran into a tab, but tabs are not allowed in Elm files."
422− (reflowParagraph "Replace the tab with spages.")
197+ "Replace the tab with spaces."
424 EndOfFile_Comment ->
200 EndOfFile_Comment ->
426 "I got to the end of the file while parsing a multi-line comment."
202 "I got to the end of the file while parsing a multi-line comment."
427− ( Help.stack
204+ H.stack
428− [ reflowParagraph $
205+ [ H.reflow $
429− "Multi-line comments look like {- comment -}, and it looks like\
206+ "Multi-line comments look like {- comment -}, and it looks like\
430− \ you are missing the closing marker."
207+ \ you are missing the closing marker."
431− , reflowParagraph $
208+ , H.toSimpleHint $
432− "Nested multi-line comments like {- this {- and this -} -} are allowed.\
209+ "Nested multi-line comments like {- this {- and this -} -} are allowed.\
433− \ That means the opening and closing markers must be balanced, just\
210+ \ The opening and closing markers must be balanced though, just\
434− \ like parentheses in normal code. Maybe that is the problem?"
211+ \ like parentheses in normal code. Maybe that is the problem?"
438 EndOfFile_Shader ->
215 EndOfFile_Shader ->
440 "I got to the end of the file while parsing a GLSL block."
217 "I got to the end of the file while parsing a GLSL block."
441− (reflowParagraph $
218+ ,
442 "A shader should be defined in a block like this: [glsl| ... |]"
220 "A shader should be defined in a block like this: [glsl| ... |]"
445 EndOfFile_String ->
223 EndOfFile_String ->
447 "I got to the end of the file while parsing a string."
225 "I got to the end of the file while parsing a string."
448− (reflowParagraph $
226+ ,
449 "Strings look like \"this\" with double quotes on each end.\
228 "Strings look like \"this\" with double quotes on each end.\
450− \ So the closing double quote seems to be missing."
229+ \ Is the closing double quote missing in your code?"
453 EndOfFile_MultiString ->
232 EndOfFile_MultiString ->
455 "I got to the end of the file while parsing a multi-line string."
234 "I got to the end of the file while parsing a multi-line string."
456− (reflowParagraph $
235+ ,
457− "Multi-line strings begin and end with three double quotes in a\
237+ "Multi-line strings look like \"\"\"this\"\"\" with three double quotes on each\
458− \ row, like \"\"\"this\"\"\". So the closing marker seems\
238+ \ end. Is the closing triple quote missing in your code?"
462 EndOfFile_Char ->
241 EndOfFile_Char ->
464 "I got to the end of the file while parsing a character."
243 "I got to the end of the file while parsing a character."
465− (reflowParagraph $
244+ ,
466− "Characters look like 'x' with single quotes on each end.\
246+ "Characters look like 'c' with single quotes on each end.\
467− \ So the closing single quote seems to be missing."
247+ \ Is the closing single quote missing in your code?"
470 NewLineInString ->
250 NewLineInString ->
472 "This string is missing the closing quote."
252 "This string is missing the closing quote."
473− ( Help.stack
254+ H.stack
474− [ reflowParagraph $
255+ [ H.reflow $
475− "Elm strings must start and end with a double quote, like \"this\"."
256+ "Elm strings like \"this\" cannot contain newlines."
476− , reflowParagraph $
257+ , H.toSimpleHint $
477− "If you want a string that can contain newlines, use three double quotes in a\
258+ "For strings that CAN contain newlines, say \"\"\"this\"\"\" for Elm’s\
478− \ row, like \"\"\"this\"\"\"."
259+ \ multi-line string syntax. It allows unescaped newlines and double quotes."
482 NewLineInChar ->
263 NewLineInChar ->
484 "This character is missing the closing quote."
265 "This character is missing the closing quote."
485− ( reflowParagraph $
266+ ,
486− "Elm characters must start and end with a single quote, like 'a' and 'b'"
267+ "Elm characters must start and end with a single quote. Valid examples\n\
268+ \ include 'a', 'b', '\n', 'ø', and '\\u{00F8}' for unicode code points."
489 BadEscape _ escapeProblem ->
271 BadEscape _ escapeProblem ->
490− uncurry parseReport (escapeProblemToReport escapeProblem)
272+ case escapeProblem of
275+ "Backslashes always start escaped characters, but I do not recognize this one:"
277+ [ "Maybe there is some typo?"
278+ , H.toSimpleHint "Valid escape characters include:"
279+ , H.indent 4 $ H.vcat $
289+ "The last one lets encode ANY character by its Unicode code\
290+ \ point, so use that for anything outside the ordinary six."
296+ "I ran into an invalid Unicode escape character:"
299+ [ "Here are some examples of valid Unicode escape characters:"
300+ , H.indent 4 $ H.vcat $
307+ "Notice that the code point is always surrounded by curly\
308+ \ braces. They are required!"
314+ "This is not a real Unicode code point:"
316+ "All valid Unicode code points are between 0 and 10FFFF."
319+ UnicodeLength numDigits badCode ->
320+ if numDigits < 4 then
322+ "Every Unicode code point needs at least four digits:"
325+ goodCode = replicate (4 - numDigits) '0' ++ badCode
326+ escape = "\\u{" <> H.text goodCode <> "}"
328+ H.hsep [ "Try", H.dullyellow escape, "instead?" ]
333+ "This Unicode code point has too many digits:"
336+ ["Valid","code","points","are","between"
337+ , H.dullyellow "\\u{0000}", "and", H.dullyellow "\\u{10FFFF}"
338+ ,"so","it","must","have","between","four","and","six","digits."
492 BadChar _ ->
342 BadChar _ ->
494 "Ran into a bad use of single quotes."
344 "Ran into a bad use of single quotes."
495− ( Help.stack
346+ H.stack
496− [ reflowParagraph $
347+ [ H.reflow $
497− "If you want to create a string, switch to double quotes:"
348+ "If you want to create a string, switch to double quotes:"
498− , Help.indent 4 $
349+ , H.indent 4 $
499− dullyellow (text "'this'")
350+ H.dullyellow "'this'" <> " => " <> H.green "\"this\""
500− <> text " => "
351+ , H.toSimpleHint $
501− <> green (text "\"this\"")
503− "Unlike JavaScript, Elm distinguishes between strings like \"hello\"\
352+ "Unlike JavaScript, Elm distinguishes between strings like \"hello\"\
504− \ and individual characters like 'A' and '3'. If you really do want\
353+ \ and individual characters like 'A' and '3'. If you really do want\
505− \ a character though, something went wrong and I did not find the\
354+ \ a character though, something went wrong and I did not find the\
506− \ closing single quote."
355+ \ closing single quote."
510− BadNumberDot ->
359+ BadNumberDot numberBeforeDot ->
512 "Numbers cannot end with a decimal points."
361 "Numbers cannot end with a decimal points."
513− ( reflowParagraph $
362+ ,
514− "Leave it off or add some digits after it, like or 3 or 3.0"
363+ let
365+ H.text (show numberBeforeDot)
367+ "Saying " <> H.green number <> " or " <> H.green (number <> ".0") <> " will work though!"
517 BadNumberEnd ->
370 BadNumberEnd ->
519 "Numbers cannot have letters or underscores in them."
372 "Numbers cannot have letters or underscores in them."
520− ( reflowParagraph $
373+ ,
521− "Maybe a space is missing between a number and a variable?"
375+ "Maybe a space is missing between a number and a variable?"
524 BadNumberExp ->
378 BadNumberExp ->
526 "If you put the letter E in a number, it should followed by more digits."
380 "If you put the letter E in a number, it should followed by more digits."
527− ( reflowParagraph $
381+ ,
528− "If you want to say 1000, you can also say 1e3.\
383+ "If you want to say 1000, you can also say 1e3.\
529− \ You cannot just end it with an E though!"
384+ \ You cannot just end it with an E though!"
532 BadNumberHex ->
387 BadNumberHex ->
534 "I see the start of a hex number, but not the end."
389 "I see the start of a hex number, but not the end."
535− ( reflowParagraph $
390+ ,
536− "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal digits (i.e. 0123456789abcdefABCDEF)"
392+ "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal\
393+ \ digits. Valid hexidecimal digits include: 0123456789abcdefABCDEF"
539 BadNumberZero ->
396 BadNumberZero ->
541− "Normal numbers cannot start with a zero. Take the zeros off the front."
398+ "Normal numbers cannot start with zeros. Take the zeros off the front."
542− ( reflowParagraph $
399+ ,
543− "Only numbers like 0x0040 or 0.25 can start with a zero."
401+ "Only numbers like 0x0040 or 0.25 can start with a zero."
406+ "I cannot pattern match with floating point numbers:"
409+ "Equality on floats can be unreliable, so you usually want to check that they\
410+ \ are nearby with some sort of (abs (actual - expected) < 0.001) check."
546 BadShader msg ->
413 BadShader msg ->
548 "I ran into a problem while parsing this GLSL block."
415 "I ran into a problem while parsing this GLSL block."
549− (reflowParagraph msg)
416+ ,
417+ H.reflow (Text.unpack msg)
551− BadUnderscore char ->
420+ BadUnderscore _ ->
553− ("An underscore cannot be immediately followed by `" <> Text.singleton char <> "`.")
555− "Variable names cannot start with an underscore in Elm. You can\
422+ "A variable name cannot start with an underscore:"
556− \ use an underscore as a \"wildcard\" that matches anything\
423+ ,
557− \ though. So maybe you forgot a space after the underscore?"
424+ H.reflow $
425+ "You can (1) use a wildcard like _ to ignore the value or you can (2) use\
426+ \ a name that starts with a letter to access the value later. Pick one!"
560 BadOp op stack ->
429 BadOp op stack ->
561 case op of
430 case op of
562 HasType ->
431 HasType ->
563− badOp subRegion stack "A" "\"has type\" operator"
432+ badOp stack "A" "\"has type\" operator"
564 "type annotations and record types"
433 "type annotations and record types"
565 "Maybe you want :: instead? Or maybe something is indented too much?"
434 "Maybe you want :: instead? Or maybe something is indented too much?"
567 Equals ->
436 Equals ->
568− badEquals subRegion stack
437+ (
439+ "I was not expecting this equals sign"
440+ <> contextToString " here" " while parsing " stack <> "."
442+ toBadEqualsHint stack
571 if isCaseRelated stack then
446 if isCaseRelated stack then
573 "I ran into a stray arrow while parsing this `case` expression."
448 "I ran into a stray arrow while parsing this `case` expression."
574− ( reflowParagraph $
449+ ,
575− "All branches in a `case` must be indented the exact\
451+ "All branches in a `case` must be indented the exact\
576− \ same amount, so the patterns are vertically\
452+ \ same amount, so the patterns are vertically\
577− \ aligned. Maybe this branch is indented too much?"
453+ \ aligned. Maybe this branch is indented too much?"
581− badOp subRegion stack "An" "arrow"
457+ badOp stack "An" "arrow"
582 "cases expressions and anonymous functions"
458 "cases expressions and anonymous functions"
583 "Maybe you want > or >= instead?"
459 "Maybe you want > or >= instead?"
586− badOp subRegion stack "A" "vertical bar"
462+ badOp stack "A" "vertical bar"
587 "type declarations"
463 "type declarations"
588 "Maybe you want || instead?"
464 "Maybe you want || instead?"
592 "I was not expecting this dot."
468 "I was not expecting this dot."
593− ( reflowParagraph $
469+ ,
594− "Dots are for record access and decimal points, so\
471+ "Dots are for record access and decimal points, so\
595− \ they cannot float around on their own. Maybe\
472+ \ they cannot float around on their own. Maybe\
596− \ there is some extra whitespace?"
473+ \ there is some extra whitespace?"
599 Theories stack allTheories ->
476 Theories stack allTheories ->
601− starter =
478+ H.reflow $
602− "Something went wrong while parsing "
479+ "Something went wrong while parsing " <> contextToString "your code" "" stack <> "."
603− <> contextToText "your code" "" stack
480+ ,
606− parseReport starter $
607− case Set.toList (Set.fromList allTheories) of
481+ case allTheories of
609− Help.stack
483+ H.stack
610− [ reflowParagraph $
484+ [ H.reflow $
611− "I do not have any suggestions though!"
485+ "I do not have any suggestions though!"
612− , reflowParagraph $
486+ , H.reflow $
613− "Can you get it down to a <http://sscce.org> and share it at\
487+ "Can you get it down to a <http://sscce.org> and share it at\
614− \ <https://github.com/elm-lang/error-message-catalog/issues>?\
488+ \ <https://github.com/elm-lang/error-message-catalog/issues>?\
615− \ That way we can figure out how to give better advice!"
489+ \ That way we can figure out how to give better advice!"
620− "I was expecting to see "
621− <> addPeriod (theoryToText stack theory)
625− [ text "I was expecting:"
628− ++ map (bullet . theoryToText stack) theories
631−escapeProblemToReport :: EscapeProblem -> ( Text, Help.Doc )
632−escapeProblemToReport escapeProblem =
633− case escapeProblem of
635− ( "A backslash starts an escaped character, but I do not recognize this one:"
637− [ "Maybe there is some typo?"
638− , Help.toSimpleHint "Valid escape characters include:"
639− , Help.indent 4 $ Help.vcat $
649− "The last one lets encode ANY character by its Unicode code\
650− \ point, so there are no other escape characters in Elm."
655− ( "I ran into an invalid Unicode escape character:"
657− [ "Here are some examples of valid Unicode escape characters:"
658− , Help.indent 4 $ Help.vcat $
665− "Notice that the code point is always surrounded by curly\
666− \ braces. They are required!"
671− ( "This is not a real Unicode code point:"
672− , "All valid Unicode code points are between 0 and 10FFFF."
675− UnicodeLength numDigits badCode ->
492+ [theory] ->
677− moreOrFewer =
494+ "I was expecting to see "
678− if numDigits < 4 then "more" else "fewer"
495+ <> addPeriod (theoryToString stack theory)
681− Text.justifyRight 4 '0' $ Text.dropWhile (== '0') badCode
683− suggestion =
497+ theories ->
684− [ "Try"
498+ H.vcat $
685− , "using"
499+ [ "I was expecting:"
686− , dullyellow $ text $ "\\u{" <> goodCode <> "}"
687− , "instead."
500+ , ""
689− in
502+ ++ map (bullet . theoryToString stack) theories
690− ( "This Unicode code point needs " <> moreOrFewer <> " digits:"
696−-- HELPERS
507+-- BAD OP HELPERS
699−bullet :: Text -> Help.Doc
510+badOp :: ContextStack -> String -> String -> String -> String -> ( H.Doc, H.Doc )
700−bullet point =
511+badOp stack article opName setting hint =
701− Help.hang 4 (" - " <> reflowParagraph point)
512+ (
703−
514+ "I was not expecting this " <> opName
704−addPeriod :: Text -> Text
515+ <> contextToString " here" " while parsing " stack <> "."
705−addPeriod msg =
516+ ,
706− if Text.last msg `elem` ['`', ')', '.', '!', '?'] then
517+ H.reflow $
707− msg
518+ article <> " " <> opName <> " should only appear in "
708− else
519+ <> setting <> ". " <> hint
712−badOp :: Maybe R.Region -> ContextStack -> Text -> Text -> Text -> Text -> Report.Report
713−badOp subRegion stack article opName setting hint =
716− "I was not expecting this " <> opName
717− <> contextToText "" " while parsing " stack <> "."
719− makeParseReport subRegion pre $
721− article <> " " <> opName <> " should only appear in "
722− <> setting <> ". " <> hint
725−badEquals :: Maybe R.Region -> ContextStack -> Report.Report
726−badEquals subRegion stack =
729− "I was not expecting this equals sign"
730− <> contextToText "" " while parsing " stack <> "."
732− makeParseReport subRegion pre (badEqualsHelp stack)
735−badEqualsHelp :: ContextStack -> Help.Doc
523+toBadEqualsHint :: ContextStack -> H.Doc
736−badEqualsHelp stack =
524+toBadEqualsHint stack =
737 case stack of
525 case stack of
739− reflowParagraph $
527+ H.reflow $
740 "Maybe you want == instead? Or maybe something is indented too much?"
528 "Maybe you want == instead? Or maybe something is indented too much?"
742 (ExprRecord, _) : _ ->
530 (ExprRecord, _) : _ ->
743− reflowParagraph $
531+ H.reflow $
744 "Records look like { x = 3, y = 4 } with the equals sign right\
532 "Records look like { x = 3, y = 4 } with the equals sign right\
745 \ after the field name. Maybe you forgot a comma?"
533 \ after the field name. Maybe you forgot a comma?"
747 (Definition _, _) : rest ->
535 (Definition _, _) : rest ->
748− reflowParagraph $
536+ H.reflow $
749 "Maybe this is supposed to be a separate definition? If so, it\
537 "Maybe this is supposed to be a separate definition? If so, it\
750 \ is indented too far. "
538 \ is indented too far. "
@@ -755,28 +543,43 @@ badEqualsHelp stack =
755 "Spaces are not allowed before top-level definitions."
543 "Spaces are not allowed before top-level definitions."
757 _ : rest ->
545 _ : rest ->
758− badEqualsHelp rest
546+ toBadEqualsHint rest
550+isCaseRelated :: ContextStack -> Bool
551+isCaseRelated stack =
556+ (context, _) : rest ->
557+ context == ExprCase || isCaseRelated rest
761−contextToText :: Text -> Text -> ContextStack -> Text
561+-- CONTEXT
762−contextToText defaultText prefixText stack =
562+
564+contextToString :: String -> String -> ContextStack -> String
565+contextToString defaultString prefixString stack =
763 case stack of
566 case stack of
765− defaultText
568+ defaultString
767 (context, _) : rest ->
570 (context, _) : rest ->
768 let anchor = getAnchor rest in
571 let anchor = getAnchor rest in
769− prefixText <>
572+ prefixString <>
770 case context of
573 case context of
771− ExprIf -> "an `if`" <> anchor
574+ ExprIf -> "an `if` expression" <> anchor
772− ExprLet -> "a `let`" <> anchor
575+ ExprLet -> "a `let` expression" <> anchor
773 ExprFunc -> "an anonymous function" <> anchor
576 ExprFunc -> "an anonymous function" <> anchor
774− ExprCase -> "a `case`" <> anchor
577+ ExprCase -> "a `case` expression" <> anchor
775 ExprList -> "a list" <> anchor
578 ExprList -> "a list" <> anchor
776 ExprTuple -> "an expression (in parentheses)" <> anchor
579 ExprTuple -> "an expression (in parentheses)" <> anchor
777 ExprRecord -> "a record" <> anchor
580 ExprRecord -> "a record" <> anchor
778− Definition name -> name <> "'s definition"
581+ Definition name -> N.toString name <> "'s definition"
779− Annotation name -> name <> "'s type annotation"
582+ Annotation name -> N.toString name <> "'s type annotation"
780 TypeTuple -> "a type (in parentheses)" <> anchor
583 TypeTuple -> "a type (in parentheses)" <> anchor
781 TypeRecord -> "a record type" <> anchor
584 TypeRecord -> "a record type" <> anchor
782 PatternList -> "a list pattern" <> anchor
585 PatternList -> "a list pattern" <> anchor
@@ -790,7 +593,7 @@ contextToText defaultText prefixText stack =
790 Port -> "a port declaration"
593 Port -> "a port declaration"
793−getAnchor :: ContextStack -> Text
596+getAnchor :: ContextStack -> String
794getAnchor stack =
597getAnchor stack =
795 case stack of
598 case stack of
@@ -799,27 +602,34 @@ getAnchor stack =
799 (context, _) : rest ->
602 (context, _) : rest ->
800 case context of
603 case context of
801 Definition name ->
604 Definition name ->
802− " in " <> name <> "'s definition"
605+ " in " <> N.toString name <> "'s definition"
804 Annotation name ->
607 Annotation name ->
805− " in " <> name <> "'s type annotation"
608+ " in " <> N.toString name <> "'s type annotation"
808 getAnchor rest
611 getAnchor rest
811−isCaseRelated :: ContextStack -> Bool
812−isCaseRelated stack =
817− (context, _) : rest ->
615+-- THEORY HELPERS
818− context == ExprCase || isCaseRelated rest
616+
618+bullet :: String -> H.Doc
620+ H.hang 4 (" - " <> H.fillSep (map H.text (words point)))
623+addPeriod :: String -> String
625+ if last msg `elem` ['`', ')', '.', '!', '?'] then
821−theoryToText :: ContextStack -> Theory -> Text
631+theoryToString :: ContextStack -> Theory -> String
822−theoryToText context theory =
632+theoryToString context theory =
823 case theory of
633 case theory of
824 Keyword keyword ->
634 Keyword keyword ->
825 "the `" <> keyword <> "` keyword"
635 "the `" <> keyword <> "` keyword"
@@ -841,7 +651,7 @@ theoryToText context theory =
841 "]" -> "a right square bracket, to end a list"
651 "]" -> "a right square bracket, to end a list"
842 "{" -> "a left curly brace, for starting records"
652 "{" -> "a left curly brace, for starting records"
843 "}" -> "a right curly brace, to end a record"
653 "}" -> "a right curly brace, to end a record"
844− "{-|" -> "a doc comment, like {-| example -}"
654+ "{-|" -> "a doc comment, like {-| this -}"
845 _ -> "the (" <> symbol <> ") symbol"
655 _ -> "the (" <> symbol <> ") symbol"
847 LowVar ->
657 LowVar ->
@@ -863,7 +673,7 @@ theoryToText context theory =
863 case next of
673 case next of
864 Decl -> "a declaration, like `x = 5` or `type alias Model = { ... }`"
674 Decl -> "a declaration, like `x = 5` or `type alias Model = { ... }`"
865 Expr -> "an expression, like x or 42"
675 Expr -> "an expression, like x or 42"
866− AfterOpExpr op -> "an expression after that (" <> op <> ") operator, like x or 42"
676+ AfterOpExpr op -> "an expression after that (" <> N.toString op <> ") operator, like x or 42"
867 ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
677 ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
868 Arg -> "an argument, like `name` or `total`"
678 Arg -> "an argument, like `name` or `total`"
869 Pattern -> "a pattern, like `name` or (Just x)"
679 Pattern -> "a pattern, like `name` or (Just x)"
@@ -872,7 +682,7 @@ theoryToText context theory =
872 Exposing -> "something like `exposing (..)`"
682 Exposing -> "something like `exposing (..)`"
875−equalsTheory :: ContextStack -> Text
685+equalsTheory :: ContextStack -> String
876equalsTheory stack =
686equalsTheory stack =
877 case stack of
687 case stack of
@@ -881,13 +691,13 @@ equalsTheory stack =
881 (context, _) : rest ->
691 (context, _) : rest ->
882 case context of
692 case context of
883 ExprRecord -> "an equals sign (=) followed by an expression"
693 ExprRecord -> "an equals sign (=) followed by an expression"
884− Definition name -> "an equals sign (=) followed by " <> name <> "'s definition"
694+ Definition name -> "an equals sign (=) followed by " <> N.toString name <> "'s definition"
885 TypeUnion -> "an equals sign (=) followed by the first union type constructor"
695 TypeUnion -> "an equals sign (=) followed by the first union type constructor"
886 TypeAlias -> "an equals sign (=) followed by the aliased type"
696 TypeAlias -> "an equals sign (=) followed by the aliased type"
887 _ -> equalsTheory rest
697 _ -> equalsTheory rest
890−barTheory :: ContextStack -> Text
700+barTheory :: ContextStack -> String
891barTheory stack =
701barTheory stack =
892 case stack of
702 case stack of
@@ -901,7 +711,7 @@ barTheory stack =
901 _ -> barTheory rest
711 _ -> barTheory rest
904−badSpace :: ContextStack -> Text
714+badSpace :: ContextStack -> String
905badSpace stack =
715badSpace stack =
906 case stack of
716 case stack of
@@ -916,8 +726,8 @@ badSpace stack =
916 ExprList -> "the end of that list" <> badSpaceExprEnd rest
726 ExprList -> "the end of that list" <> badSpaceExprEnd rest
917 ExprTuple -> "a closing paren" <> badSpaceExprEnd rest
727 ExprTuple -> "a closing paren" <> badSpaceExprEnd rest
918 ExprRecord -> "the end of that record" <> badSpaceExprEnd rest
728 ExprRecord -> "the end of that record" <> badSpaceExprEnd rest
919− Definition name -> "the rest of " <> name <> "'s definition" <> badSpaceExprEnd stack
729+ Definition name -> "the rest of " <> N.toString name <> "'s definition" <> badSpaceExprEnd stack
920− Annotation name -> "the rest of " <> name <> "'s type annotation" <> badSpaceEnd
730+ Annotation name -> "the rest of " <> N.toString name <> "'s type annotation" <> badSpaceEnd
921 TypeTuple -> "a closing paren" <> badSpaceEnd
731 TypeTuple -> "a closing paren" <> badSpaceEnd
922 TypeRecord -> "the end of that record" <> badSpaceEnd
732 TypeRecord -> "the end of that record" <> badSpaceEnd
923 PatternList -> "the end of that list" <> badSpaceEnd
733 PatternList -> "the end of that list" <> badSpaceEnd
@@ -931,12 +741,12 @@ badSpace stack =
931 Port -> "more of that port declaration" <> badSpaceEnd
741 Port -> "more of that port declaration" <> badSpaceEnd
934−badSpaceEnd :: Text
744+badSpaceEnd :: String
935badSpaceEnd =
745badSpaceEnd =
936 ". Maybe you forgot some code? Or you need more indentation?"
746 ". Maybe you forgot some code? Or you need more indentation?"
939−badSpaceExprEnd :: ContextStack -> Text
749+badSpaceExprEnd :: ContextStack -> String
940badSpaceExprEnd stack =
750badSpaceExprEnd stack =
941 case stack of
751 case stack of
@@ -948,9 +758,10 @@ badSpaceExprEnd stack =
948 if column <= 1 then
758 if column <= 1 then
949 "to be indented?"
759 "to be indented?"
951− "more indentation? (Try " <> i2t (column + 1) <> "+ spaces.)"
761+ "more indentation? (Try " <> show (column + 1) <> "+ spaces.)"
953− ". Maybe you forgot some code? Or maybe the body of `" <> name
763+ ". Maybe you forgot some code? Or maybe the body of `"
954 <> "` needs " <> ending
765 <> "` needs " <> ending
956 _ : rest ->
767 _ : rest ->