on 442ac09 help sign in
elk/src/Reporting/Error/Syntax.hs
860 lines 28 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 , ParseError(..)
6 , Problem(..), Theory(..)
7 , ContextStack, Context(..)
8 , BadOp(..), Next(..)
9 , toReport
10 )
11 where
13import qualified Data.Set as Set
14import qualified Data.Text as Text
15import Data.Text (Text)
17import qualified Reporting.Render.Type as RenderType
18import qualified Reporting.Region as R
19import qualified Reporting.Report as Report
20import qualified Reporting.Helpers as Help
21import Reporting.Helpers ((<>), dullyellow, hsep, i2t, reflowParagraph, text)
25-- ALL SYNTAX ERRORS
28data Error
29 = Parse (Maybe R.Region) Problem
30 | BadFunctionName Int
31 | BadPattern Text
33 | CommentOnNothing
35 | SettingsOnNormalModule
36 | SettingsOnPortModule
37 | DuplicateSettingOnEffectModule Text
38 | BadSettingOnEffectModule Text
39 | NoSettingsOnEffectModule
40 | MissingManagerOnEffectModule Text
41 | UnexpectedPort Text
43 | TypeWithoutDefinition Text
45 | DuplicateArgument Text Text
46 | DuplicateFieldName R.Region Text
47 | DuplicateValueDeclaration Text
48 | DuplicateTypeDeclaration Text
49 | DuplicateDefinition Text
50 | UnboundTypeVarsInUnion Text [Text] [Text]
51 | UnboundTypeVarsInAlias Text [Text] [Text]
52 | UnusedTypeVarsInAlias Text [Text] [Text]
53 | MessyTypeVarsInAlias Text [Text] [Text] [Text]
57-- PARSE ERRORS
60data ParseError = ParseError !Int !Int !Problem
63data Problem
64 = Tab
65 | EndOfFile_Comment
66 | EndOfFile_Shader
67 | EndOfFile_String
68 | EndOfFile_MultiString
69 | NewLineInString
70 | BadEscape
71 | BadChar
72 | BadNumberDot
73 | BadNumberEnd
74 | BadNumberExp
75 | BadNumberHex
76 | BadNumberZero
77 | BadShader Text
78 | BadOp BadOp ContextStack
79 | Theories ContextStack [Theory]
82data BadOp = HasType | Equals | Arrow | Pipe | Dot
85data Theory
86 = Keyword Text
87 | Symbol Text
88 | Expecting Next
89 | LowVar
90 | CapVar
91 | InfixOp
92 | Digit
93 | BadSpace
94 deriving (Eq, Ord)
97data Next
98 = Decl
99 | Expr
100 | AfterOpExpr Text
101 | ElseBranch
102 | Arg
103 | Pattern
104 | Type
105 | Listing
106 | Exposing
107 deriving (Eq, Ord)
110type ContextStack = [(Context, R.Position)]
113data Context
114 = ExprIf
115 | ExprLet
116 | ExprFunc
117 | ExprCase
118 | ExprList
119 | ExprTuple
120 | ExprRecord
121 ----------------
122 | Definition Text
123 | Annotation Text
124 ----------------
125 | TypeTuple
126 | TypeRecord
127 ----------------
128 | PatternList
129 | PatternTuple
130 | PatternRecord
131 ----------------
132 | Module
133 | Import
134 | TypeUnion
135 | TypeAlias
136 | Infix
137 | Port
138 deriving (Eq, Ord, Show)
142-- TO REPORT
145toReport :: RenderType.Localizer -> Error -> Report.Report
146toReport _localizer err =
147 case err of
148 Parse subRegion problem ->
149 problemToReport subRegion problem
151 BadFunctionName arity ->
152 Report.report
153 "BAD FUNCTION DEFINITION"
154 Nothing
155 "Complex patterns cannot be used as function names."
156 ( reflowParagraph $
157 "This function definition has " <> i2t arity <> " arguments, but instead\
158 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
159 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
160 \ be changed to a normal name."
161 )
163 BadPattern name ->
164 Report.report
165 "BAD PATTERN"
166 Nothing
167 ("The free variable `" <> name <> "` appears more than once in this pattern.")
168 ( Help.stack
169 [ text "Rename the variables so there are no duplicates."
170 , reflowParagraph $
171 "In Elm, pattern matching works by binding these free variables to subsections\
172 \ of the matching value. It does not make sense to have the same name for two\
173 \ different subsections though! When you say `" <> name <> "` in some code, there\
174 \ is no way for me to know which subsection you mean!"
175 ]
176 )
178 CommentOnNothing ->
179 Report.report
180 "STRAY COMMENT"
181 Nothing
182 ("This documentation comment is not followed by anything.")
183 ( reflowParagraph $
184 "All documentation comments need to be right above the declaration they\
185 \ describe. Maybe some code got deleted or commented out by accident? Or\
186 \ maybe this comment is here by accident?"
187 )
189 SettingsOnNormalModule ->
190 Report.report
191 "BAD MODULE DECLARATION"
192 Nothing
193 "A normal module can expose values, but not settings like this."
194 ( reflowParagraph $
195 "If you want a normal module, just remove this stuff. If you want to create\
196 \ an `effect module` you forgot to use the `effect` keyword. In that\
197 \ case, change `module` to `effect module` and you should be headed in\
198 \ the right direction!"
199 )
201 SettingsOnPortModule ->
202 Report.report
203 "BAD MODULE DECLARATION"
204 Nothing
205 "A port module can expose values, but not have settings like this."
206 ( reflowParagraph $
207 "If you want a port module, just remove this stuff. If you want to create\
208 \ a custom effect module instead (which is rare) change `port module`\
209 \ to `effect module` and you should be headed in the right direction!"
210 )
212 DuplicateSettingOnEffectModule name ->
213 Report.report
214 "EFFECT MODULE PROBLEM"
215 Nothing
216 ("You have defined " <> Help.functionName name <> " multiple times.")
217 ( reflowParagraph $
218 "There can only be one " <> Help.functionName name
219 <> " though! Remove until there is one left."
220 )
222 BadSettingOnEffectModule name ->
223 Report.report
224 "EFFECT MODULE PROBLEM"
225 Nothing
226 ("Setting " <> Help.functionName name <> " is not recognized.")
227 ( reflowParagraph $
228 "Remove this entry and you should be all set!"
229 )
231 NoSettingsOnEffectModule ->
232 Report.report
233 "EFFECT MODULE PROBLEM"
234 Nothing
235 ("You are defining an effect module, but it has no settings.")
236 ( reflowParagraph $
237 "If you just wanted a normal module, change the keywords `effect module`\
238 \ to `module` and you should be all set. If you want a proper effect module,\
239 \ you need to specify your commands and/or subscriptions. Read more about this\
240 \ here: <http://guide.elm-lang.org/effect_managers/>"
241 )
243 MissingManagerOnEffectModule name ->
244 Report.report
245 "EFFECT MODULE PROBLEM"
246 Nothing
247 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
248 ( reflowParagraph $
249 "There is a small set of top-level functions and values that must be defined\
250 \ in any complete effect module. The best thing is probably to just read more\
251 \ about effect modules here:\
252 \ <http://guide.elm-lang.org/effect_managers/>"
253 )
255 UnexpectedPort name ->
256 Report.report
257 "BAD PORT"
258 Nothing
259 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
260 ( reflowParagraph $
261 "All ports must be defined in a `port module`. You should probably have only\
262 \ one of these for your project. This way all of your foreign interactions\
263 \ stay relatively organized."
264 )
266 TypeWithoutDefinition valueName ->
267 Report.report
268 "MISSING DEFINITION"
269 Nothing
270 ("There is a type annotation for `" <> valueName <> "` but there"
271 <> " is no corresponding definition!"
272 )
273 ( text $
274 "Directly below the type annotation, put a definition like:\n\n"
275 <> " " <> valueName <> " = 42"
276 )
278 DuplicateArgument funcName argName ->
279 Report.report
280 "DUPLICATE ARGUMENT"
281 Nothing
282 ( "The name `" <> argName
283 <> "` is used more than once in the arguments of "
284 <> Help.functionName funcName <> "."
285 )
286 ( reflowParagraph $
287 "Rename things until `" <> argName <> "` is used only once.\
288 \ Otherwise how can we tell which one you want when you\
289 \ say `" <> argName <> "` it in the body of your function?"
290 )
292 DuplicateFieldName region name ->
293 Report.report
294 "DUPLICATE FIELD"
295 (Just region)
296 ("This record has more than one field named `" <> name <> "`.")
297 (text "There can only be one. Do some renaming to make sure the names are distinct!")
299 DuplicateValueDeclaration name ->
300 Report.report
301 "DUPLICATE DEFINITION"
302 Nothing
303 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
304 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
305 )
306 ( reflowParagraph $
307 "Find all the top-level values named " <> Help.functionName name
308 <> " and do some renaming. Make sure the names are distinct!"
309 )
311 DuplicateTypeDeclaration name ->
312 Report.report
313 "DUPLICATE DEFINITION"
314 Nothing
315 ( "There are multiple types named `" <> name <> "` in this module."
316 )
317 ( reflowParagraph $
318 "Search through this module, find all the types named `"
319 <> name <> "`, and give each of them a unique name."
320 )
322 DuplicateDefinition name ->
323 Report.report
324 "DUPLICATE DEFINITION"
325 Nothing
326 ("There are multiple values named `" <> name <> "` in this let-expression."
327 )
328 ( reflowParagraph $
329 "Search through this let-expression, find all the values named `"
330 <> name <> "`, and give each of them a unique name."
331 )
333 UnboundTypeVarsInUnion typeName givenVars unbound ->
334 unboundTypeVars "type" typeName givenVars unbound
336 UnboundTypeVarsInAlias typeName givenVars unbound ->
337 unboundTypeVars "type alias" typeName givenVars unbound
339 UnusedTypeVarsInAlias typeName givenVars unused ->
340 Report.report
341 "UNUSED TYPE VARIABLES"
342 Nothing
343 ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
344 <> Help.commaSep unused
345 )
346 ( Help.stack
347 [ text "You probably need to change the declaration like this:"
348 , dullyellow $ hsep $
349 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
350 ]
351 )
353 MessyTypeVarsInAlias typeName givenVars unused unbound ->
354 Report.report
355 "TYPE VARIABLE PROBLEMS"
356 Nothing
357 ( "Type alias `" <> typeName <> "` has some problems with type variables."
358 )
359 ( Help.stack
360 [ reflowParagraph $
361 "The declaration says it uses certain type variables ("
362 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
363 <> "Furthermore, the aliased type says it uses type variables ("
364 <> Help.commaSep unbound
365 <> ") that do not appear in the declaration."
366 , text "You probably need to change the declaration like this:"
367 , dullyellow $ hsep $
368 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
369 ]
370 )
373unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
374unboundTypeVars declKind typeName givenVars unboundVars =
375 Report.report
376 "UNBOUND TYPE VARIABLES"
377 Nothing
378 ( Help.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
379 <> Help.commaSep unboundVars
380 )
381 ( Help.stack
382 [ text "You probably need to change the declaration like this:"
383 , hsep $
384 map text (declKind : typeName : givenVars)
385 ++ map (dullyellow . text) unboundVars
386 ++ map text ["=", "..."]
387 , reflowParagraph $
388 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
389 "` is an Int and another where it is a Bool. When we explicitly list the type\
390 \ variables, the type checker can see that they are actually different types."
391 ]
392 )
396-- PARSE ERROR TO REPORT
399makeParseReport :: Maybe R.Region -> Text -> Help.Doc -> Report.Report
400makeParseReport subRegion pre post =
401 Report.report "PARSE ERROR" subRegion pre post
404problemToReport :: Maybe R.Region -> Problem -> Report.Report
405problemToReport subRegion problem =
406 let parseReport = makeParseReport subRegion in
407 case problem of
408 Tab ->
409 parseReport
410 "I ran into a tab, but tabs are not allowed in Elm files."
411 (reflowParagraph "Replace the tab with spages.")
413 EndOfFile_Comment ->
414 parseReport
415 "I got to the end of the file while parsing a multi-line comment."
416 ( Help.stack
417 [ reflowParagraph $
418 "Multi-line comments look like {- comment -}, and it looks like\
419 \ you are missing the closing marker."
420 , reflowParagraph $
421 "Nested multi-line comments like {- this {- and this -} -} are allowed.\
422 \ That means the opening and closing markers must be balanced, just\
423 \ like parentheses in normal code. Maybe that is the problem?"
424 ]
425 )
427 EndOfFile_Shader ->
428 parseReport
429 "I got to the end of the file while parsing a GLSL block."
430 (reflowParagraph $
431 "A shader should be defined in a block like this: [glsl| ... |]"
432 )
434 EndOfFile_String ->
435 parseReport
436 "I got to the end of the file while parsing a string."
437 (reflowParagraph $
438 "Strings look like \"this\" with double quotes on each end.\
439 \ So the closing double quote seems to be missing."
440 )
442 EndOfFile_MultiString ->
443 parseReport
444 "I got to the end of the file while parsing a multi-line string."
445 (reflowParagraph $
446 "Multi-line strings begin and end with three double quotes in a\
447 \ row, like \"\"\"this\"\"\". So the closing marker seems\
448 \ to be missing."
449 )
451 NewLineInString ->
452 parseReport
453 "This string is missing the closing quote."
454 ( Help.stack
455 [ reflowParagraph $
456 "Elm strings must start and end with a double quote, like \"this\"."
457 , reflowParagraph $
458 "If you want a string that can contain newlines, use three double quotes in a\
459 \ row, like \"\"\"this\"\"\"."
460 ]
461 )
463 BadEscape ->
464 parseReport
465 "Ran into a bad escape code."
466 ( reflowParagraph
467 "Elm allows typical escape characters like \\n and \\t, but you can\
468 \ also use \\x0040 to refer to unicode characters by their hex code.\
469 \ It seems like something has gone wrong with one of these codes."
470 )
472 BadChar ->
473 parseReport
474 "Ran into a bad use of single quotes."
475 ( Help.stack
476 [ reflowParagraph $
477 "If you want to create a string, switch to double quotes:"
478 , Help.indent 4 $
479 dullyellow (text "'this'")
480 <> text " => "
481 <> dullyellow (text "\"this\"")
482 , reflowParagraph $
483 "Unlike JavaScript, Elm distinguishes between strings like \"hello\"\
484 \ and individual characters like 'A' and '3'. If you really do want\
485 \ a character though, something went wrong and I did not find the\
486 \ closing single quote."
487 ]
488 )
490 BadNumberDot ->
491 parseReport
492 "Numbers cannot end with a decimal points."
493 ( reflowParagraph $
494 "Leave it off or add some digits after it, like or 3 or 3.0"
495 )
497 BadNumberEnd ->
498 parseReport
499 "Numbers cannot have letters or underscores in them."
500 ( reflowParagraph $
501 "Maybe a space is missing between a number and a variable?"
502 )
504 BadNumberExp ->
505 parseReport
506 "If you put the letter E in a number, it should followed by more digits."
507 ( reflowParagraph $
508 "If you want to say 1000, you can also say 1e3.\
509 \ You cannot just end it with an E though!"
510 )
512 BadNumberHex ->
513 parseReport
514 "I see the start of a hex number, but not the end."
515 ( reflowParagraph $
516 "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal digits (i.e. 0123456789abcdefABCDEF)"
517 )
519 BadNumberZero ->
520 parseReport
521 "Normal numbers cannot start with a zero. Take the zeros off the front."
522 ( reflowParagraph $
523 "Only numbers like 0x0040 or 0.25 can start with a zero."
524 )
526 BadShader msg ->
527 parseReport
528 "I ran into a problem while parsing this GLSL block."
529 (reflowParagraph msg)
531 BadOp op stack ->
532 case op of
533 HasType ->
534 badOp subRegion stack "A" "\"has type\" operator"
535 "type annotations and record types"
536 "Maybe you want :: instead? Or maybe something is indented too much?"
538 Equals ->
539 badEquals subRegion stack
541 Arrow ->
542 if isCaseRelated stack then
543 parseReport
544 "I ran into a stray arrow while parsing this `case` expression."
545 ( reflowParagraph $
546 "All branches in a `case` must be indented the exact\
547 \ same amount, so the patterns are vertically\
548 \ aligned. Maybe this branch is indented too much?"
549 )
551 else
552 badOp subRegion stack "An" "arrow"
553 "cases expressions and anonymous functions"
554 "Maybe you want > or >= instead?"
556 Pipe ->
557 badOp subRegion stack "A" "vertical bar"
558 "type declarations"
559 "Maybe you want || instead?"
561 Dot ->
562 parseReport
563 "I was not expecting this dot."
564 ( reflowParagraph $
565 "Dots are for record access and decimal points, so\
566 \ they cannot float around on their own. Maybe\
567 \ there is some extra whitespace?"
568 )
570 Theories stack allTheories ->
571 let
572 starter =
573 "Something went wrong while parsing "
574 <> contextToText "your code" "" stack
575 <> "."
576 in
577 parseReport starter $
578 case Set.toList (Set.fromList allTheories) of
579 [] ->
580 Help.stack
581 [ reflowParagraph $
582 "I do not have any suggestions though!"
583 , reflowParagraph $
584 "Can you get it down to a <http://sscce.org> and share it at\
585 \ <https://github.com/elm-lang/error-message-catalog/issues>?\
586 \ That way we can figure out how to give better advice!"
587 ]
589 [theory] ->
590 reflowParagraph $
591 "I was expecting to see "
592 <> addPeriod (theoryToText stack theory)
594 theories ->
595 Help.vcat $
596 [ text "I was expecting:"
597 , text ""
598 ]
599 ++ map (bullet . theoryToText stack) theories
602bullet :: Text -> Help.Doc
603bullet point =
604 Help.hang 4 (" - " <> reflowParagraph point)
607addPeriod :: Text -> Text
608addPeriod msg =
609 if Text.last msg `elem` ['`', ')', '.', '!', '?'] then
610 msg
611 else
612 msg <> "."
615badOp :: Maybe R.Region -> ContextStack -> Text -> Text -> Text -> Text -> Report.Report
616badOp subRegion stack article opName setting hint =
617 let
618 pre =
619 "I was not expecting this " <> opName
620 <> contextToText "" " while parsing " stack <> "."
621 in
622 makeParseReport subRegion pre $
623 reflowParagraph $
624 article <> " " <> opName <> " should only appear in "
625 <> setting <> ". " <> hint
628badEquals :: Maybe R.Region -> ContextStack -> Report.Report
629badEquals subRegion stack =
630 let
631 pre =
632 "I was not expecting this equals sign"
633 <> contextToText "" " while parsing " stack <> "."
634 in
635 makeParseReport subRegion pre (badEqualsHelp stack)
638badEqualsHelp :: ContextStack -> Help.Doc
639badEqualsHelp stack =
640 case stack of
641 [] ->
642 reflowParagraph $
643 "Maybe you want == instead? Or maybe something is indented too much?"
645 (ExprRecord, _) : _ ->
646 reflowParagraph $
647 "Records look like { x = 3, y = 4 } with the equals sign right\
648 \ after the field name. Maybe you forgot a comma?"
650 (Definition _, _) : rest ->
651 reflowParagraph $
652 "Maybe this is supposed to be a separate definition? If so, it\
653 \ is indented too far. "
654 <>
655 if any ((==) ExprLet . fst) rest then
656 "All definitions in a `let` expression must be vertically aligned."
657 else
658 "Spaces are not allowed before top-level definitions."
660 _ : rest ->
661 badEqualsHelp rest
664contextToText :: Text -> Text -> ContextStack -> Text
665contextToText defaultText prefixText stack =
666 case stack of
667 [] ->
668 defaultText
670 (context, _) : rest ->
671 let anchor = getAnchor rest in
672 prefixText <>
673 case context of
674 ExprIf -> "an `if`" <> anchor
675 ExprLet -> "a `let`" <> anchor
676 ExprFunc -> "an anonymous function" <> anchor
677 ExprCase -> "a `case`" <> anchor
678 ExprList -> "a list" <> anchor
679 ExprTuple -> "an expression (in parentheses)" <> anchor
680 ExprRecord -> "a record" <> anchor
681 Definition name -> name <> "'s definition"
682 Annotation name -> name <> "'s type annotation"
683 TypeTuple -> "a type (in parentheses)" <> anchor
684 TypeRecord -> "a record type" <> anchor
685 PatternList -> "a list pattern" <> anchor
686 PatternTuple -> "a pattern (in parentheses)" <> anchor
687 PatternRecord -> "a record pattern" <> anchor
688 Module -> "a module declaration"
689 Import -> "an import"
690 TypeUnion -> "a union type"
691 TypeAlias -> "a type alias"
692 Infix -> "an infix declaration"
693 Port -> "a port declaration"
696getAnchor :: ContextStack -> Text
697getAnchor stack =
698 case stack of
699 [] ->
700 ""
702 (context, _) : rest ->
703 case context of
704 Definition name ->
705 " in " <> name <> "'s definition"
707 Annotation name ->
708 " in " <> name <> "'s type annotation"
710 _ ->
711 getAnchor rest
714isCaseRelated :: ContextStack -> Bool
715isCaseRelated stack =
716 case stack of
717 [] ->
718 False
720 (context, _) : rest ->
721 context == ExprCase || isCaseRelated rest
724theoryToText :: ContextStack -> Theory -> Text
725theoryToText context theory =
726 case theory of
727 Keyword keyword ->
728 "the `" <> keyword <> "` keyword"
730 Symbol symbol ->
731 case symbol of
732 "=" -> equalsTheory context
733 "->" -> "an arrow (->) followed by an expression"
734 ":" -> "the \"has type\" symbol (:) followed by a type"
735 "," -> "a comma"
736 "|" -> barTheory context
737 "::" -> "the cons operator (::) followed by more list elements"
738 "." -> "a dot (.)"
739 "-" -> "a minus sign (-)"
740 "_" -> "an underscore"
741 "(" -> "a left paren, for grouping or starting tuples"
742 ")" -> "a closing paren"
743 "[" -> "a left square bracket, for starting lists"
744 "]" -> "a right square bracket, to end a list"
745 "{" -> "a left curly brace, for starting records"
746 "}" -> "a right curly brace, to end a record"
747 "{-|" -> "a doc comment, like {-| example -}"
748 _ -> "the (" <> symbol <> ") symbol"
750 LowVar ->
751 "a lower-case variable, like `x` or `user`"
753 CapVar ->
754 "an upper-case variable, like `Maybe` or `Just`"
756 InfixOp ->
757 "an infix operator, like (+) or (==)"
759 Digit ->
760 "a digit from 0 to 9"
762 BadSpace ->
763 badSpace context
765 Expecting next ->
766 case next of
767 Decl -> "a declaration, like `x = 5` or `type alias Model = { ... }`"
768 Expr -> "an expression, like x or 42"
769 AfterOpExpr op -> "an expression after that (" <> op <> ") operator, like x or 42"
770 ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
771 Arg -> "an argument, like `name` or `total`"
772 Pattern -> "a pattern, like `name` or (Just x)"
773 Type -> "a type, like Int or (List String)"
774 Listing -> "a list of exposed values and types, like (..) or (x,y,z)"
775 Exposing -> "something like `exposing (..)`"
778equalsTheory :: ContextStack -> Text
779equalsTheory stack =
780 case stack of
781 [] ->
782 "an equals sign (=)"
784 (context, _) : rest ->
785 case context of
786 ExprRecord -> "an equals sign (=) followed by an expression"
787 Definition name -> "an equals sign (=) followed by " <> name <> "'s definition"
788 TypeUnion -> "an equals sign (=) followed by the first union type constructor"
789 TypeAlias -> "an equals sign (=) followed by the aliased type"
790 _ -> equalsTheory rest
793barTheory :: ContextStack -> Text
794barTheory stack =
795 case stack of
796 [] ->
797 "a vertical bar (|)"
799 (context, _) : rest ->
800 case context of
801 ExprRecord -> "a vertical bar (|) followed by the record fields you want to update"
802 TypeRecord -> "a vertical bar (|) followed by some record field types"
803 TypeUnion -> "a vertical bar (|) followed by more union type constructors"
804 _ -> barTheory rest
807badSpace :: ContextStack -> Text
808badSpace stack =
809 case stack of
810 [] ->
811 "more indentation? I was not done with that last thing yet."
813 (context, _) : rest ->
814 case context of
815 ExprIf -> "the end of that `if`" <> badSpaceExprEnd rest
816 ExprLet -> "the end of that `let`" <> badSpaceExprEnd rest
817 ExprFunc -> badSpace rest
818 ExprCase -> "more of that `case`" <> badSpaceExprEnd rest
819 ExprList -> "the end of that list" <> badSpaceExprEnd rest
820 ExprTuple -> "a closing paren" <> badSpaceExprEnd rest
821 ExprRecord -> "the end of that record" <> badSpaceExprEnd rest
822 Definition name -> "the rest of " <> name <> "'s definition" <> badSpaceExprEnd stack
823 Annotation name -> "the rest of " <> name <> "'s type annotation" <> badSpaceEnd
824 TypeTuple -> "a closing paren" <> badSpaceEnd
825 TypeRecord -> "the end of that record" <> badSpaceEnd
826 PatternList -> "the end of that list" <> badSpaceEnd
827 PatternTuple -> "a closing paren" <> badSpaceEnd
828 PatternRecord -> "the end of that record" <> badSpaceEnd
829 Module -> "something like `module Main exposing (..)`"
830 Import -> "something like `import Html exposing (..)`"
831 TypeUnion -> "more of that union type" <> badSpaceEnd
832 TypeAlias -> "more of that type alias" <> badSpaceEnd
833 Infix -> "more of that infix declaration" <> badSpaceEnd
834 Port -> "more of that port declaration" <> badSpaceEnd
837badSpaceEnd :: Text
838badSpaceEnd =
839 ". Maybe you forgot some code? Or you need more indentation?"
842badSpaceExprEnd :: ContextStack -> Text
843badSpaceExprEnd stack =
844 case stack of
845 [] ->
846 badSpaceEnd
848 (Definition name, R.Position _ column) : _ ->
849 let
850 ending =
851 if column <= 1 then
852 "to be indented?"
853 else
854 "more indentation? (Try " <> i2t (column + 1) <> "+ spaces.)"
855 in
856 ". Maybe you forgot some code? Or maybe the body of `" <> name
857 <> "` needs " <> ending
859 _ : rest ->
860 badSpaceExprEnd rest