on 7dd0bbd help sign in
elk/src/Reporting/Error/Syntax.hs
820 lines 27 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(..), NextDecl(..)
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 | EndOfFile
94 | FreshLine NextDecl
95 | BadSpace
96 deriving (Eq, Ord)
99data Next
100 = Decl
101 | Expr
102 | AfterOpExpr Text
103 | ElseBranch
104 | Arg
105 | Pattern
106 | Type
107 | Listing
108 | Exposing
109 deriving (Eq, Ord)
112data NextDecl = ModuleDecl | DocCommentDecl | ImportDecl | OtherDecl
113 deriving (Eq, Ord)
116type ContextStack = [(Context, R.Position)]
119data Context
120 = ExprIf
121 | ExprLet
122 | ExprFunc
123 | ExprCase
124 | ExprList
125 | ExprTuple
126 | ExprRecord
127 ----------------
128 | Definition Text
129 | Annotation Text
130 ----------------
131 | TypeTuple
132 | TypeRecord
133 ----------------
134 | PatternList
135 | PatternTuple
136 | PatternRecord
137 ----------------
138 | Module
139 | Import
140 | TypeUnion
141 | TypeAlias
142 | Infix
143 | Port
144 deriving (Eq, Ord, Show)
148-- TO REPORT
151toReport :: RenderType.Localizer -> Error -> Report.Report
152toReport _localizer err =
153 case err of
154 Parse subRegion problem ->
155 problemToReport subRegion problem
157 BadFunctionName arity ->
158 Report.report
159 "BAD FUNCTION DEFINITION"
160 Nothing
161 "Complex patterns cannot be used as function names."
162 ( reflowParagraph $
163 "This function definition has " <> i2t arity <> " arguments, but instead\
164 \ of a normal name like `add` or `reverse` it has a pattern. There is no\
165 \ way to \"deconstruct\" a function with pattern matching, so this needs to\
166 \ be changed to a normal name."
167 )
169 BadPattern name ->
170 Report.report
171 "BAD PATTERN"
172 Nothing
173 ("The free variable `" <> name <> "` appears more than once in this pattern.")
174 ( Help.stack
175 [ text "Rename the variables so there are no duplicates."
176 , reflowParagraph $
177 "In Elm, pattern matching works by binding these free variables to subsections\
178 \ of the matching value. It does not make sense to have the same name for two\
179 \ different subsections though! When you say `" <> name <> "` in some code, there\
180 \ is no way for me to know which subsection you mean!"
181 ]
182 )
184 CommentOnNothing ->
185 Report.report
186 "STRAY COMMENT"
187 Nothing
188 ("This documentation comment is not followed by anything.")
189 ( reflowParagraph $
190 "All documentation comments need to be right above the declaration they\
191 \ describe. Maybe some code got deleted or commented out by accident? Or\
192 \ maybe this comment is here by accident?"
193 )
195 SettingsOnNormalModule ->
196 Report.report
197 "BAD MODULE DECLARATION"
198 Nothing
199 "A normal module can expose values, but not settings like this."
200 ( reflowParagraph $
201 "If you want a normal module, just remove this stuff. If you want to create\
202 \ an `effect module` you forgot to use the `effect` keyword. In that\
203 \ case, change `module` to `effect module` and you should be headed in\
204 \ the right direction!"
205 )
207 SettingsOnPortModule ->
208 Report.report
209 "BAD MODULE DECLARATION"
210 Nothing
211 "A port module can expose values, but not have settings like this."
212 ( reflowParagraph $
213 "If you want a port module, just remove this stuff. If you want to create\
214 \ a custom effect module instead (which is rare) change `port module`\
215 \ to `effect module` and you should be headed in the right direction!"
216 )
218 DuplicateSettingOnEffectModule name ->
219 Report.report
220 "EFFECT MODULE PROBLEM"
221 Nothing
222 ("You have defined " <> Help.functionName name <> " multiple times.")
223 ( reflowParagraph $
224 "There can only be one " <> Help.functionName name
225 <> " though! Remove until there is one left."
226 )
228 BadSettingOnEffectModule name ->
229 Report.report
230 "EFFECT MODULE PROBLEM"
231 Nothing
232 ("Setting " <> Help.functionName name <> " is not recognized.")
233 ( reflowParagraph $
234 "Remove this entry and you should be all set!"
235 )
237 NoSettingsOnEffectModule ->
238 Report.report
239 "EFFECT MODULE PROBLEM"
240 Nothing
241 ("You are defining an effect module, but it has no settings.")
242 ( reflowParagraph $
243 "If you just wanted a normal module, change the keywords `effect module`\
244 \ to `module` and you should be all set. If you want a proper effect module,\
245 \ you need to specify your commands and/or subscriptions. Read more about this\
246 \ here: <http://guide.elm-lang.org/effect_managers/>"
247 )
249 MissingManagerOnEffectModule name ->
250 Report.report
251 "EFFECT MODULE PROBLEM"
252 Nothing
253 ("You are defining an effect module, but there is no " <> Help.functionName name <> " defined.")
254 ( reflowParagraph $
255 "There is a small set of top-level functions and values that must be defined\
256 \ in any complete effect module. The best thing is probably to just read more\
257 \ about effect modules here:\
258 \ <http://guide.elm-lang.org/effect_managers/>"
259 )
261 UnexpectedPort name ->
262 Report.report
263 "BAD PORT"
264 Nothing
265 ("You are declaring port " <> Help.functionName name <> " in a normal module.")
266 ( reflowParagraph $
267 "All ports must be defined in a `port module`. You should probably have only\
268 \ one of these for your project. This way all of your foreign interactions\
269 \ stay relatively organized."
270 )
272 TypeWithoutDefinition valueName ->
273 Report.report
274 "MISSING DEFINITION"
275 Nothing
276 ("There is a type annotation for `" <> valueName <> "` but there"
277 <> " is no corresponding definition!"
278 )
279 ( text $
280 "Directly below the type annotation, put a definition like:\n\n"
281 <> " " <> valueName <> " = 42"
282 )
284 DuplicateArgument funcName argName ->
285 Report.report
286 "DUPLICATE ARGUMENT"
287 Nothing
288 ( "The name `" <> argName
289 <> "` is used more than once in the arguments of "
290 <> Help.functionName funcName <> "."
291 )
292 ( reflowParagraph $
293 "Rename things until `" <> argName <> "` is used only once.\
294 \ Otherwise how can we tell which one you want when you\
295 \ say `" <> argName <> "` it in the body of your function?"
296 )
298 DuplicateFieldName region name ->
299 Report.report
300 "DUPLICATE FIELD"
301 (Just region)
302 ("This record has more than one field named `" <> name <> "`.")
303 (text "There can only be one. Do some renaming to make sure the names are distinct!")
305 DuplicateValueDeclaration name ->
306 Report.report
307 "DUPLICATE DEFINITION"
308 Nothing
309 ( "Naming multiple top-level values " <> Help.functionName name <> " makes things\n"
310 <> "ambiguous. When you say " <> Help.functionName name <> " which one do you want?"
311 )
312 ( reflowParagraph $
313 "Find all the top-level values named " <> Help.functionName name
314 <> " and do some renaming. Make sure the names are distinct!"
315 )
317 DuplicateTypeDeclaration name ->
318 Report.report
319 "DUPLICATE DEFINITION"
320 Nothing
321 ( "There are multiple types named `" <> name <> "` in this module."
322 )
323 ( reflowParagraph $
324 "Search through this module, find all the types named `"
325 <> name <> "`, and give each of them a unique name."
326 )
328 DuplicateDefinition name ->
329 Report.report
330 "DUPLICATE DEFINITION"
331 Nothing
332 ("There are multiple values named `" <> name <> "` in this let-expression."
333 )
334 ( reflowParagraph $
335 "Search through this let-expression, find all the values named `"
336 <> name <> "`, and give each of them a unique name."
337 )
339 UnboundTypeVarsInUnion typeName givenVars unbound ->
340 unboundTypeVars "type" typeName givenVars unbound
342 UnboundTypeVarsInAlias typeName givenVars unbound ->
343 unboundTypeVars "type alias" typeName givenVars unbound
345 UnusedTypeVarsInAlias typeName givenVars unused ->
346 Report.report
347 "UNUSED TYPE VARIABLES"
348 Nothing
349 ( "Type alias `" <> typeName <> "` cannot have unused type variables: "
350 <> Help.commaSep unused
351 )
352 ( Help.stack
353 [ text "You probably need to change the declaration like this:"
354 , dullyellow $ hsep $
355 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ ["=", "..."])
356 ]
357 )
359 MessyTypeVarsInAlias typeName givenVars unused unbound ->
360 Report.report
361 "TYPE VARIABLE PROBLEMS"
362 Nothing
363 ( "Type alias `" <> typeName <> "` has some problems with type variables."
364 )
365 ( Help.stack
366 [ reflowParagraph $
367 "The declaration says it uses certain type variables ("
368 <> Help.commaSep unused <> ") but they do not appear in the aliased type. "
369 <> "Furthermore, the aliased type says it uses type variables ("
370 <> Help.commaSep unbound
371 <> ") that do not appear in the declaration."
372 , text "You probably need to change the declaration like this:"
373 , dullyellow $ hsep $
374 map text ("type" : "alias" : typeName : filter (`notElem` unused) givenVars ++ unbound ++ ["=", "..."])
375 ]
376 )
379unboundTypeVars :: Text -> Text -> [Text] -> [Text] -> Report.Report
380unboundTypeVars declKind typeName givenVars unboundVars =
381 Report.report
382 "UNBOUND TYPE VARIABLES"
383 Nothing
384 ( Help.capitalize declKind <> " `" <> typeName <> "` must declare its use of type variable"
385 <> Help.commaSep unboundVars
386 )
387 ( Help.stack
388 [ text "You probably need to change the declaration like this:"
389 , hsep $
390 map text (declKind : typeName : givenVars)
391 ++ map (dullyellow . text) unboundVars
392 ++ map text ["=", "..."]
393 , reflowParagraph $
394 "Here's why. Imagine one `" <> typeName <> "` where `" <> head unboundVars <>
395 "` is an Int and another where it is a Bool. When we explicitly list the type\
396 \ variables, the type checker can see that they are actually different types."
397 ]
398 )
402-- PARSE ERROR TO REPORT
405makeParseReport :: Maybe R.Region -> Text -> Help.Doc -> Report.Report
406makeParseReport subRegion pre post =
407 Report.report "PARSE ERROR" subRegion pre post
410problemToReport :: Maybe R.Region -> Problem -> Report.Report
411problemToReport subRegion problem =
412 let parseReport = makeParseReport subRegion in
413 case problem of
414 Tab ->
415 parseReport
416 "I ran into a tab, but tabs are not allowed in Elm files."
417 (reflowParagraph "Replace the tab with spages.")
419 EndOfFile_Comment ->
420 parseReport
421 "I got to the end of the file while parsing a multi-line comment."
422 ( Help.stack
423 [ reflowParagraph $
424 "Multi-line comments look like {- comment -}, and it looks like\
425 \ you are missing the closing marker."
426 , reflowParagraph $
427 "Nested multi-line comments like {- this {- and this -} -} are allowed.\
428 \ That means the opening and closing markers must be balanced, just\
429 \ like parentheses in normal code. Maybe that is the problem?"
430 ]
431 )
433 EndOfFile_Shader ->
434 parseReport
435 "I got to the end of the file while parsing a GLSL block."
436 (reflowParagraph $
437 "A shader should be defined in a block like this: [glsl| ... |]"
438 )
440 EndOfFile_String ->
441 parseReport
442 "I got to the end of the file while parsing a string."
443 (reflowParagraph $
444 "Strings look like \"this\" with double quotes on each end.\
445 \ So the closing double quote seems to be missing."
446 )
448 EndOfFile_MultiString ->
449 parseReport
450 "I got to the end of the file while parsing a multi-line string."
451 (reflowParagraph $
452 "Multi-line strings begin and end with three double quotes in a\
453 \ row, like \"\"\"this\"\"\". So the closing marker seems\
454 \ to be missing."
455 )
457 NewLineInString ->
458 parseReport
459 "This string is missing the closing quote."
460 ( Help.stack
461 [ reflowParagraph $
462 "Elm strings must start and end with a double quote, like \"this\"."
463 , reflowParagraph $
464 "If you want a string that can contain newlines, use three double quotes in a\
465 \ row, like \"\"\"this\"\"\"."
466 ]
467 )
469 BadEscape ->
470 parseReport
471 "Ran into a bad escape code."
472 ( reflowParagraph
473 "Elm allows typical escape characters like \\n and \\t, but you can\
474 \ also use \\x0040 to refer to unicode characters by their hex code.\
475 \ It seems like something has gone wrong with one of these codes."
476 )
478 BadChar ->
479 parseReport
480 "Ran into a bad use of single quotes."
481 ( Help.stack
482 [ reflowParagraph $
483 "If you want to create a string, switch to double quotes:"
484 , Help.indent 4 $
485 dullyellow (text "'this'")
486 <> text " => "
487 <> dullyellow (text "\"this\"")
488 , reflowParagraph $
489 "Unlike JavaScript, Elm distinguishes between strings like \"hello\"\
490 \ and individual characters like 'A' and '3'. It is not all strings!\
491 \ If you really do want a character though, something went wrong\
492 \ and I did not find the closing single quote."
493 ]
494 )
496 BadNumberDot ->
497 parseReport
498 "Numbers cannot end with a decimal points."
499 ( reflowParagraph $
500 "Leave it off or add some digits after it, like or 3 or 3.0"
501 )
503 BadNumberEnd ->
504 parseReport
505 "Numbers cannot have letters or underscores in them."
506 ( reflowParagraph $
507 "Maybe a space is missing between a number and a variable?"
508 )
510 BadNumberExp ->
511 parseReport
512 "If you put the letter E in a number, it should followed by more digits."
513 ( reflowParagraph $
514 "If you want to say 1000, you can also say 1e3.\
515 \ You cannot just end it with an E though!"
516 )
518 BadNumberHex ->
519 parseReport
520 "I see the start of a hex number, but not the end."
521 ( reflowParagraph $
522 "A hex number looks like 0x123ABC, where the 0x is followed by hexidecimal digits (i.e. 0123456789abcdefABCDEF)"
523 )
525 BadNumberZero ->
526 parseReport
527 "Normal numbers cannot start with a zero. Take the zeros off the front."
528 ( reflowParagraph $
529 "Only numbers like 0x0040 or 0.25 can start with a zero."
530 )
532 BadShader msg ->
533 parseReport
534 "I ran into a problem while parsing this GLSL block."
535 (reflowParagraph msg)
537 BadOp op stack ->
538 case op of
539 HasType ->
540 badOp subRegion stack "the \"has type\" operator" "(:)"
541 "type annotations and record types"
542 "Maybe you want :: instead? Or maybe your indentation is a bit off?"
544 Equals ->
545 badOp subRegion stack "an equals sign" "(=)"
546 "definitions"
547 "Maybe you want == instead? Or maybe your indentation is a bit off?"
549 Arrow ->
550 if isCaseRelated stack then
551 parseReport
552 "I ran into a stray arrow (->) while parsing this `case` expression."
553 ( reflowParagraph $
554 "All branches in a `case` must be indented the exact\
555 \ same amount, so the patterns are vertically\
556 \ aligned. Maybe this branch is indented too much?"
557 )
559 else
560 badOp subRegion stack "an arrow" "(->)"
561 "cases expressions and anonymous functions"
562 "Maybe you want > or >= instead?"
564 Pipe ->
565 badOp subRegion stack "a vertical bar" "(|)"
566 "type declarations"
567 "Maybe you want || instead?"
569 Dot ->
570 parseReport
571 "I was not expecting a dot (.) here."
572 ( reflowParagraph $
573 "Dots are for record access and decimal points, so\
574 \ they cannot float around on their own. Maybe\
575 \ there is some extra whitespace?"
576 )
578 Theories stack allTheories ->
579 let
580 starter =
581 "Something went wrong while parsing "
582 <> contextToText "your code" "" stack
583 <> "."
584 in
585 parseReport starter $
586 case Set.toList (Set.fromList allTheories) of
587 [] ->
588 Help.stack
589 [ reflowParagraph $
590 "I do not have any suggestions though!"
591 , reflowParagraph $
592 "Can you get it down to a <http://sscce.org> and share it at\
593 \ <https://github.com/elm-lang/error-message-catalog/issues>?\
594 \ That way we can figure out how to give better advice!"
595 ]
597 [theory] ->
598 reflowParagraph $
599 "I was expecting to see "
600 <> addPeriod (theoryToText stack theory)
602 theories ->
603 Help.vcat $
604 [ text "I was expecting:"
605 , text ""
606 ]
607 ++ map (bullet . theoryToText stack) theories
610bullet :: Text -> Help.Doc
611bullet point =
612 Help.hang 4 (" - " <> reflowParagraph point)
615addPeriod :: Text -> Text
616addPeriod msg =
617 if Text.last msg `elem` ['`', ')', '.', '!', '?'] then
618 msg
619 else
620 msg <> "."
623badOp :: Maybe R.Region -> ContextStack -> Text -> Text -> Text -> Text -> Report.Report
624badOp subRegion stack opName op setting hint =
625 makeParseReport subRegion ("I was not expecting " <> opName <> " here.") $
626 Help.stack
627 [ reflowParagraph $
628 "A " <> op <> " should only appear in " <> setting
629 <> contextToText "" ", but I think I am parsing " stack <> "."
630 , reflowParagraph hint
631 ]
634contextToText :: Text -> Text -> ContextStack -> Text
635contextToText defaultText prefixText stack =
636 case stack of
637 [] ->
638 defaultText
640 (context, _) : rest ->
641 let anchor = getAnchor rest in
642 prefixText <>
643 case context of
644 ExprIf -> "an `if`" <> anchor
645 ExprLet -> "a `let`" <> anchor
646 ExprFunc -> "an anonymous function" <> anchor
647 ExprCase -> "a `case`" <> anchor
648 ExprList -> "a list" <> anchor
649 ExprTuple -> "an expression (in parentheses)" <> anchor
650 ExprRecord -> "a record" <> anchor
651 Definition name -> name <> "'s definition"
652 Annotation name -> name <> "'s type annotation"
653 TypeTuple -> "a type (in parentheses)" <> anchor
654 TypeRecord -> "a record type" <> anchor
655 PatternList -> "a list pattern" <> anchor
656 PatternTuple -> "a pattern (in parentheses)" <> anchor
657 PatternRecord -> "a record pattern" <> anchor
658 Module -> "a module declaration"
659 Import -> "an import"
660 TypeUnion -> "a union type"
661 TypeAlias -> "a type alias"
662 Infix -> "an infix declaration"
663 Port -> "a port declaration"
666getAnchor :: ContextStack -> Text
667getAnchor stack =
668 case stack of
669 [] ->
670 ""
672 (context, _) : rest ->
673 case context of
674 Definition name ->
675 " in " <> name <> "'s definition"
677 Annotation name ->
678 " in " <> name <> "'s type annotation"
680 _ ->
681 getAnchor rest
684isCaseRelated :: ContextStack -> Bool
685isCaseRelated stack =
686 case stack of
687 [] ->
688 False
690 (context, _) : rest ->
691 context == ExprCase || isCaseRelated rest
694theoryToText :: ContextStack -> Theory -> Text
695theoryToText context theory =
696 case theory of
697 Keyword keyword ->
698 "the `" <> keyword <> "` keyword"
700 Symbol symbol ->
701 case symbol of
702 "=" -> equalsTheory context
703 "->" -> "an arrow (->) followed by an expression"
704 ":" -> "the \"has type\" symbol (:) followed by a type"
705 "," -> "a comma"
706 "|" -> barTheory context
707 "::" -> "the cons operator (::) followed by more list elements"
708 "." -> "a dot (.)"
709 "-" -> "a minus sign (-)"
710 "_" -> "an underscore"
711 "(" -> "a left paren, for grouping or starting tuples"
712 ")" -> "a closing paren"
713 "[" -> "a left square bracket, for starting lists"
714 "]" -> "a right square bracket, to end a list"
715 "{" -> "a left curly brace, for starting records"
716 "}" -> "a right curly brace, to end a record"
717 "{-|" -> "a doc comment, like {-| example -}"
718 _ -> "the (" <> symbol <> ") symbol"
720 LowVar ->
721 "a lower-case variable, like `x` or `user`"
723 CapVar ->
724 "an upper-case variable, like `Maybe` or `Just`"
726 InfixOp ->
727 "an infix operator, like (+) or (==)"
729 Digit ->
730 "a digit from 0 to 9"
732 EndOfFile ->
733 "the end of the file"
735 BadSpace ->
736 badSpace context
738 FreshLine nextDecl ->
739 "a fresh line (without any leading spaces) for " <>
740 case nextDecl of
741 ModuleDecl -> "something like `module Main exposing (..)`"
742 DocCommentDecl -> "something like `import Html exposing (text)`"
743 ImportDecl -> "an `import` or a declarations"
744 OtherDecl -> "a top-level declaration, like `view model = div [] [...]`"
746 Expecting next ->
747 case next of
748 Decl -> "a declaration, like `x = 5` or `type alias Model = { ... }`"
749 Expr -> "an expression, like x or 42"
750 AfterOpExpr op -> "an expression after that (" <> op <> ") operator, like x or 42"
751 ElseBranch -> "an `else` branch. An `if` must handle both possibilities."
752 Arg -> "an argument, like `name` or `total`"
753 Pattern -> "a pattern, like `name` or (Just x)"
754 Type -> "a type, like Int or (List String)"
755 Listing -> "a list of exposed values and types, like (..) or (x,y,z)"
756 Exposing -> "something like `exposing (..)`"
759equalsTheory :: ContextStack -> Text
760equalsTheory stack =
761 case stack of
762 [] ->
763 "an equals sign (=)"
765 (context, _) : rest ->
766 case context of
767 ExprRecord -> "an equals sign (=) followed by an expression"
768 Definition name -> "an equals sign (=) followed by " <> name <> "'s definition"
769 TypeUnion -> "an equals sign (=) followed by the first union type constructor"
770 TypeAlias -> "an equals sign (=) followed by the aliased type"
771 _ -> equalsTheory rest
774barTheory :: ContextStack -> Text
775barTheory stack =
776 case stack of
777 [] ->
778 "a vertical bar (|)"
780 (context, _) : rest ->
781 case context of
782 ExprRecord -> "a vertical bar (|) followed by the record fields you want to update"
783 TypeRecord -> "a vertical bar (|) followed by some record field types"
784 TypeUnion -> "a vertical bar (|) followed by more union type constructors"
785 _ -> barTheory rest
788badSpace :: ContextStack -> Text
789badSpace stack =
790 case stack of
791 [] ->
792 "more indentation? I was not done with that last thing yet."
794 (context, _) : rest ->
795 case context of
796 ExprIf -> "the end of that `if`" <> badSpaceEnd
797 ExprLet -> "the end of that `let`" <> badSpaceEnd
798 ExprFunc -> badSpace rest
799 ExprCase -> "more of that `case`" <> badSpaceEnd
800 ExprList -> "the end of that list" <> badSpaceEnd
801 ExprTuple -> "a closing paren" <> badSpaceEnd
802 ExprRecord -> "the end of that record" <> badSpaceEnd
803 Definition name -> "the rest of " <> name <> "'s definition" <> badSpaceEnd
804 Annotation name -> "the rest of " <> name <> "'s type annotation" <> badSpaceEnd
805 TypeTuple -> "a closing paren" <> badSpaceEnd
806 TypeRecord -> "the end of that record" <> badSpaceEnd
807 PatternList -> "the end of that list" <> badSpaceEnd
808 PatternTuple -> "a closing paren" <> badSpaceEnd
809 PatternRecord -> "the end of that record" <> badSpaceEnd
810 Module -> "something like `module Main exposing (..)`"
811 Import -> "something like `import Html exposing (..)`"
812 TypeUnion -> "more of that union type" <> badSpaceEnd
813 TypeAlias -> "more of that type alias" <> badSpaceEnd
814 Infix -> "more of that infix declaration" <> badSpaceEnd
815 Port -> "more of that port declaration" <> badSpaceEnd
818badSpaceEnd :: Text
819badSpaceEnd =
820 ". Maybe you forgot some code? Or you need more indentation?"