on 7d2da8d help sign in
5401 lines 195 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 , toReport
6 --
7 , Module(..)
8 , Exposing(..)
9 --
10 , Decl(..)
11 , DeclType(..)
12 , TypeAlias(..)
13 , CustomType(..)
14 , DeclDef(..)
15 , Port(..)
16 --
17 , Expr(..)
18 , Record(..)
19 , Tuple(..)
20 , List(..)
21 , Func(..)
22 , Case(..)
23 , If(..)
24 , Let(..)
25 , Def(..)
26 , Destruct(..)
27 --
28 , Pattern(..)
29 , PRecord(..)
30 , PTuple(..)
31 , PList(..)
32 --
33 , Type(..)
34 , TRecord(..)
35 , TTuple(..)
36 --
37 , Char(..)
38 , String(..)
39 , Escape(..)
40 , Number(..)
41 --
42 , Space(..)
43 , toSpaceReport
44 )
45 where
48import Prelude hiding (Char, String)
49import qualified Data.Char as Char
50import qualified Data.Name as Name
51import Data.Word (Word16)
52import Numeric (showHex)
54import qualified Elm.ModuleName as ModuleName
55import Parse.Primitives (Row, Col)
56import Parse.Symbol (BadOperator(..))
57import qualified Reporting.Annotation as A
58import qualified Reporting.Doc as D
59import qualified Reporting.Report as Report
60import qualified Reporting.Render.Code as Code
64-- ALL SYNTAX ERRORS
67data Error
68 = ModuleNameUnspecified ModuleName.Raw
69 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
70 | UnexpectedPort A.Region
71 | NoPorts A.Region
72 | ParseError Module
76-- MODULE
79data Module
80 = ModuleSpace Space Row Col
81 | ModuleBadEnd Row Col
82 --
83 | ModuleProblem Row Col
84 | ModuleName Row Col
85 | ModuleExposing Exposing Row Col
86 --
87 | PortModuleProblem Row Col
88 | PortModuleName Row Col
89 | PortModuleExposing Exposing Row Col
90 --
91 | Effect Row Col
92 --
93 | FreshLine Row Col
94 --
95 | ImportStart Row Col
96 | ImportName Row Col
97 | ImportAs Row Col
98 | ImportAlias Row Col
99 | ImportExposing Row Col
100 | ImportExposingList Exposing Row Col
101 | ImportEnd Row Col -- different based on col=1 or if greater
102 --
103 | ImportIndentName Row Col
104 | ImportIndentAlias Row Col
105 | ImportIndentExposingList Row Col
106 --
107 | Infix Row Col
108 --
109 | Declarations Decl Row Col
112data Exposing
113 = ExposingSpace Space Row Col
114 | ExposingStart Row Col
115 | ExposingValue Row Col
116 | ExposingOperator Row Col
117 | ExposingOperatorReserved BadOperator Row Col
118 | ExposingOperatorRightParen Row Col
119 | ExposingTypePrivacy Row Col
120 | ExposingEnd Row Col
121 --
122 | ExposingIndentEnd Row Col
123 | ExposingIndentValue Row Col
127-- DECLARATIONS
130data Decl
131 = DeclStart Row Col
132 | DeclSpace Space Row Col
133 --
134 | Port Port Row Col
135 | DeclType DeclType Row Col
136 | DeclDef Name.Name DeclDef Row Col
137 --
138 | DeclFreshLineAfterDocComment Row Col
141data DeclDef
142 = DeclDefSpace Space Row Col
143 | DeclDefEquals Row Col
144 | DeclDefType Type Row Col
145 | DeclDefArg Pattern Row Col
146 | DeclDefBody Expr Row Col
147 | DeclDefNameRepeat Row Col
148 | DeclDefNameMatch Name.Name Row Col
149 --
150 | DeclDefIndentType Row Col
151 | DeclDefIndentEquals Row Col
152 | DeclDefIndentBody Row Col
155data Port
156 = PortSpace Space Row Col
157 | PortName Row Col
158 | PortColon Row Col
159 | PortType Type Row Col
160 | PortIndentName Row Col
161 | PortIndentColon Row Col
162 | PortIndentType Row Col
166-- TYPE DECLARATIONS
169data DeclType
170 = DT_Space Space Row Col
171 | DT_Name Row Col
172 | DT_Alias TypeAlias Row Col
173 | DT_Union CustomType Row Col
174 --
175 | DT_IndentName Row Col
178data TypeAlias
179 = AliasSpace Space Row Col
180 | AliasName Row Col
181 | AliasEquals Row Col
182 | AliasBody Type Row Col
183 --
184 | AliasIndentEquals Row Col
185 | AliasIndentBody Row Col
188data CustomType
189 = CT_Space Space Row Col
190 | CT_Name Row Col
191 | CT_Equals Row Col
192 | CT_Bar Row Col
193 | CT_Variant Row Col
194 | CT_VariantArg Type Row Col
195 --
196 | CT_IndentEquals Row Col
197 | CT_IndentBar Row Col
198 | CT_IndentAfterBar Row Col
199 | CT_IndentAfterEquals Row Col
203-- EXPRESSIONS
206data Expr
207 = Let Let Row Col
208 | Case Case Row Col
209 | If If Row Col
210 | List List Row Col
211 | Record Record Row Col
212 | Tuple Tuple Row Col
213 | Func Func Row Col
214 --
215 | Dot Row Col
216 | Access Row Col
217 | OperatorRight Name.Name Row Col
218 | OperatorReserved BadOperator Row Col
219 --
220 | Start Row Col
221 | Char Char Row Col
222 | String String Row Col
223 | Number Number Row Col
224 | Space Space Row Col
225 | EndlessShader Row Col
226 | ShaderProblem [Char.Char] Row Col
227 | IndentOperatorRight Name.Name Row Col
230data Record
231 = RecordOpen Row Col
232 | RecordEnd Row Col
233 | RecordField Row Col
234 | RecordEquals Row Col
235 | RecordExpr Expr Row Col
236 | RecordSpace Space Row Col
237 --
238 | RecordIndentOpen Row Col
239 | RecordIndentEnd Row Col
240 | RecordIndentField Row Col
241 | RecordIndentEquals Row Col
242 | RecordIndentExpr Row Col
245data Tuple
246 = TupleExpr Expr Row Col
247 | TupleSpace Space Row Col
248 | TupleEnd Row Col
249 | TupleOperatorClose Row Col
250 | TupleOperatorReserved BadOperator Row Col
251 --
252 | TupleIndentExpr1 Row Col
253 | TupleIndentExprN Row Col
254 | TupleIndentEnd Row Col
257data List
258 = ListSpace Space Row Col
259 | ListOpen Row Col
260 | ListExpr Expr Row Col
261 | ListEnd Row Col
262 --
263 | ListIndentOpen Row Col
264 | ListIndentEnd Row Col
265 | ListIndentExpr Row Col
268data Func
269 = FuncSpace Space Row Col
270 | FuncArg Pattern Row Col
271 | FuncBody Expr Row Col
272 | FuncArrow Row Col
273 --
274 | FuncIndentArg Row Col
275 | FuncIndentArrow Row Col
276 | FuncIndentBody Row Col
279data Case
280 = CaseSpace Space Row Col
281 | CaseOf Row Col
282 | CasePattern Pattern Row Col
283 | CaseArrow Row Col
284 | CaseExpr Expr Row Col
285 | CaseBranch Expr Row Col
286 --
287 | CaseIndentOf Row Col
288 | CaseIndentExpr Row Col
289 | CaseIndentPattern Row Col
290 | CaseIndentArrow Row Col
291 | CaseIndentBranch Row Col
292 | CasePatternAlignment Word16 Row Col
295data If
296 = IfSpace Space Row Col
297 | IfThen Row Col
298 | IfElse Row Col
299 | IfElseBranchStart Row Col
300 --
301 | IfCondition Expr Row Col
302 | IfThenBranch Expr Row Col
303 | IfElseBranch Expr Row Col
304 --
305 | IfIndentCondition Row Col
306 | IfIndentThen Row Col
307 | IfIndentThenBranch Row Col
308 | IfIndentElseBranch Row Col
309 | IfIndentElse Row Col
312data Let
313 = LetSpace Space Row Col
314 | LetIn Row Col
315 | LetDefAlignment Word16 Row Col
316 | LetDefName Row Col
317 | LetDef Name.Name Def Row Col
318 | LetDestruct Destruct Row Col
319 | LetBody Expr Row Col
320 | LetIndentDef Row Col
321 | LetIndentIn Row Col
322 | LetIndentBody Row Col
325data Def
326 = DefSpace Space Row Col
327 | DefType Type Row Col
328 | DefNameRepeat Row Col
329 | DefNameMatch Name.Name Row Col
330 | DefArg Pattern Row Col
331 | DefEquals Row Col
332 | DefBody Expr Row Col
333 | DefIndentEquals Row Col
334 | DefIndentType Row Col
335 | DefIndentBody Row Col
336 | DefAlignment Word16 Row Col
339data Destruct
340 = DestructSpace Space Row Col
341 | DestructPattern Pattern Row Col
342 | DestructEquals Row Col
343 | DestructBody Expr Row Col
344 | DestructIndentEquals Row Col
345 | DestructIndentBody Row Col
349-- PATTERNS
352data Pattern
353 = PRecord PRecord Row Col
354 | PTuple PTuple Row Col
355 | PList PList Row Col
356 --
357 | PStart Row Col
358 | PChar Char Row Col
359 | PString String Row Col
360 | PNumber Number Row Col
361 | PFloat Word16 Row Col
362 | PAlias Row Col
363 | PWildcardNotVar Name.Name Int Row Col
364 | PSpace Space Row Col
365 --
366 | PIndentStart Row Col
367 | PIndentAlias Row Col
370data PRecord
371 = PRecordOpen Row Col
372 | PRecordEnd Row Col
373 | PRecordField Row Col
374 | PRecordSpace Space Row Col
375 --
376 | PRecordIndentOpen Row Col
377 | PRecordIndentEnd Row Col
378 | PRecordIndentField Row Col
381data PTuple
382 = PTupleOpen Row Col
383 | PTupleEnd Row Col
384 | PTupleExpr Pattern Row Col
385 | PTupleSpace Space Row Col
386 --
387 | PTupleIndentEnd Row Col
388 | PTupleIndentExpr1 Row Col
389 | PTupleIndentExprN Row Col
392data PList
393 = PListOpen Row Col
394 | PListEnd Row Col
395 | PListExpr Pattern Row Col
396 | PListSpace Space Row Col
397 --
398 | PListIndentOpen Row Col
399 | PListIndentEnd Row Col
400 | PListIndentExpr Row Col
404-- TYPES
407data Type
408 = TRecord TRecord Row Col
409 | TTuple TTuple Row Col
410 --
411 | TStart Row Col
412 | TSpace Space Row Col
413 --
414 | TIndentStart Row Col
417data TRecord
418 = TRecordOpen Row Col
419 | TRecordEnd Row Col
420 --
421 | TRecordField Row Col
422 | TRecordColon Row Col
423 | TRecordType Type Row Col
424 --
425 | TRecordSpace Space Row Col
426 --
427 | TRecordIndentOpen Row Col
428 | TRecordIndentField Row Col
429 | TRecordIndentColon Row Col
430 | TRecordIndentType Row Col
431 | TRecordIndentEnd Row Col
434data TTuple
435 = TTupleOpen Row Col
436 | TTupleEnd Row Col
437 | TTupleType Type Row Col
438 | TTupleSpace Space Row Col
439 --
440 | TTupleIndentType1 Row Col
441 | TTupleIndentTypeN Row Col
442 | TTupleIndentEnd Row Col
446-- LITERALS
449data Char
450 = CharEndless
451 | CharEscape Escape
452 | CharNotString Word16
455data String
456 = StringEndless_Single
457 | StringEndless_Multi
458 | StringEscape Escape
461data Escape
462 = EscapeUnknown
463 | BadUnicodeFormat Word16
464 | BadUnicodeCode Word16
465 | BadUnicodeLength Word16 Int Int
468data Number
469 = NumberEnd
470 | NumberDot Int
471 | NumberHexDigit
472 | NumberNoLeadingZero
476-- MISC
479data Space
480 = HasTab
481 | EndlessMultiComment
485-- TO REPORT
488toReport :: Code.Source -> Error -> Report.Report
489toReport source err =
490 case err of
491 ModuleNameUnspecified name ->
492 let
493 region = toRegion 1 1
494 in
495 Report.Report "MODULE NAME MISSING" region [] $
496 D.stack
497 [ D.reflow $
498 "I need the module name to be declared at the top of this file, like this:"
499 , D.indent 4 $ D.fillSep $
500 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
501 , D.reflow $
502 "Try adding that as the first line of your file!"
503 , D.toSimpleNote $
504 "It is best to replace (..) with an explicit list of types and\
505 \ functions you want to expose. When you know a value is only used\
506 \ within this module, you can refactor without worrying about uses\
507 \ elsewhere. Limiting exposed values can also speed up compilation\
508 \ because I can skip a bunch of work if I see that the exposed API\
509 \ has not changed."
510 ]
512 ModuleNameMismatch expectedName (A.At region actualName) ->
513 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
514 Code.toSnippet source region Nothing
515 (
516 "It looks like this module name is out of sync:"
517 ,
518 D.stack
519 [ D.reflow $
520 "I need it to match the file path, so I was expecting to see `"
521 ++ ModuleName.toChars expectedName
522 ++ "` here. Make the following change, and you should be all set!"
523 , D.indent 4 $
524 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
525 , D.toSimpleNote $
526 "I require that module names correspond to file paths. This makes it much\
527 \ easier to explore unfamiliar codebases! So if you want to keep the current\
528 \ module name, try renaming the file instead."
529 ]
530 )
532 UnexpectedPort region ->
533 Report.Report "UNEXPECTED PORTS" region [] $
534 Code.toSnippet source region Nothing
535 (
536 D.reflow $
537 "You are declaring ports in a normal module."
538 ,
539 D.stack
540 [ D.fillSep
541 ["Switch","this","to","say",D.cyan "port module","instead,"
542 ,"marking","that","this","module","contains","port","declarations."
543 ]
544 , D.link "Note"
545 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
546 "ports"
547 "to learn the syntax and how to use it effectively."
548 ]
549 )
551 NoPorts region ->
552 Report.Report "NO PORTS" region [] $
553 Code.toSnippet source region Nothing
554 (
555 D.reflow $
556 "This module does not declare any ports, but it says it will:"
557 ,
558 D.fillSep
559 ["Switch","this","to",D.cyan "module"
560 ,"and","you","should","be","all","set!"
561 ]
562 )
564 ParseError modul ->
565 toParseErrorReport source modul
568toParseErrorReport :: Code.Source -> Module -> Report.Report
569toParseErrorReport source modul =
570 case modul of
571 ModuleSpace space row col ->
572 toSpaceReport source space row col
574 ModuleBadEnd row col ->
575 case Code.whatIsNext source row col of
576 Code.Keyword keyword ->
577 let
578 region = toKeywordRegion row col keyword
579 in
580 Report.Report "RESERVED WORD" region [] $
581 Code.toSnippet source region Nothing
582 (
583 D.reflow $
584 "I got stuck on this reserved word:"
585 ,
586 D.reflow $
587 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
588 )
590 Code.Operator op ->
591 let
592 region = toKeywordRegion row col op
593 in
594 Report.Report "UNEXPECTED SYMBOL" region [] $
595 Code.toSnippet source region Nothing
596 (
597 D.reflow $
598 "I ran into an unexpected symbol:"
599 ,
600 D.reflow $
601 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
602 \ I can give a better hint from there?"
603 )
605 Code.Close term bracket ->
606 let
607 region = toRegion row col
608 in
609 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
610 Code.toSnippet source region Nothing
611 (
612 D.reflow $
613 "I ran into an unexpected " ++ term ++ ":"
614 ,
615 D.reflow $
616 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
617 )
619 Code.Other maybeChar ->
620 let
621 region = toRegion row col
622 in
623 case maybeChar of
624 Just ';' ->
625 Report.Report "UNEXPECTED SEMICOLON" region [] $
626 Code.toSnippet source region Nothing
627 (
628 D.reflow $
629 "I got stuck on this semicolon:"
630 ,
631 D.stack
632 [ D.reflow $ "Try removing it?"
633 , D.toSimpleNote $
634 "Some languages require semicolons at the end of each statement. These are\
635 \ often called C-like languages, and they usually share a lot of language design\
636 \ choices. (E.g. side-effects, for loops, etc.) Elm manages effects with commands\
637 \ and subscriptions instead, so there is no special syntax for \"statements\" and\
638 \ therefore no need to use semicolons to separate them. I think this will make\
639 \ more sense as you work through <https://guide.elm-lang.org> though!"
640 ]
641 )
643 Just ',' ->
644 Report.Report "UNEXPECTED COMMA" region [] $
645 Code.toSnippet source region Nothing
646 (
647 D.reflow $
648 "I got stuck on this comma:"
649 ,
650 D.stack
651 [ D.reflow $
652 "I do not think I am parsing a list or tuple right now. Try deleting the comma?"
653 , D.toSimpleNote $
654 "If this is supposed to be part of a list, the problem may be a bit earlier.\
655 \ Perhaps the opening [ is missing? Or perhaps some value in the list has an extra\
656 \ closing ] that is making me think the list ended earlier? The same kinds of\
657 \ things could be going wrong if this is supposed to be a tuple."
658 ]
659 )
661 Just '`' ->
662 Report.Report "UNEXPECTED CHARACTER" region [] $
663 Code.toSnippet source region Nothing
664 (
665 D.reflow $
666 "I got stuck on this character:"
667 ,
668 D.stack
669 [ D.reflow $
670 "It is not used for anything in Elm syntax. It is used for multi-line strings in\
671 \ some languages though, so if you want a string that spans multiple lines, you\
672 \ can use Elm's multi-line string syntax like this:"
673 , D.vcat
674 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
675 , mempty
676 , D.dullyellow "# Multi-line Strings"
677 , mempty
678 , D.dullyellow "- start with triple double quotes"
679 , D.dullyellow "- write whatever you want"
680 , D.dullyellow "- no need to escape newlines or double quotes"
681 , D.dullyellow "- end with triple double quotes"
682 , mempty
683 , D.dullyellow "\"\"\""
684 ]
685 , D.reflow $
686 "Otherwise I do not know what is going on! Try removing the character?"
687 ]
688 )
690 Just '$' ->
691 Report.Report "UNEXPECTED SYMBOL" region [] $
692 Code.toSnippet source region Nothing
693 (
694 D.reflow $
695 "I got stuck on this dollar sign:"
696 ,
697 D.reflow $
698 "It is not used for anything in Elm syntax. Are you coming from a language where\
699 \ dollar signs can be used in variable names? If so, try a name that (1) starts\
700 \ with a letter and (2) only contains letters, numbers, and underscores."
701 )
703 Just c | elem c ['#','@','!','%','~'] ->
704 Report.Report "UNEXPECTED SYMBOL" region [] $
705 Code.toSnippet source region Nothing
706 (
707 D.reflow $
708 "I got stuck on this symbol:"
709 ,
710 D.reflow $
711 "It is not used for anything in Elm syntax. Try removing it?"
712 )
714 _ ->
715 Report.Report "SYNTAX PROBLEM" region [] $
716 Code.toSnippet source region Nothing
717 (
718 D.reflow $
719 "I got stuck here:"
720 ,
721 D.reflow $
722 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
723 \ specific hints, but something is really tripping me up this time."
724 )
726 ModuleProblem row col ->
727 let
728 region = toRegion row col
729 in
730 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
731 Code.toSnippet source region Nothing
732 (
733 D.reflow $
734 "I am parsing an `module` declaration, but I got stuck here:"
735 ,
736 D.stack
737 [ D.reflow $
738 "Here are some examples of valid `module` declarations:"
739 , D.indent 4 $ D.vcat $
740 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
741 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
742 ]
743 , D.reflow $
744 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
745 \ of files when the public interface of a module stays the same, so exposing fewer\
746 \ values can help improve compile times!"
747 ]
748 )
750 ModuleName row col ->
751 let
752 region = toRegion row col
753 in
754 Report.Report "EXPECTING MODULE NAME" region [] $
755 Code.toSnippet source region Nothing
756 (
757 D.reflow $
758 "I was parsing an `module` declaration until I got stuck here:"
759 ,
760 D.stack
761 [ D.reflow $
762 "I was expecting to see the module name next, like in these examples:"
763 , D.indent 4 $ D.vcat $
764 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
765 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
766 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
767 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
768 ]
769 , D.reflow $
770 "Notice that the module names all start with capital letters. That is required!"
771 ]
772 )
774 ModuleExposing exposing row col ->
775 toExposingReport source exposing row col
777 PortModuleProblem row col ->
778 let
779 region = toRegion row col
780 in
781 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
782 Code.toSnippet source region Nothing
783 (
784 D.reflow $
785 "I am parsing an `port module` declaration, but I got stuck here:"
786 ,
787 D.stack
788 [ D.reflow $
789 "Here are some examples of valid `port module` declarations:"
790 , D.indent 4 $ D.vcat $
791 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
792 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
793 ]
794 , D.link "Note" "Read" "ports" "for more help."
795 ]
796 )
798 PortModuleName row col ->
799 let
800 region = toRegion row col
801 in
802 Report.Report "EXPECTING MODULE NAME" region [] $
803 Code.toSnippet source region Nothing
804 (
805 D.reflow $
806 "I was parsing an `module` declaration until I got stuck here:"
807 ,
808 D.stack
809 [ D.reflow $
810 "I was expecting to see the module name next, like in these examples:"
811 , D.indent 4 $ D.vcat $
812 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
813 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
814 ]
815 , D.reflow $
816 "Notice that the module names start with capital letters. That is required!"
817 ]
818 )
820 PortModuleExposing exposing row col ->
821 toExposingReport source exposing row col
823 Effect row col ->
824 let
825 region = toRegion row col
826 in
827 Report.Report "BAD MODULE DECLARATION" region [] $
828 Code.toSnippet source region Nothing
829 (
830 D.reflow $
831 "I cannot parse this module declaration:"
832 ,
833 D.reflow $
834 "This type of module is reserved for the @elm organization. It is used to\
835 \ define certain effects, avoiding building them into the compiler."
836 )
838 FreshLine row col ->
839 let
840 region = toRegion row col
842 toBadFirstLineReport keyword =
843 Report.Report "TOO MUCH INDENTATION" region [] $
844 Code.toSnippet source region Nothing
845 (
846 D.reflow $
847 "This `" ++ keyword ++ "` should not have any spaces before it:"
848 ,
849 D.reflow $
850 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
851 )
853 in
854 case Code.whatIsNext source row col of
855 Code.Keyword "module" -> toBadFirstLineReport "module"
856 Code.Keyword "import" -> toBadFirstLineReport "import"
857 Code.Keyword "type" -> toBadFirstLineReport "type"
858 Code.Keyword "port" -> toBadFirstLineReport "port"
859 _ ->
860 Report.Report "SYNTAX PROBLEM" region [] $
861 Code.toSnippet source region Nothing
862 (
863 D.reflow $
864 "I got stuck here:"
865 ,
866 D.stack
867 [ D.reflow $
868 "I am not sure what is going on, but I recommend starting an Elm\
869 \ file with the following lines:"
870 , D.vcat
871 [ D.fillSep [D.cyan "import","Html"]
872 , ""
873 , D.fillSep [D.green "main","="]
874 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
875 ]
876 , D.reflow $
877 "You should be able to copy those lines directly into your file. Check out the\
878 \ examples at <https://elm-lang.org/examples> for more help getting started!"
879 , D.toSimpleNote $
880 "This can also happen when something is indented too much!"
881 ]
882 )
884 ImportStart row col ->
885 toImportReport source row col
887 ImportName row col ->
888 let
889 region = toRegion row col
890 in
891 Report.Report "EXPECTING IMPORT NAME" region [] $
892 Code.toSnippet source region Nothing
893 (
894 D.reflow $
895 "I was parsing an `import` until I got stuck here:"
896 ,
897 D.stack
898 [ D.reflow $
899 "I was expecting to see a module name next, like in these examples:"
900 , D.indent 4 $ D.vcat $
901 [ D.fillSep [D.cyan "import","Dict"]
902 , D.fillSep [D.cyan "import","Maybe"]
903 , D.fillSep [D.cyan "import","Html.Attributes"]
904 , D.fillSep [D.cyan "import","Json.Decode"]
905 ]
906 , D.reflow $
907 "Notice that the module names all start with capital letters. That is required!"
908 ]
909 )
911 ImportAs row col ->
912 toImportReport source row col
914 ImportAlias row col ->
915 let
916 region = toRegion row col
917 in
918 Report.Report "EXPECTING IMPORT ALIAS" region [] $
919 Code.toSnippet source region Nothing
920 (
921 D.reflow $
922 "I was parsing an `import` until I got stuck here:"
923 ,
924 D.stack
925 [ D.reflow $
926 "I was expecting to see an alias next, like in these examples:"
927 , D.indent 4 $ D.vcat $
928 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
929 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
930 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
931 ]
932 , D.reflow $
933 "Notice that the alias always starts with a capital letter. That is required!"
934 ]
935 )
937 ImportExposing row col ->
938 toImportReport source row col
940 ImportExposingList exposing row col ->
941 toExposingReport source exposing row col
943 ImportEnd row col ->
944 toImportReport source row col
946 ImportIndentName row col ->
947 toImportReport source row col
949 ImportIndentAlias row col ->
950 toImportReport source row col
952 ImportIndentExposingList row col ->
953 let
954 region = toRegion row col
955 in
956 Report.Report "UNFINISHED IMPORT" region [] $
957 Code.toSnippet source region Nothing
958 (
959 D.reflow $
960 "I was parsing an `import` until I got stuck here:"
961 ,
962 D.stack
963 [ D.reflow $
964 "I was expecting to see the list of exposed values next. For example, here\
965 \ are two ways to expose values from the `Html` module:"
966 , D.indent 4 $ D.vcat $
967 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
968 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
969 ]
970 , D.reflow $
971 "I generally recommend the second style. It is more explicit, making it\
972 \ much easier to figure out where values are coming from in large projects!"
973 ]
974 )
976 Infix row col ->
977 let
978 region = toRegion row col
979 in
980 Report.Report "BAD INFIX" region [] $
981 Code.toSnippet source region Nothing
982 (
983 D.reflow $
984 "Something went wrong in this infix operator declaration:"
985 ,
986 D.reflow $
987 "This feature is used by the @elm organization to define the\
988 \ languages built-in operators."
989 )
991 Declarations decl _ _ ->
992 toDeclarationsReport source decl
996-- IMPORTS
999toImportReport :: Code.Source -> Row -> Col -> Report.Report
1000toImportReport source row col =
1001 let
1002 region = toRegion row col
1003 in
1004 Report.Report "UNFINISHED IMPORT" region [] $
1005 Code.toSnippet source region Nothing
1007 D.reflow $
1008 "I am partway through parsing an import, but I got stuck here:"
1010 D.stack
1011 [ D.reflow $
1012 "Here are some examples of valid `import` declarations:"
1013 , D.indent 4 $ D.vcat $
1014 [ D.fillSep [D.cyan "import","Html"]
1015 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
1016 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
1017 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1019 , D.reflow $
1020 "You are probably trying to import a different module, but try to make it look like one of these examples!"
1026-- EXPOSING
1029toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
1030toExposingReport source exposing startRow startCol =
1031 case exposing of
1032 ExposingSpace space row col ->
1033 toSpaceReport source space row col
1035 ExposingStart row col ->
1036 let
1037 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1038 region = toRegion row col
1039 in
1040 Report.Report "PROBLEM IN EXPOSING" region [] $
1041 Code.toSnippet source surroundings (Just region)
1043 D.reflow $
1044 "I want to parse exposed values, but I am getting stuck here:"
1046 D.stack
1047 [ D.fillSep $
1048 ["Exposed","values","are","always","surrounded","by","parentheses."
1049 ,"So","try","adding","a",D.green "(","here?"
1051 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
1052 , D.indent 4 $ D.vcat $
1053 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1054 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
1056 , D.reflow $
1057 "If you are getting tripped up, you can just expose everything for now. It should\
1058 \ get easier to make an explicit exposing list as you see more examples in the wild."
1062 ExposingValue row col ->
1063 case Code.whatIsNext source row col of
1064 Code.Keyword keyword ->
1065 let
1066 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1067 region = toKeywordRegion row col keyword
1068 in
1069 Report.Report "RESERVED WORD" region [] $
1070 Code.toSnippet source surroundings (Just region)
1072 D.reflow $
1073 "I got stuck on this reserved word:"
1075 D.reflow $
1076 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
1079 Code.Operator op ->
1080 let
1081 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1082 region = toKeywordRegion row col op
1083 in
1084 Report.Report "UNEXPECTED SYMBOL" region [] $
1085 Code.toSnippet source surroundings (Just region)
1087 D.reflow $
1088 "I got stuck on this symbol:"
1090 D.stack
1091 [ D.reflow $
1092 "If you are trying to expose an operator, add parentheses around it like this:"
1093 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1097 _ ->
1098 let
1099 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1100 region = toRegion row col
1101 in
1102 Report.Report "PROBLEM IN EXPOSING" region [] $
1103 Code.toSnippet source surroundings (Just region)
1105 D.reflow $
1106 "I got stuck while parsing these exposed values:"
1108 D.stack
1109 [ D.reflow $
1110 "I do not have an exact recommendation, so here are some valid examples\
1111 \ of `exposing` for reference:"
1112 , D.indent 4 $ D.vcat $
1113 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1114 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1116 , D.reflow $
1117 "These examples show how to expose types, variants, operators, and functions. Everything\
1118 \ should be some permutation of these examples, just with different names."
1122 ExposingOperator row col ->
1123 let
1124 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1125 region = toRegion row col
1126 in
1127 Report.Report "PROBLEM IN EXPOSING" region [] $
1128 Code.toSnippet source surroundings (Just region)
1130 D.reflow $
1131 "I just saw an open parenthesis, so I was expecting an operator next:"
1133 D.fillSep $
1134 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1135 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1136 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1140 ExposingOperatorReserved op row col ->
1141 let
1142 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1143 region = toRegion row col
1144 in
1145 Report.Report "RESERVED SYMBOL" region [] $
1146 Code.toSnippet source surroundings (Just region)
1148 D.reflow $
1149 "I cannot expose this as an operator:"
1151 case op of
1152 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1153 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1154 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1155 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1156 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1159 ExposingOperatorRightParen row col ->
1160 let
1161 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1162 region = toRegion row col
1163 in
1164 Report.Report "PROBLEM IN EXPOSING" region [] $
1165 Code.toSnippet source surroundings (Just region)
1167 D.reflow $
1168 "It looks like you are exposing an operator, but I got stuck here:"
1170 D.fillSep $
1171 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1172 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1176 ExposingEnd row col ->
1177 let
1178 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1179 region = toRegion row col
1180 in
1181 Report.Report "UNFINISHED EXPOSING" region [] $
1182 Code.toSnippet source surroundings (Just region)
1184 D.reflow $
1185 "I was partway through parsing exposed values, but I got stuck here:"
1187 D.reflow $
1188 "Maybe there is a comma missing before this?"
1191 ExposingTypePrivacy row col ->
1192 let
1193 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1194 region = toRegion row col
1195 in
1196 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1197 Code.toSnippet source surroundings (Just region)
1199 D.reflow $
1200 "It looks like you are trying to expose the variants of a custom type:"
1202 D.stack
1203 [ D.fillSep $
1204 ["You","need","to","write","something","like"
1205 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1206 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1207 ,"expressions","could","miss","a","variant","and","crash!"
1209 , D.toSimpleNote $
1210 "It is often best to keep the variants hidden! If someone pattern matches on\
1211 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1212 \ their `case` expressions do not cover all variants! So if you do not need\
1213 \ people to pattern match, keep the variants hidden and expose functions to\
1214 \ construct values of this type. This way you can add new variants as a MINOR change!"
1218 ExposingIndentEnd row col ->
1219 let
1220 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1221 region = toRegion row col
1222 in
1223 Report.Report "UNFINISHED EXPOSING" region [] $
1224 Code.toSnippet source surroundings (Just region)
1226 D.reflow $
1227 "I was partway through parsing exposed values, but I got stuck here:"
1229 D.stack
1230 [ D.fillSep $
1231 ["I","was","expecting","a","closing","parenthesis."
1232 ,"Try","adding","a",D.green ")","right","here?"
1234 , D.toSimpleNote $
1235 "I can get confused when there is not enough indentation, so if you already\
1236 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1240 ExposingIndentValue row col ->
1241 let
1242 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1243 region = toRegion row col
1244 in
1245 Report.Report "UNFINISHED EXPOSING" region [] $
1246 Code.toSnippet source surroundings (Just region)
1248 D.reflow $
1249 "I was partway through parsing exposed values, but I got stuck here:"
1251 D.reflow $
1252 "I was expecting another value to expose."
1257-- SPACES
1260toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1261toSpaceReport source space row col =
1262 case space of
1263 HasTab ->
1264 let
1265 region = toRegion row col
1266 in
1267 Report.Report "NO TABS" region [] $
1268 Code.toSnippet source region Nothing
1270 D.reflow $
1271 "I ran into a tab, but tabs are not allowed in Elm files."
1273 D.reflow $
1274 "Replace the tab with spaces."
1277 EndlessMultiComment ->
1278 let
1279 region = toWiderRegion row col 2
1280 in
1281 Report.Report "ENDLESS COMMENT" region [] $
1282 Code.toSnippet source region Nothing
1284 D.reflow $
1285 "I cannot find the end of this multi-line comment:"
1287 D.stack -- "{-"
1288 [ D.reflow "Add a -} somewhere after this to end the comment."
1289 , D.toSimpleHint
1290 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1291 \ that happens to contain another comment. Like parentheses and curly braces,\
1292 \ the start and end markers must always be balanced. Maybe that is the problem?"
1298-- DECLARATIONS
1301toRegion :: Row -> Col -> A.Region
1302toRegion row col =
1303 let
1304 pos = A.Position row col
1305 in
1306 A.Region pos pos
1309toWiderRegion :: Row -> Col -> Word16 -> A.Region
1310toWiderRegion row col extra =
1311 A.Region
1312 (A.Position row col)
1313 (A.Position row (col + extra))
1316toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1317toKeywordRegion row col keyword =
1318 A.Region
1319 (A.Position row col)
1320 (A.Position row (col + fromIntegral (length keyword)))
1323toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1324toDeclarationsReport source decl =
1325 case decl of
1326 DeclStart row col ->
1327 case Code.whatIsNext source row col of
1328 Code.Close term bracket ->
1329 let
1330 region = toRegion row col
1331 in
1332 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
1333 Code.toSnippet source region Nothing
1335 D.reflow $
1336 "I was not expecting to see a " ++ term ++ " here:"
1337 , D.reflow $
1338 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
1341 Code.Keyword keyword ->
1342 let
1343 region = toKeywordRegion row col keyword
1344 in
1345 Report.Report "RESERVED WORD" region [] $
1346 Code.toSnippet source region Nothing
1348 D.reflow $
1349 "I was not expecting to run into the `" ++ keyword ++ "` keyword here:"
1351 case keyword of
1352 "import" ->
1353 D.reflow $
1354 "It is reserved for declaring imports at the top of your module. If you want\
1355 \ another import, try moving it up top with the other imports. If you want to\
1356 \ define a value or function, try changing the name to something else!"
1358 "case" ->
1359 D.stack
1360 [ D.reflow $
1361 "It is reserved for writing `case` expressions. Try using a different name?"
1362 , D.toSimpleNote $
1363 "If you are trying to write a `case` expression, it needs to be part of a\
1364 \ definition. So you could write something like this instead:"
1365 , D.vcat $
1366 [ D.indent 0 $ D.fillSep [D.green "getWidth","maybeWidth","="]
1367 , D.indent 2 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
1368 , D.indent 4 $ D.fillSep [D.blue "Just","width","->"]
1369 , D.indent 6 $ D.fillSep ["width","+",D.dullyellow "200"]
1370 , ""
1371 , D.indent 4 $ D.fillSep [D.blue "Nothing","->"]
1372 , D.indent 6 $ D.fillSep [D.dullyellow "400"]
1374 , D.reflow $
1375 "This defines a `getWidth` function that we can use elsewhere in our program."
1378 "if" ->
1379 D.stack
1380 [ D.reflow $
1381 "It is reserved for writing `if` expressions. Try using a different name?"
1382 , D.toSimpleNote $
1383 "If you are trying to write an `if` expression, it needs to be part of a\
1384 \ definition. So you could write something like this instead:"
1385 , D.vcat $
1386 [ D.indent 0 $ D.fillSep [D.green "reviewPowerLevel","powerLevel","="]
1387 , D.indent 2 $ D.fillSep $
1388 [D.cyan "if","powerLevel",">",D.dullyellow "9000"
1389 ,D.cyan "then",D.dullyellow "\"OVER 9000!!!\""
1390 ,D.cyan "else",D.dullyellow "\"not bad\""
1393 , D.reflow $
1394 "This defines a `reviewPowerLevel` function that we can use elsewhere in our program."
1397 _ ->
1398 D.reflow $
1399 "It is a reserved word. Try changing the name to something else?"
1402 _ ->
1403 let
1404 region = toRegion row col
1405 in
1406 Report.Report "SYNTAX PROBLEM" region [] $
1407 Code.toSnippet source region Nothing
1409 D.reflow $
1410 "I was expecting to see a new declaration here:"
1412 D.stack
1413 [ D.reflow $
1414 "I am not sure what is going wrong exactly, but here are a couple valid\
1415 \ declarations for reference:"
1416 , D.vcat
1417 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1418 , D.fillSep [D.green "add","x","y","="]
1419 , D.fillSep [" ","x","+","y"]
1421 , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1422 , D.reflow $
1423 "Note that all declarations start with lower-case letters in Elm. Capitalization\
1424 \ makes a difference, so be conscious of that if you are working from examples!"
1428 DeclSpace space row col ->
1429 toSpaceReport source space row col
1431 Port port_ row col ->
1432 toPortReport source port_ row col
1434 DeclType declType row col ->
1435 toDeclTypeReport source declType row col
1437 DeclDef name declDef row col ->
1438 toDeclDefReport source name declDef row col
1440 DeclFreshLineAfterDocComment row col ->
1441 let
1442 region = toRegion row col
1443 in
1444 Report.Report "EXPECTING DECLARATION" region [] $
1445 Code.toSnippet source region Nothing
1447 D.reflow $
1448 "I just saw a doc comment, but then I got stuck here:"
1450 D.reflow $
1451 "I was expecting to see the corresponding declaration next, starting on a fresh\
1452 \ line with no indentation."
1457-- PORT
1460toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1461toPortReport source port_ startRow startCol =
1462 case port_ of
1463 PortSpace space row col ->
1464 toSpaceReport source space row col
1466 PortName row col ->
1467 case Code.whatIsNext source row col of
1468 Code.Keyword keyword ->
1469 let
1470 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1471 region = toKeywordRegion row col keyword
1472 in
1473 Report.Report "RESERVED WORD" region [] $
1474 Code.toSnippet source surroundings (Just region)
1476 D.reflow $
1477 "I cannot handle ports with names like this:"
1479 D.reflow $
1480 "You are trying to make a port named `" ++ keyword
1481 ++ "` but that is a reserved word. Try using some other name?"
1484 _ ->
1485 let
1486 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1487 region = toRegion row col
1488 in
1489 Report.Report "PORT PROBLEM" region [] $
1490 Code.toSnippet source surroundings (Just region)
1492 D.reflow $
1493 "I just saw the start of a `port` declaration, but then I got stuck here:"
1495 D.stack
1496 [ D.fillSep
1497 ["I","was","expecting","to","see","a","name","like"
1498 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1499 ,"Something","that","starts","with","a","lower-case","letter."
1501 , portNote
1505 PortColon row col ->
1506 let
1507 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1508 region = toRegion row col
1509 in
1510 Report.Report "PORT PROBLEM" region [] $
1511 Code.toSnippet source surroundings (Just region)
1513 D.reflow $
1514 "I just saw the start of a `port` declaration, but then I got stuck here:"
1516 D.stack
1517 [ D.reflow $
1518 "I was expecting to see a colon next. And then a type that tells me\
1519 \ what type of values are going to flow through."
1520 , portNote
1524 PortType tipe row col ->
1525 toTypeReport source TC_Port tipe row col
1527 PortIndentName row col ->
1528 let
1529 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1530 region = toRegion row col
1531 in
1532 Report.Report "UNFINISHED PORT" region [] $
1533 Code.toSnippet source surroundings (Just region)
1535 D.reflow $
1536 "I just saw the start of a `port` declaration, but then I got stuck here:"
1538 D.stack
1539 [ D.fillSep
1540 ["I","was","expecting","to","see","a","name","like"
1541 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1542 ,"Something","that","starts","with","a","lower-case","letter."
1544 , portNote
1548 PortIndentColon row col ->
1549 let
1550 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1551 region = toRegion row col
1552 in
1553 Report.Report "UNFINISHED PORT" region [] $
1554 Code.toSnippet source surroundings (Just region)
1556 D.reflow $
1557 "I just saw the start of a `port` declaration, but then I got stuck here:"
1559 D.stack
1560 [ D.reflow $
1561 "I was expecting to see a colon next. And then a type that tells me\
1562 \ what type of values are going to flow through."
1563 , portNote
1567 PortIndentType row col ->
1568 let
1569 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1570 region = toRegion row col
1571 in
1572 Report.Report "UNFINISHED PORT" region [] $
1573 Code.toSnippet source surroundings (Just region)
1575 D.reflow $
1576 "I just saw the start of a `port` declaration, but then I got stuck here:"
1578 D.stack
1579 [ D.reflow $
1580 "I was expecting to see a type next. Here are examples of outgoing and\
1581 \ incoming ports for reference:"
1582 , D.vcat
1583 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1584 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1586 , D.reflow $
1587 "The first line defines a `send` port so you can send strings out to JavaScript.\
1588 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1589 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1590 \ get receive messages when new WebSocket messages come in or when an entry in\
1591 \ IndexedDB changes for some external reason."
1596portNote :: D.Doc
1597portNote =
1598 D.stack
1599 [ D.toSimpleNote $
1600 "Here are some example `port` declarations for reference:"
1601 , D.vcat
1602 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1603 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1605 , D.reflow $
1606 "The first line defines a `send` port so you can send strings out to JavaScript.\
1607 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1608 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1609 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1610 \ is changed for some external reason."
1615-- DECL TYPE
1618toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1619toDeclTypeReport source declType startRow startCol =
1620 case declType of
1621 DT_Space space row col ->
1622 toSpaceReport source space row col
1624 DT_Name row col ->
1625 let
1626 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1627 region = toRegion row col
1628 in
1629 Report.Report "EXPECTING TYPE NAME" region [] $
1630 Code.toSnippet source surroundings (Just region)
1632 D.reflow $
1633 "I think I am parsing a type declaration, but I got stuck here:"
1635 D.stack
1636 [ D.fillSep $
1637 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1638 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1640 , customTypeNote
1644 DT_Alias typeAlias row col ->
1645 toTypeAliasReport source typeAlias row col
1647 DT_Union customType row col ->
1648 toCustomTypeReport source customType row col
1650 DT_IndentName row col ->
1651 let
1652 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1653 region = toRegion row col
1654 in
1655 Report.Report "EXPECTING TYPE NAME" region [] $
1656 Code.toSnippet source surroundings (Just region)
1658 D.reflow $
1659 "I think I am parsing a type declaration, but I got stuck here:"
1661 D.stack
1662 [ D.fillSep $
1663 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1664 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1666 , customTypeNote
1671toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1672toTypeAliasReport source typeAlias startRow startCol =
1673 case typeAlias of
1674 AliasSpace space row col ->
1675 toSpaceReport source space row col
1677 AliasName row col ->
1678 let
1679 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1680 region = toRegion row col
1681 in
1682 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1683 Code.toSnippet source surroundings (Just region)
1685 D.reflow $
1686 "I am partway through parsing a type alias, but I got stuck here:"
1688 D.stack
1689 [ D.fillSep $
1690 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1691 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1693 , typeAliasNote
1697 AliasEquals row col ->
1698 case Code.whatIsNext source row col of
1699 Code.Keyword keyword ->
1700 let
1701 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1702 region = toKeywordRegion row col keyword
1703 in
1704 Report.Report "RESERVED WORD" region [] $
1705 Code.toSnippet source surroundings (Just region)
1707 D.reflow $
1708 "I ran into a reserved word unexpectedly while parsing this type alias:"
1710 D.stack
1711 [ D.reflow $
1712 "It looks like you are trying use `" ++ keyword
1713 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1714 , typeAliasNote
1718 _ ->
1719 let
1720 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1721 region = toRegion row col
1722 in
1723 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1724 Code.toSnippet source surroundings (Just region)
1726 D.reflow $
1727 "I am partway through parsing a type alias, but I got stuck here:"
1729 D.stack
1730 [ D.reflow $
1731 "I was expecting to see a type variable or an equals sign next."
1732 , typeAliasNote
1736 AliasBody tipe row col ->
1737 toTypeReport source TC_TypeAlias tipe row col
1739 AliasIndentEquals row col ->
1740 let
1741 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1742 region = toRegion row col
1743 in
1744 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1745 Code.toSnippet source surroundings (Just region)
1747 D.reflow $
1748 "I am partway through parsing a type alias, but I got stuck here:"
1750 D.stack
1751 [ D.reflow $
1752 "I was expecting to see a type variable or an equals sign next."
1753 , typeAliasNote
1757 AliasIndentBody row col ->
1758 let
1759 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1760 region = toRegion row col
1761 in
1762 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1763 Code.toSnippet source surroundings (Just region)
1765 D.reflow $
1766 "I am partway through parsing a type alias, but I got stuck here:"
1768 D.stack
1769 [ D.fillSep $
1770 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1771 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1773 , typeAliasNote
1778typeAliasNote :: D.Doc
1779typeAliasNote =
1780 D.stack
1781 [ D.toSimpleNote $
1782 "Here is an example of a valid `type alias` for reference:"
1783 , D.vcat $
1784 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1785 , D.indent 2 $ D.vcat $
1786 ["{ name : String"
1787 ,", age : Int"
1788 ,", height : Float"
1789 ,"}"
1792 , D.reflow $
1793 "This would let us use `Person` as a shorthand for that record type. Using this\
1794 \ shorthand makes type annotations much easier to read, and makes changing code\
1795 \ easier if you decide later that there is more to a person than age and height!"
1799toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1800toCustomTypeReport source customType startRow startCol =
1801 case customType of
1802 CT_Space space row col ->
1803 toSpaceReport source space row col
1805 CT_Name row col ->
1806 let
1807 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1808 region = toRegion row col
1809 in
1810 Report.Report "EXPECTING TYPE NAME" region [] $
1811 Code.toSnippet source surroundings (Just region)
1813 D.reflow $
1814 "I think I am parsing a type declaration, but I got stuck here:"
1816 D.stack
1817 [ D.fillSep $
1818 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1819 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1821 , customTypeNote
1825 CT_Equals row col ->
1826 case Code.whatIsNext source row col of
1827 Code.Keyword keyword ->
1828 let
1829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1830 region = toKeywordRegion row col keyword
1831 in
1832 Report.Report "RESERVED WORD" region [] $
1833 Code.toSnippet source surroundings (Just region)
1835 D.reflow $
1836 "I ran into a reserved word unexpectedly while parsing this custom type:"
1838 D.stack
1839 [ D.reflow $
1840 "It looks like you are trying use `" ++ keyword
1841 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1842 , customTypeNote
1846 _ ->
1847 let
1848 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1849 region = toRegion row col
1850 in
1851 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1852 Code.toSnippet source surroundings (Just region)
1854 D.reflow $
1855 "I am partway through parsing a custom type, but I got stuck here:"
1857 D.stack
1858 [ D.reflow $
1859 "I was expecting to see a type variable or an equals sign next."
1860 , customTypeNote
1864 CT_Bar row col ->
1865 let
1866 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1867 region = toRegion row col
1868 in
1869 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1870 Code.toSnippet source surroundings (Just region)
1872 D.reflow $
1873 "I am partway through parsing a custom type, but I got stuck here:"
1875 D.stack
1876 [ D.reflow $
1877 "I was expecting to see a vertical bar like | next."
1878 , customTypeNote
1882 CT_Variant row col ->
1883 let
1884 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1885 region = toRegion row col
1886 in
1887 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1888 Code.toSnippet source surroundings (Just region)
1890 D.reflow $
1891 "I am partway through parsing a custom type, but I got stuck here:"
1893 D.stack
1894 [ D.fillSep $
1895 ["I","was","expecting","to","see","a","variant","name","next."
1896 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1897 ,"Any","name","that","starts","with","a","capital","letter","really!"
1899 , customTypeNote
1903 CT_VariantArg tipe row col ->
1904 toTypeReport source TC_CustomType tipe row col
1906 CT_IndentEquals row col ->
1907 let
1908 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1909 region = toRegion row col
1910 in
1911 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1912 Code.toSnippet source surroundings (Just region)
1914 D.reflow $
1915 "I am partway through parsing a custom type, but I got stuck here:"
1917 D.stack
1918 [ D.reflow $
1919 "I was expecting to see a type variable or an equals sign next."
1920 , customTypeNote
1924 CT_IndentBar row col ->
1925 let
1926 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1927 region = toRegion row col
1928 in
1929 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1930 Code.toSnippet source surroundings (Just region)
1932 D.reflow $
1933 "I am partway through parsing a custom type, but I got stuck here:"
1935 D.stack
1936 [ D.reflow $
1937 "I was expecting to see a vertical bar like | next."
1938 , customTypeNote
1942 CT_IndentAfterBar row col ->
1943 let
1944 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1945 region = toRegion row col
1946 in
1947 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1948 Code.toSnippet source surroundings (Just region)
1950 D.reflow $
1951 "I am partway through parsing a custom type, but I got stuck here:"
1953 D.stack
1954 [ D.reflow $
1955 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1956 , customTypeNote
1960 CT_IndentAfterEquals row col ->
1961 let
1962 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1963 region = toRegion row col
1964 in
1965 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1966 Code.toSnippet source surroundings (Just region)
1968 D.reflow $
1969 "I am partway through parsing a custom type, but I got stuck here:"
1971 D.stack
1972 [ D.reflow $
1973 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1974 , customTypeNote
1979customTypeNote :: D.Doc
1980customTypeNote =
1981 D.stack
1982 [ D.toSimpleNote $
1983 "Here is an example of a valid `type` declaration for reference:"
1984 , D.vcat $
1985 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1986 , D.indent 2 $ D.fillSep ["=","Failure"]
1987 , D.indent 2 $ D.fillSep ["|","Waiting"]
1988 , D.indent 2 $ D.fillSep ["|","Success","String"]
1990 , D.reflow $
1991 "This defines a new `Status` type with three variants. This could be useful if\
1992 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1993 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1994 \ things go. Notice that the Success variant has some associated data, allowing\
1995 \ us to store a String if the request goes well!"
2000-- DECL DEF
2003toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
2004toDeclDefReport source name declDef startRow startCol =
2005 case declDef of
2006 DeclDefSpace space row col ->
2007 toSpaceReport source space row col
2009 DeclDefEquals row col ->
2010 case Code.whatIsNext source row col of
2011 Code.Keyword keyword ->
2012 let
2013 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2014 region = toKeywordRegion row col keyword
2015 in
2016 Report.Report "RESERVED WORD" region [] $
2017 Code.toSnippet source surroundings (Just region)
2019 D.reflow $
2020 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
2022 D.reflow $
2023 "This is a reserved word! Try using some other name?"
2026 Code.Operator op ->
2027 let
2028 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2029 region = toKeywordRegion row col op
2030 in
2031 Report.Report "UNEXPECTED SYMBOL" region [] $
2032 Code.toSnippet source surroundings (Just region)
2034 D.reflow $
2035 "I was not expecting to see this symbol here:"
2037 D.stack
2038 [ D.reflow $
2039 "I am not sure what is going wrong exactly, so here is a valid\
2040 \ definition (with an optional type annotation) for reference:"
2041 , D.vcat
2042 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2043 , D.fillSep [D.green "add","x","y","="]
2044 , D.fillSep [" ","x","+","y"]
2046 , D.reflow $
2047 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2051 _ ->
2052 let
2053 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2054 region = toRegion row col
2055 in
2056 Report.Report "PROBLEM IN DEFINITION" region [] $
2057 Code.toSnippet source surroundings (Just region)
2059 D.reflow $
2060 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2062 D.stack
2063 [ D.reflow $
2064 "I am not sure what is going wrong exactly, so here is a valid\
2065 \ definition (with an optional type annotation) for reference:"
2066 , D.vcat
2067 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2068 , D.fillSep [D.green "add","x","y","="]
2069 , D.fillSep [" ","x","+","y"]
2071 , D.reflow $
2072 "Try to use that format!"
2076 DeclDefType tipe row col ->
2077 toTypeReport source (TC_Annotation name) tipe row col
2079 DeclDefArg pattern row col ->
2080 toPatternReport source PArg pattern row col
2082 DeclDefBody expr row col ->
2083 toExprReport source (InDef name startRow startCol) expr row col
2085 DeclDefNameRepeat row col ->
2086 let
2087 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2088 region = toRegion row col
2089 in
2090 Report.Report "EXPECTING DEFINITION" region [] $
2091 Code.toSnippet source surroundings (Just region)
2093 D.reflow $
2094 "I just saw the type annotation for `" ++ Name.toChars name
2095 ++ "` so I was expecting to see its definition here:"
2097 D.stack
2098 [ D.reflow $
2099 "Type annotations always appear directly above the relevant\
2100 \ definition, without anything else in between. (Not even doc comments!)"
2101 , declDefNote
2105 DeclDefNameMatch defName row col ->
2106 let
2107 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2108 region = toRegion row col
2109 in
2110 Report.Report "NAME MISMATCH" region [] $
2111 Code.toSnippet source surroundings (Just region)
2113 D.reflow $
2114 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2116 D.stack
2117 [ D.reflow $
2118 "These names do not match! Is there a typo?"
2119 , D.indent 4 $ D.fillSep $
2120 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2124 DeclDefIndentType row col ->
2125 let
2126 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2127 region = toRegion row col
2128 in
2129 Report.Report "UNFINISHED DEFINITION" region [] $
2130 Code.toSnippet source surroundings (Just region)
2132 D.reflow $
2133 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
2135 D.stack
2136 [ D.reflow $
2137 "I just saw a colon, so I am expecting to see a type next."
2138 , declDefNote
2142 DeclDefIndentEquals row col ->
2143 let
2144 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2145 region = toRegion row col
2146 in
2147 Report.Report "UNFINISHED DEFINITION" region [] $
2148 Code.toSnippet source surroundings (Just region)
2150 D.reflow $
2151 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2153 D.stack
2154 [ D.reflow $
2155 "I was expecting to see an argument or an equals sign next."
2156 , declDefNote
2160 DeclDefIndentBody row col ->
2161 let
2162 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2163 region = toRegion row col
2164 in
2165 Report.Report "UNFINISHED DEFINITION" region [] $
2166 Code.toSnippet source surroundings (Just region)
2168 D.reflow $
2169 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2171 D.stack
2172 [ D.reflow $
2173 "I was expecting to see an expression next. What is it equal to?"
2174 , declDefNote
2179declDefNote :: D.Doc
2180declDefNote =
2181 D.stack
2182 [ D.reflow $
2183 "Here is a valid definition (with a type annotation) for reference:"
2184 , D.vcat
2185 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2186 , D.fillSep [D.green "add","x","y","="]
2187 , D.fillSep [" ","x","+","y"]
2189 , D.reflow $
2190 "The top line (called a \"type annotation\") is optional. You can leave it off\
2191 \ if you want. As you get more comfortable with Elm and as your project grows,\
2192 \ it becomes more and more valuable to add them though! They work great as\
2193 \ compiler-verified documentation, and they often improve error messages!"
2198-- CONTEXT
2201data Context
2202 = InNode Node Row Col Context
2203 | InDef Name.Name Row Col
2204 | InDestruct Row Col
2207data Node
2208 = NRecord
2209 | NParens
2210 | NList
2211 | NFunc
2212 | NCond
2213 | NThen
2214 | NElse
2215 | NCase
2216 | NBranch
2217 deriving (Eq)
2220getDefName :: Context -> Maybe Name.Name
2221getDefName context =
2222 case context of
2223 InDestruct _ _ -> Nothing
2224 InDef name _ _ -> Just name
2225 InNode _ _ _ c -> getDefName c
2228isWithin :: Node -> Context -> Bool
2229isWithin desiredNode context =
2230 case context of
2231 InDestruct _ _ -> False
2232 InDef _ _ _ -> False
2233 InNode actualNode _ _ _ -> desiredNode == actualNode
2237-- EXPR REPORTS
2240toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2241toExprReport source context expr startRow startCol =
2242 case expr of
2243 Let let_ row col ->
2244 toLetReport source context let_ row col
2246 Case case_ row col ->
2247 toCaseReport source context case_ row col
2249 If if_ row col ->
2250 toIfReport source context if_ row col
2252 List list row col ->
2253 toListReport source context list row col
2255 Record record row col ->
2256 toRecordReport source context record row col
2258 Tuple tuple row col ->
2259 toTupleReport source context tuple row col
2261 Func func row col ->
2262 toFuncReport source context func row col
2264 Dot row col ->
2265 let region = toRegion row col in
2266 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2267 Code.toSnippet source region Nothing
2269 D.reflow $
2270 "I was expecting to see a record accessor here:"
2272 D.fillSep
2273 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2274 ,"that","accesses","a","value","from","a","record."
2278 Access row col ->
2279 let region = toRegion row col in
2280 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2281 Code.toSnippet source region Nothing
2283 D.reflow $
2284 "I am trying to parse a record accessor here:"
2286 D.stack
2288 D.fillSep
2289 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2290 ,"that","accesses","a","value","from","a","record."
2293 D.toSimpleNote $
2294 "Record field names must start with a lower case letter!"
2298 OperatorRight op row col ->
2299 let region = toRegion row col in
2300 Report.Report "MISSING EXPRESSION" region [] $
2301 Code.toSnippet source region Nothing
2303 D.reflow $
2304 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2306 D.stack
2307 [ D.fillSep $
2308 ["You","can","just","put","anything","for","now,","like"
2309 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2310 ,"Once","there","is","something","there,","I","can","probably"
2311 ,"give","a","more","specific","hint!"
2313 , D.toSimpleNote $
2314 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2315 \ Or if I run into operators in unexpected spots. Point is, there are a\
2316 \ couple ways I can get confused and give sort of weird advice!"
2320 OperatorReserved operator row col ->
2321 toOperatorReport source context operator row col
2323 Start row col ->
2324 let
2325 (contextRow, contextCol, aThing) =
2326 case context of
2327 InDestruct r c -> (r, c, "a definition")
2328 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2329 InNode NRecord r c _ -> (r, c, "a record")
2330 InNode NParens r c _ -> (r, c, "some parentheses")
2331 InNode NList r c _ -> (r, c, "a list")
2332 InNode NFunc r c _ -> (r, c, "an anonymous function")
2333 InNode NCond r c _ -> (r, c, "an `if` expression")
2334 InNode NThen r c _ -> (r, c, "an `if` expression")
2335 InNode NElse r c _ -> (r, c, "an `if` expression")
2336 InNode NCase r c _ -> (r, c, "a `case` expression")
2337 InNode NBranch r c _ -> (r, c, "a `case` expression")
2339 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2340 region = toRegion row col
2341 in
2342 Report.Report "MISSING EXPRESSION" region [] $
2343 Code.toSnippet source surroundings (Just region)
2345 D.reflow $
2346 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2348 D.stack
2349 [ D.fillSep $
2350 ["I","was","expecting","to","see","an","expression","like"
2351 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2352 ,"Once","there","is","something","there,","I","can","probably"
2353 ,"give","a","more","specific","hint!"
2355 , D.toSimpleNote $
2356 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2357 \ Or if I run into operators in unexpected spots. Point is, there are a\
2358 \ couple ways I can get confused and give sort of weird advice!"
2362 Char char row col ->
2363 toCharReport source char row col
2365 String string row col ->
2366 toStringReport source string row col
2368 Number number row col ->
2369 toNumberReport source number row col
2371 Space space row col ->
2372 toSpaceReport source space row col
2374 EndlessShader row col ->
2375 let
2376 region = toWiderRegion row col 6
2377 in
2378 Report.Report "ENDLESS SHADER" region [] $
2379 Code.toSnippet source region Nothing
2381 D.reflow "I cannot find the end of this shader:"
2383 D.reflow "Add a |] somewhere after this to end the shader."
2386 ShaderProblem problem row col ->
2387 let
2388 region = toRegion row col
2389 in
2390 Report.Report "SHADER PROBLEM" region [] $
2391 Code.toSnippet source region Nothing
2393 D.reflow $
2394 "I ran into a problem while parsing this GLSL block."
2396 D.stack
2397 [ D.reflow $
2398 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2399 , D.indent 4 $ D.vcat $
2400 map D.fromChars (filter (/="") (lines problem))
2404 IndentOperatorRight op row col ->
2405 let
2406 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2407 region = toRegion row col
2408 in
2409 Report.Report "MISSING EXPRESSION" region [] $
2410 Code.toSnippet source surroundings (Just region)
2412 D.reflow $
2413 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2415 D.stack
2417 D.fillSep $
2418 ["You","can","just","put","anything","for","now,","like"
2419 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2420 ,"Once","there","is","something","there,","I","can","probably"
2421 ,"give","a","more","specific","hint!"
2424 D.toSimpleNote $
2425 "I may be getting confused by your indentation? The easiest way to make sure\
2426 \ this is not an indentation problem is to put the expression on the right of\
2427 \ the " ++ Name.toChars op ++ " operator on the same line."
2433-- CHAR
2436toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2437toCharReport source char row col =
2438 case char of
2439 CharEndless ->
2440 let
2441 region = toRegion row col
2442 in
2443 Report.Report "MISSING SINGLE QUOTE" region [] $
2444 Code.toSnippet source region Nothing
2446 D.reflow $
2447 "I thought I was parsing a character, but I got to the end of\
2448 \ the line without seeing the closing single quote:"
2450 D.reflow $
2451 "Add a closing single quote here!"
2454 CharEscape escape ->
2455 toEscapeReport source escape row col
2457 CharNotString width ->
2458 let
2459 region = toWiderRegion row col width
2460 in
2461 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2462 Code.toSnippet source region Nothing
2464 "The following string uses single quotes:"
2466 D.stack
2467 [ "Please switch to double quotes instead:"
2468 , D.indent 4 $
2469 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2470 , D.toSimpleNote $
2471 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2472 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2473 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2474 \ individual characters."
2480-- STRING
2483toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2484toStringReport source string row col =
2485 case string of
2486 StringEndless_Single ->
2487 let
2488 region = toRegion row col
2489 in
2490 Report.Report "ENDLESS STRING" region [] $
2491 Code.toSnippet source region Nothing
2493 D.reflow $
2494 "I got to the end of the line without seeing the closing double quote:"
2496 D.stack
2497 [ D.fillSep $
2498 ["Strings","look","like",D.green "\"this\"","with","double"
2499 ,"quotes","on","each","end.","Is","the","closing","double"
2500 ,"quote","missing","in","your","code?"
2502 , D.toSimpleNote $
2503 "For a string that spans multiple lines, you can use the multi-line string\
2504 \ syntax like this:"
2505 , D.vcat
2506 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2507 , mempty
2508 , D.dullyellow "# Multi-line Strings"
2509 , mempty
2510 , D.dullyellow "- start with triple double quotes"
2511 , D.dullyellow "- write whatever you want"
2512 , D.dullyellow "- no need to escape newlines or double quotes"
2513 , D.dullyellow "- end with triple double quotes"
2514 , mempty
2515 , D.dullyellow "\"\"\""
2520 StringEndless_Multi ->
2521 let
2522 region = toWiderRegion row col 3
2523 in
2524 Report.Report "ENDLESS STRING" region [] $
2525 Code.toSnippet source region Nothing
2527 D.reflow $
2528 "I cannot find the end of this multi-line string:"
2530 D.stack
2531 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2532 , D.toSimpleNote $
2533 "Here is a valid multi-line string for reference:"
2534 , D.vcat
2535 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2536 , mempty
2537 , D.dullyellow "# Multi-line Strings"
2538 , mempty
2539 , D.dullyellow "- start with triple double quotes"
2540 , D.dullyellow "- write whatever you want"
2541 , D.dullyellow "- no need to escape newlines or double quotes"
2542 , D.dullyellow "- end with triple double quotes"
2543 , mempty
2544 , D.dullyellow "\"\"\""
2549 StringEscape escape ->
2550 toEscapeReport source escape row col
2554-- ESCAPES
2557toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2558toEscapeReport source escape row col =
2559 case escape of
2560 EscapeUnknown ->
2561 let
2562 region = toWiderRegion row col 2
2563 in
2564 Report.Report "UNKNOWN ESCAPE" region [] $
2565 Code.toSnippet source region Nothing
2567 D.reflow $
2568 "Backslashes always start escaped characters, but I do not recognize this one:"
2570 D.stack
2571 [ D.reflow $
2572 "Valid escape characters include:"
2573 , D.dullyellow $ D.indent 4 $ D.vcat $
2574 [ "\\n"
2575 , "\\r"
2576 , "\\t"
2577 , "\\\""
2578 , "\\\'"
2579 , "\\\\"
2580 , "\\u{003D}"
2582 , D.reflow $
2583 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2584 , D.toSimpleNote $
2585 "The last style lets encode ANY character by its Unicode code\
2586 \ point. That means \\u{0009} and \\t are the same. You can use\
2587 \ that style for anything not covered by the other six escapes!"
2591 BadUnicodeFormat width ->
2592 let
2593 region = toWiderRegion row col width
2594 in
2595 Report.Report "BAD UNICODE ESCAPE" region [] $
2596 Code.toSnippet source region Nothing
2598 D.reflow $
2599 "I ran into an invalid Unicode escape:"
2601 D.stack
2602 [ D.reflow $
2603 "Here are some examples of valid Unicode escapes:"
2604 , D.dullyellow $ D.indent 4 $ D.vcat $
2605 [ "\\u{0041}"
2606 , "\\u{03BB}"
2607 , "\\u{6728}"
2608 , "\\u{1F60A}"
2610 , D.reflow $
2611 "Notice that the code point is always surrounded by curly braces.\
2612 \ Maybe you are missing the opening or closing curly brace?"
2615 BadUnicodeCode width ->
2616 let
2617 region = toWiderRegion row col width
2618 in
2619 Report.Report "BAD UNICODE ESCAPE" region [] $
2620 Code.toSnippet source region Nothing
2622 D.reflow $
2623 "This is not a valid code point:"
2625 D.reflow $
2626 "The valid code points are between 0 and 10FFFF inclusive."
2629 BadUnicodeLength width numDigits badCode ->
2630 let
2631 region = toWiderRegion row col width
2632 in
2633 Report.Report "BAD UNICODE ESCAPE" region [] $
2634 Code.toSnippet source region Nothing $
2635 if numDigits < 4 then
2637 D.reflow $
2638 "Every code point needs at least four digits:"
2640 let
2641 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2642 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2643 in
2644 D.fillSep ["Try",D.green suggestion,"instead?"]
2647 else
2649 D.reflow $
2650 "This code point has too many digits:"
2652 D.fillSep $
2653 ["Valid","code","points","are","between"
2654 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2655 ,"so","try","trimming","any","leading","zeros","until"
2656 ,"you","have","between","four","and","six","digits."
2662-- NUMBERS
2665toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2666toNumberReport source number row col =
2667 let
2668 region = toRegion row col
2669 in
2670 case number of
2671 NumberEnd ->
2672 Report.Report "WEIRD NUMBER" region [] $
2673 Code.toSnippet source region Nothing
2675 D.reflow $
2676 "I thought I was reading a number, but I ran into some weird stuff here:"
2678 D.stack
2679 [ D.reflow $
2680 "I recognize numbers in the following formats:"
2681 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2682 , D.reflow $
2683 "So is there a way to write it like one of those?"
2687 NumberDot int ->
2688 Report.Report "WEIRD NUMBER" region [] $
2689 Code.toSnippet source region Nothing
2691 D.reflow $
2692 "Numbers cannot end with a dot like this:"
2694 D.fillSep
2695 ["Switching","to",D.green (D.fromChars (show int))
2696 ,"or",D.green (D.fromChars (show int ++ ".0"))
2697 ,"will","work","though!"
2701 NumberHexDigit ->
2702 Report.Report "WEIRD HEXIDECIMAL" region [] $
2703 Code.toSnippet source region Nothing
2705 D.reflow $
2706 "I thought I was reading a hexidecimal number until I got here:"
2708 D.stack
2709 [ D.reflow $
2710 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2711 \ only recognize things like this:"
2712 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2716 NumberNoLeadingZero ->
2717 Report.Report "LEADING ZEROS" region [] $
2718 Code.toSnippet source region Nothing
2720 D.reflow $
2721 "I do not accept numbers with leading zeros:"
2723 D.stack
2724 [ D.reflow $
2725 "Just delete the leading zeros and it should work!"
2726 , D.toSimpleNote $
2727 "Some languages let you to specify octal numbers by adding a leading zero.\
2728 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2729 \ that, but others probably want it to equal 111. Either path is going to\
2730 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2731 \ situation."
2737-- OPERATORS
2740toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2741toOperatorReport source context operator row col =
2742 case operator of
2743 BadDot ->
2744 let
2745 region = toRegion row col
2746 in
2747 Report.Report "UNEXPECTED SYMBOL" region [] $
2748 Code.toSnippet source region Nothing
2750 "I was not expecting this dot:"
2752 D.reflow $
2753 "Dots are for record access and decimal points, so\
2754 \ they cannot float around on their own. Maybe\
2755 \ there is some extra whitespace?"
2758 BadPipe ->
2759 let
2760 region = toRegion row col
2761 in
2762 Report.Report "UNEXPECTED SYMBOL" region [] $
2763 Code.toSnippet source region Nothing
2765 D.reflow $
2766 "I was not expecting this vertical bar:"
2768 D.reflow $
2769 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2772 BadArrow ->
2773 let
2774 region = toWiderRegion row col 2
2775 in
2776 Report.Report "UNEXPECTED ARROW" region [] $
2777 Code.toSnippet source region Nothing $
2778 if isWithin NCase context then
2780 D.reflow $
2781 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2783 D.stack
2784 [ D.reflow "Maybe the `of` keyword is missing on a previous line?"
2785 , noteForCaseError
2789 else if isWithin NBranch context then
2791 D.reflow $
2792 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2794 D.stack
2795 [ D.reflow $
2796 "It makes sense to see arrows around here, so I suspect it is something earlier."
2797 , noteForCaseIndentError
2801 else
2803 D.reflow $
2804 "I was not expecting an arrow here:"
2806 D.reflow $
2807 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2808 \ you want > or >= instead?"
2811 BadEquals ->
2812 let
2813 region = toRegion row col
2814 in
2815 Report.Report "UNEXPECTED EQUALS" region [] $
2816 Code.toSnippet source region Nothing
2818 D.reflow $
2819 "I was not expecting to see this equals sign:"
2821 D.stack
2823 D.reflow "Maybe you want == instead? To check if two values are equal?"
2825 D.toSimpleNote $
2826 if isWithin NRecord context then
2827 "Records look like { x = 3, y = 4 } with the equals sign right\
2828 \ after the field name. So maybe you forgot a comma?"
2829 else
2830 case getDefName context of
2831 Nothing ->
2832 "I may be getting confused by your indentation. I need all definitions to be indented\
2833 \ exactly the same amount, so if this is meant to be a new definition, it may have too\
2834 \ many spaces in front of it."
2836 Just name ->
2837 "I may be getting confused by your indentation. I think I am still parsing the `"
2838 ++ Name.toChars name ++ "` definition. Is this supposed to be part of a definition\
2839 \ after that? If so, the problem may be a bit before the equals sign. I need all\
2840 \ definitions to be indented exactly the same amount, so the problem may be that\
2841 \ this new definition has too many spaces in front of it."
2845 BadHasType ->
2846 let
2847 region = toRegion row col
2848 in
2849 Report.Report "UNEXPECTED SYMBOL" region [] $
2850 Code.toSnippet source region Nothing $
2852 D.reflow $
2853 "I was not expecting to run into the \"has type\" symbol here:"
2855 case getDefName context of
2856 Nothing ->
2857 D.fillSep
2858 ["Maybe","you","want",D.green "::","instead?"
2859 ,"To","put","something","on","the","front","of","a","list?"
2862 Just name ->
2863 D.stack
2865 D.fillSep
2866 ["Maybe","you","want",D.green "::","instead?"
2867 ,"To","put","something","on","the","front","of","a","list?"
2869 , D.toSimpleNote $
2870 "The single colon is reserved for type annotations and record types, but I think\
2871 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2873 D.toSimpleNote $
2874 "I may be getting confused by your indentation. Is this supposed to be part of\
2875 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2876 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2877 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2878 \ this new definition is indented a bit too much."
2884-- CASE
2887toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2888toLetReport source context let_ startRow startCol =
2889 case let_ of
2890 LetSpace space row col ->
2891 toSpaceReport source space row col
2893 LetIn row col ->
2894 let
2895 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2896 region = toRegion row col
2897 in
2898 Report.Report "LET PROBLEM" region [] $
2899 Code.toSnippet source surroundings (Just region)
2901 D.reflow $
2902 "I was partway through parsing a `let` expression, but I got stuck here:"
2904 D.stack
2905 [ D.fillSep $
2906 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2907 ,"keyword","next.","Is","there","a","typo?"
2909 , D.toSimpleNote $
2910 "This can also happen if you are trying to define another value within the `let` but\
2911 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2912 \ spaces before it. They should line up exactly!"
2916 LetDefAlignment _ row col ->
2917 let
2918 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2919 region = toRegion row col
2920 in
2921 Report.Report "LET PROBLEM" region [] $
2922 Code.toSnippet source surroundings (Just region)
2924 D.reflow $
2925 "I was partway through parsing a `let` expression, but I got stuck here:"
2927 D.stack
2928 [ D.fillSep $
2929 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2930 ,"keyword","next.","Is","there","a","typo?"
2932 , D.toSimpleNote $
2933 "This can also happen if you are trying to define another value within the `let` but\
2934 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2935 \ spaces before it. They should line up exactly!"
2939 LetDefName row col ->
2940 case Code.whatIsNext source row col of
2941 Code.Keyword keyword ->
2942 let
2943 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2944 region = toKeywordRegion row col keyword
2945 in
2946 Report.Report "RESERVED WORD" region [] $
2947 Code.toSnippet source surroundings (Just region)
2949 D.reflow $
2950 "I was partway through parsing a `let` expression, but I got stuck here:"
2952 D.reflow $
2953 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
2954 \ it is a reserved word! Try using a different name instead."
2957 _ ->
2958 toUnfinishLetReport source row col startRow startCol $
2959 D.reflow $
2960 "I was expecting the name of a definition next."
2962 LetDef name def row col ->
2963 toLetDefReport source name def row col
2965 LetDestruct destruct row col ->
2966 toLetDestructReport source destruct row col
2968 LetBody expr row col ->
2969 toExprReport source context expr row col
2971 LetIndentDef row col ->
2972 toUnfinishLetReport source row col startRow startCol $
2973 D.reflow $
2974 "I was expecting a value to be defined here."
2976 LetIndentIn row col ->
2977 toUnfinishLetReport source row col startRow startCol $
2978 D.fillSep $
2979 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
2980 ,"Or","maybe","more","of","that","expression?"
2983 LetIndentBody row col ->
2984 toUnfinishLetReport source row col startRow startCol $
2985 D.reflow $
2986 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
2989toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2990toUnfinishLetReport source row col startRow startCol message =
2991 let
2992 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2993 region = toRegion row col
2994 in
2995 Report.Report "UNFINISHED LET" region [] $
2996 Code.toSnippet source surroundings (Just region)
2998 D.reflow $
2999 "I was partway through parsing a `let` expression, but I got stuck here:"
3001 D.stack
3002 [ message
3003 , D.toSimpleNote $
3004 "Here is an example with a valid `let` expression for reference:"
3005 , D.vcat $
3006 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
3007 , D.indent 2 $ D.fillSep [D.cyan "let"]
3008 , D.indent 4 $ D.fillSep ["fullName","="]
3009 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
3010 , D.indent 2 $ D.fillSep [D.cyan "in"]
3011 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
3013 , D.reflow $
3014 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
3015 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
3016 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
3017 \ indented a bit more than that. That is important!"
3022toLetDefReport :: Code.Source -> Name.Name -> Def -> Row -> Col -> Report.Report
3023toLetDefReport source name def startRow startCol =
3024 case def of
3025 DefSpace space row col ->
3026 toSpaceReport source space row col
3028 DefType tipe row col ->
3029 toTypeReport source (TC_Annotation name) tipe row col
3031 DefNameRepeat row col ->
3032 let
3033 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3034 region = toRegion row col
3035 in
3036 Report.Report "EXPECTING DEFINITION" region [] $
3037 Code.toSnippet source surroundings (Just region)
3039 D.reflow $
3040 "I just saw the type annotation for `" ++ Name.toChars name
3041 ++ "` so I was expecting to see its definition here:"
3043 D.stack
3044 [ D.reflow $
3045 "Type annotations always appear directly above the relevant\
3046 \ definition, without anything else in between."
3047 , defNote
3051 DefNameMatch defName row col ->
3052 let
3053 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3054 region = toRegion row col
3055 in
3056 Report.Report "NAME MISMATCH" region [] $
3057 Code.toSnippet source surroundings (Just region)
3059 D.reflow $
3060 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
3062 D.stack
3063 [ D.reflow $
3064 "These names do not match! Is there a typo?"
3065 , D.indent 4 $ D.fillSep $
3066 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
3070 DefArg pattern row col ->
3071 toPatternReport source PArg pattern row col
3073 DefEquals row col ->
3074 case Code.whatIsNext source row col of
3075 Code.Keyword keyword ->
3076 let
3077 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3078 region = toKeywordRegion row col keyword
3079 in
3080 Report.Report "RESERVED WORD" region [] $
3081 Code.toSnippet source surroundings (Just region)
3083 D.reflow $
3084 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
3086 D.reflow $
3087 "This is a reserved word! Try using some other name?"
3090 Code.Operator op ->
3091 let
3092 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3093 region = toKeywordRegion row col op
3094 in
3095 Report.Report "UNEXPECTED SYMBOL" region [] $
3096 Code.toSnippet source surroundings (Just region)
3098 D.reflow $
3099 "I was not expecting to see this symbol here:"
3101 D.stack
3102 [ D.reflow $
3103 "I am not sure what is going wrong exactly, so here is a valid\
3104 \ definition (with an optional type annotation) for reference:"
3105 , D.vcat
3106 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3107 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3108 , D.indent 6 $ D.fillSep ["x","+","y"]
3110 , D.reflow $
3111 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3115 _ ->
3116 let
3117 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3118 region = toRegion row col
3119 in
3120 Report.Report "PROBLEM IN DEFINITION" region [] $
3121 Code.toSnippet source surroundings (Just region)
3123 D.reflow $
3124 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3126 D.stack
3127 [ D.reflow $
3128 "I am not sure what is going wrong exactly, so here is a valid\
3129 \ definition (with an optional type annotation) for reference:"
3130 , D.vcat
3131 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3132 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3133 , D.indent 4 $ D.fillSep ["x","+","y"]
3135 , D.reflow $
3136 "Try to use that format!"
3140 DefBody expr row col ->
3141 toExprReport source (InDef name startRow startCol) expr row col
3143 DefIndentEquals row col ->
3144 let
3145 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3146 region = toRegion row col
3147 in
3148 Report.Report "UNFINISHED DEFINITION" region [] $
3149 Code.toSnippet source surroundings (Just region)
3151 D.reflow $
3152 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3154 D.stack
3155 [ D.reflow $
3156 "I was expecting to see an argument or an equals sign next."
3157 , defNote
3161 DefIndentType row col ->
3162 let
3163 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3164 region = toRegion row col
3165 in
3166 Report.Report "UNFINISHED DEFINITION" region [] $
3167 Code.toSnippet source surroundings (Just region)
3169 D.reflow $
3170 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
3172 D.stack
3173 [ D.reflow $
3174 "I just saw a colon, so I am expecting to see a type next."
3175 , defNote
3179 DefIndentBody row col ->
3180 let
3181 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3182 region = toRegion row col
3183 in
3184 Report.Report "UNFINISHED DEFINITION" region [] $
3185 Code.toSnippet source surroundings (Just region)
3187 D.reflow $
3188 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3190 D.stack
3191 [ D.reflow $
3192 "I was expecting to see an expression next. What is it equal to?"
3193 , declDefNote
3197 DefAlignment indent row col ->
3198 let
3199 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3200 region = toRegion row col
3201 offset = indent - col
3202 in
3203 Report.Report "PROBLEM IN DEFINITION" region [] $
3204 Code.toSnippet source surroundings (Just region)
3206 D.reflow $
3207 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3209 D.reflow $
3210 "I just saw a type annotation indented " ++ show indent ++ " spaces, so I was\
3211 \ expecting to see the corresponding definition next with the exact same amount\
3212 \ of indentation. It looks like this line needs "
3213 ++ show offset ++ " more " ++ (if offset == 1 then "space" else "spaces") ++ "?"
3218defNote :: D.Doc
3219defNote =
3220 D.stack
3221 [ D.reflow $
3222 "Here is a valid definition (with a type annotation) for reference:"
3223 , D.vcat
3224 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3225 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3226 , D.indent 6 $ D.fillSep ["x","+","y"]
3228 , D.reflow $
3229 "The top line (called a \"type annotation\") is optional. You can leave it off\
3230 \ if you want. As you get more comfortable with Elm and as your project grows,\
3231 \ it becomes more and more valuable to add them though! They work great as\
3232 \ compiler-verified documentation, and they often improve error messages!"
3236toLetDestructReport :: Code.Source -> Destruct -> Row -> Col -> Report.Report
3237toLetDestructReport source destruct startRow startCol =
3238 case destruct of
3239 DestructSpace space row col ->
3240 toSpaceReport source space row col
3242 DestructPattern pattern row col ->
3243 toPatternReport source PLet pattern row col
3245 DestructEquals row col ->
3246 let
3247 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3248 region = toRegion row col
3249 in
3250 Report.Report "PROBLEM IN DEFINITION" region [] $
3251 Code.toSnippet source surroundings (Just region)
3253 D.reflow $
3254 "I got stuck trying to parse this definition:"
3256 case Code.whatIsNext source row col of
3257 Code.Operator ":" ->
3258 D.stack
3259 [ D.reflow $
3260 "I was expecting to see an equals sign next, followed by an expression\
3261 \ telling me what to compute."
3262 , D.toSimpleNote $
3263 "It looks like you may be trying to write a type annotation? It is not\
3264 \ possible to add type annotations on destructuring definitions like this.\
3265 \ You can assign a name to the overall structure, put a type annotation on\
3266 \ that, and then destructure separately though."
3269 _ ->
3270 D.reflow $
3271 "I was expecting to see an equals sign next, followed by an expression\
3272 \ telling me what to compute."
3275 DestructBody expr row col ->
3276 toExprReport source (InDestruct startRow startCol) expr row col
3278 DestructIndentEquals row col ->
3279 let
3280 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3281 region = toRegion row col
3282 in
3283 Report.Report "UNFINISHED DEFINITION" region [] $
3284 Code.toSnippet source surroundings (Just region)
3286 D.reflow $
3287 "I got stuck trying to parse this definition:"
3289 D.reflow $
3290 "I was expecting to see an equals sign next, followed by an expression\
3291 \ telling me what to compute."
3294 DestructIndentBody row col ->
3295 let
3296 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3297 region = toRegion row col
3298 in
3299 Report.Report "UNFINISHED DEFINITION" region [] $
3300 Code.toSnippet source surroundings (Just region)
3302 D.reflow $
3303 "I got stuck while parsing this definition:"
3305 D.reflow $
3306 "I was expecting to see an expression next. What is it equal to?"
3311-- CASE
3314toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
3315toCaseReport source context case_ startRow startCol =
3316 case case_ of
3317 CaseSpace space row col ->
3318 toSpaceReport source space row col
3320 CaseOf row col ->
3321 toUnfinishCaseReport source row col startRow startCol $
3322 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3324 CasePattern pattern row col ->
3325 toPatternReport source PCase pattern row col
3327 CaseArrow row col ->
3328 case Code.whatIsNext source row col of
3329 Code.Keyword keyword ->
3330 let
3331 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3332 region = toKeywordRegion row col keyword
3333 in
3334 Report.Report "RESERVED WORD" region [] $
3335 Code.toSnippet source surroundings (Just region)
3337 D.reflow $
3338 "I am partway through parsing a `case` expression, but I got stuck here:"
3340 D.reflow $
3341 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
3342 \ patterns, but it is a reserved word. Try using a different name?"
3345 Code.Operator ":" ->
3346 let
3347 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3348 region = toRegion row col
3349 in
3350 Report.Report "UNEXPECTED OPERATOR" region [] $
3351 Code.toSnippet source surroundings (Just region)
3353 D.reflow $
3354 "I am partway through parsing a `case` expression, but I got stuck here:"
3356 D.fillSep $
3357 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
3358 ,"For","pattern","matching","on","lists?"
3362 Code.Operator "=" ->
3363 let
3364 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3365 region = toRegion row col
3366 in
3367 Report.Report "UNEXPECTED OPERATOR" region [] $
3368 Code.toSnippet source surroundings (Just region)
3370 D.reflow $
3371 "I am partway through parsing a `case` expression, but I got stuck here:"
3373 D.fillSep $
3374 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
3378 _ ->
3379 let
3380 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3381 region = toRegion row col
3382 in
3383 Report.Report "MISSING ARROW" region [] $
3384 Code.toSnippet source surroundings (Just region)
3386 D.reflow $
3387 "I am partway through parsing a `case` expression, but I got stuck here:"
3389 D.stack
3390 [ D.reflow "I was expecting to see an arrow next."
3391 , noteForCaseIndentError
3395 CaseExpr expr row col ->
3396 toExprReport source (InNode NCase startRow startCol context) expr row col
3398 CaseBranch expr row col ->
3399 toExprReport source (InNode NBranch startRow startCol context) expr row col
3401 CaseIndentOf row col ->
3402 toUnfinishCaseReport source row col startRow startCol $
3403 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3405 CaseIndentExpr row col ->
3406 toUnfinishCaseReport source row col startRow startCol $
3407 D.reflow "I was expecting to see a expression next."
3409 CaseIndentPattern row col ->
3410 toUnfinishCaseReport source row col startRow startCol $
3411 D.reflow "I was expecting to see a pattern next."
3413 CaseIndentArrow row col ->
3414 toUnfinishCaseReport source row col startRow startCol $
3415 D.fillSep
3416 ["I","just","saw","a","pattern,","so","I","was","expecting"
3417 ,"to","see","a",D.dullyellow "->","next."
3420 CaseIndentBranch row col ->
3421 toUnfinishCaseReport source row col startRow startCol $
3422 D.reflow $
3423 "I was expecting to see an expression next. What should I do when\
3424 \ I run into this particular pattern?"
3426 CasePatternAlignment indent row col ->
3427 toUnfinishCaseReport source row col startRow startCol $
3428 D.reflow $
3429 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
3432toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3433toUnfinishCaseReport source row col startRow startCol message =
3434 let
3435 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3436 region = toRegion row col
3437 in
3438 Report.Report "UNFINISHED CASE" region [] $
3439 Code.toSnippet source surroundings (Just region)
3441 D.reflow $
3442 "I was partway through parsing a `case` expression, but I got stuck here:"
3444 D.stack
3445 [ message
3446 , noteForCaseError
3451noteForCaseError :: D.Doc
3452noteForCaseError =
3453 D.stack
3454 [ D.toSimpleNote $
3455 "Here is an example of a valid `case` expression for reference."
3456 , D.vcat $
3457 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3458 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3459 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3460 , ""
3461 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3462 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3464 , D.reflow $
3465 "Notice the indentation. Each pattern is aligned, and each branch is indented\
3466 \ a bit more than the corresponding pattern. That is important!"
3470noteForCaseIndentError :: D.Doc
3471noteForCaseIndentError =
3472 D.stack
3473 [ D.toSimpleNote $
3474 "Sometimes I get confused by indentation, so try to make your `case` look\
3475 \ something like this:"
3476 , D.vcat $
3477 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3478 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3479 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3480 , ""
3481 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3482 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3484 , D.reflow $
3485 "Notice the indentation! Each pattern is aligned, and each branch is indented\
3486 \ a bit more than the corresponding pattern. That is important!"
3491-- IF
3494toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
3495toIfReport source context if_ startRow startCol =
3496 case if_ of
3497 IfSpace space row col ->
3498 toSpaceReport source space row col
3500 IfThen row col ->
3501 let
3502 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3503 region = toRegion row col
3504 in
3505 Report.Report "UNFINISHED IF" region [] $
3506 Code.toSnippet source surroundings (Just region)
3508 D.reflow $
3509 "I was expecting to see more of this `if` expression, but I got stuck here:"
3511 D.fillSep $
3512 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3516 IfElse row col ->
3517 let
3518 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3519 region = toRegion row col
3520 in
3521 Report.Report "UNFINISHED IF" region [] $
3522 Code.toSnippet source surroundings (Just region)
3524 D.reflow $
3525 "I was expecting to see more of this `if` expression, but I got stuck here:"
3527 D.fillSep $
3528 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
3532 IfElseBranchStart row col ->
3533 let
3534 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3535 region = toRegion row col
3536 in
3537 Report.Report "UNFINISHED IF" region [] $
3538 Code.toSnippet source surroundings (Just region)
3540 D.reflow $
3541 "I just saw the start of an `else` branch, but then I got stuck here:"
3543 D.reflow $
3544 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3547 IfCondition expr row col ->
3548 toExprReport source (InNode NCond startRow startCol context) expr row col
3550 IfThenBranch expr row col ->
3551 toExprReport source (InNode NThen startRow startCol context) expr row col
3553 IfElseBranch expr row col ->
3554 toExprReport source (InNode NElse startRow startCol context) expr row col
3556 IfIndentCondition row col ->
3557 let
3558 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3559 region = toRegion row col
3560 in
3561 Report.Report "UNFINISHED IF" region [] $
3562 Code.toSnippet source surroundings (Just region)
3564 D.reflow $
3565 "I was expecting to see more of this `if` expression, but I got stuck here:"
3567 D.stack
3568 [ D.fillSep $
3569 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3570 ,"that","evaluates","to","True","or","False."
3572 , D.toSimpleNote $
3573 "I can be confused by indentation. Maybe something is not indented enough?"
3577 IfIndentThen row col ->
3578 let
3579 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3580 region = toRegion row col
3581 in
3582 Report.Report "UNFINISHED IF" region [] $
3583 Code.toSnippet source surroundings (Just region)
3585 D.reflow $
3586 "I was expecting to see more of this `if` expression, but I got stuck here:"
3588 D.stack
3589 [ D.fillSep $
3590 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3592 , D.toSimpleNote $
3593 "I can be confused by indentation. Maybe something is not indented enough?"
3597 IfIndentThenBranch row col ->
3598 let
3599 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3600 region = toRegion row col
3601 in
3602 Report.Report "UNFINISHED IF" region [] $
3603 Code.toSnippet source surroundings (Just region)
3605 D.reflow $
3606 "I got stuck after the start of this `then` branch:"
3608 D.stack
3609 [ D.reflow $
3610 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3611 , D.toSimpleNote $
3612 "I can be confused by indentation, so if the `then` branch is already\
3613 \ present, it may not be indented enough for me to recognize it."
3617 IfIndentElseBranch row col ->
3618 let
3619 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3620 region = toRegion row col
3621 in
3622 Report.Report "UNFINISHED IF" region [] $
3623 Code.toSnippet source surroundings (Just region)
3625 D.reflow $
3626 "I got stuck after the start of this `else` branch:"
3628 D.stack
3629 [ D.reflow $
3630 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3631 , D.toSimpleNote $
3632 "I can be confused by indentation, so if the `else` branch is already\
3633 \ present, it may not be indented enough for me to recognize it."
3637 IfIndentElse row col ->
3638 let
3639 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3640 region = toRegion row col
3641 in
3642 Report.Report "UNFINISHED IF" region [] $
3643 Code.toSnippet source surroundings (Just region)
3645 D.reflow $
3646 "I was expecting to see an `else` branch after this:"
3648 D.stack
3649 [ D.reflow $
3650 "I know what to do when the condition is `True`, but not when it is `False`."
3651 , D.fillSep
3652 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3658-- RECORD
3661toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3662toRecordReport source context record startRow startCol =
3663 case record of
3664 RecordOpen row col ->
3665 case Code.whatIsNext source row col of
3666 Code.Keyword keyword ->
3667 let
3668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3669 region = toKeywordRegion row col keyword
3670 in
3671 Report.Report "RESERVED WORD" region [] $
3672 Code.toSnippet source surroundings (Just region)
3674 D.reflow $
3675 "I just started parsing a record, but I got stuck on this field name:"
3677 D.reflow $
3678 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3679 \ that is a reserved word. Try using a different name!"
3682 _ ->
3683 let
3684 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3685 region = toRegion row col
3686 in
3687 Report.Report "UNFINISHED RECORD" region [] $
3688 Code.toSnippet source surroundings (Just region)
3690 D.reflow $
3691 "I just started parsing a record, but I got stuck here:"
3693 D.fillSep
3694 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3695 ,"so","I","was","expecting","to","see","a","field","name","next."
3699 RecordEnd row col ->
3700 let
3701 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3702 region = toRegion row col
3703 in
3704 Report.Report "UNFINISHED RECORD" region [] $
3705 Code.toSnippet source surroundings (Just region)
3707 D.reflow $
3708 "I am partway through parsing a record, but I got stuck here:"
3710 D.stack
3711 [ D.fillSep
3712 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3713 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3715 , D.toSimpleNote $
3716 "When I get stuck like this, it usually means that there is a missing parenthesis\
3717 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3721 RecordField row col ->
3722 case Code.whatIsNext source row col of
3723 Code.Keyword keyword ->
3724 let
3725 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3726 region = toKeywordRegion row col keyword
3727 in
3728 Report.Report "RESERVED WORD" region [] $
3729 Code.toSnippet source surroundings (Just region)
3731 D.reflow $
3732 "I am partway through parsing a record, but I got stuck on this field name:"
3734 D.reflow $
3735 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3736 \ that is a reserved word. Try using a different name!"
3739 _ ->
3740 let
3741 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3742 region = toRegion row col
3743 in
3744 Report.Report "UNFINISHED RECORD" region [] $
3745 Code.toSnippet source surroundings (Just region)
3747 D.reflow $
3748 "I am partway through parsing a record, but I got stuck after that last comma:"
3750 addNoteForRecordError $
3751 D.reflow $
3752 "Trailing commas are not allowed in records, so I was expecting to see another\
3753 \ record field defined next. If you are done defining the record, the fix may\
3754 \ be to delete that last comma?"
3757 RecordEquals row col ->
3758 let
3759 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3760 region = toRegion row col
3761 in
3762 Report.Report "UNFINISHED RECORD" region [] $
3763 Code.toSnippet source surroundings (Just region)
3765 D.reflow $
3766 "I am partway through parsing a record, but I got stuck here:"
3768 addNoteForRecordError $
3769 D.fillSep $
3770 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3771 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3775 RecordExpr expr row col ->
3776 toExprReport source (InNode NRecord startRow startCol context) expr row col
3778 RecordSpace space row col ->
3779 toSpaceReport source space row col
3781 RecordIndentOpen row col ->
3782 let
3783 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3784 region = toRegion row col
3785 in
3786 Report.Report "UNFINISHED RECORD" region [] $
3787 Code.toSnippet source surroundings (Just region)
3789 D.reflow $
3790 "I just saw the opening curly brace of a record, but then I got stuck here:"
3792 addNoteForRecordIndentError $
3793 D.fillSep $
3794 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3795 ,"Try","defining","some","fields","of","your","own?"
3799 RecordIndentEnd row col ->
3800 let
3801 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3802 region = toRegion row col
3803 in
3804 Report.Report "UNFINISHED RECORD" region [] $
3805 Code.toSnippet source surroundings (Just region)
3807 D.reflow $
3808 "I was expecting to see a closing curly brace next:"
3810 addNoteForRecordIndentError $
3811 D.fillSep $
3812 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3816 RecordIndentField row col ->
3817 let
3818 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3819 region = toRegion row col
3820 in
3821 Report.Report "UNFINISHED RECORD" region [] $
3822 Code.toSnippet source surroundings (Just region)
3824 D.reflow $
3825 "I am partway through parsing a record, but I got stuck after that last comma:"
3827 addNoteForRecordError $
3828 D.reflow $
3829 "Trailing commas are not allowed in records, so the fix may be to\
3830 \ delete that last comma? Or maybe you were in the middle of defining\
3831 \ an additional field?"
3834 RecordIndentEquals row col ->
3835 let
3836 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3837 region = toRegion row col
3838 in
3839 Report.Report "UNFINISHED RECORD" region [] $
3840 Code.toSnippet source surroundings (Just region)
3842 D.reflow $
3843 "I am partway through parsing a record. I just saw a record\
3844 \ field, so I was expecting to see an equals sign next:"
3846 addNoteForRecordIndentError $
3847 D.fillSep $
3848 ["Try","putting","an",D.green "=","followed","by","an","expression?"
3852 RecordIndentExpr row col ->
3853 let
3854 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3855 region = toRegion row col
3856 in
3857 Report.Report "UNFINISHED RECORD" region [] $
3858 Code.toSnippet source surroundings (Just region)
3860 D.reflow $
3861 "I am partway through parsing a record, and I was expecting to run into an expression next:"
3863 addNoteForRecordIndentError $
3864 D.fillSep $
3865 ["Try","putting","something","like"
3866 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3871addNoteForRecordError :: D.Doc -> D.Doc
3872addNoteForRecordError normalRecommendation =
3873 D.stack $
3874 normalRecommendation
3876 [ D.toSimpleNote
3877 "If you are trying to define a record across multiple lines, I recommend using this format:"
3878 , D.indent 4 $ D.vcat $
3879 [ "{ name = \"Alice\""
3880 , ", age = 42"
3881 , ", height = 1.75"
3882 , "}"
3884 , D.reflow $
3885 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3886 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3887 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3891addNoteForRecordIndentError :: D.Doc -> D.Doc
3892addNoteForRecordIndentError normalRecommendation =
3893 D.stack $
3894 normalRecommendation
3896 [ D.toSimpleNote
3897 "I may be confused by indentation. For example, if you are trying to define\
3898 \ a record across multiple lines, I recommend using this format:"
3899 , D.indent 4 $ D.vcat $
3900 [ "{ name = \"Alice\""
3901 , ", age = 42"
3902 , ", height = 1.75"
3903 , "}"
3905 , D.reflow $
3906 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3907 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3908 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3913-- TUPLE
3916toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
3917toTupleReport source context tuple startRow startCol =
3918 case tuple of
3919 TupleExpr expr row col ->
3920 toExprReport source (InNode NParens startRow startCol context) expr row col
3922 TupleSpace space row col ->
3923 toSpaceReport source space row col
3925 TupleEnd row col ->
3926 let
3927 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3928 region = toRegion row col
3929 in
3930 Report.Report "UNFINISHED PARENTHESES" region [] $
3931 Code.toSnippet source surroundings (Just region)
3933 D.reflow $
3934 "I was expecting to see a closing parentheses next, but I got stuck here:"
3936 D.stack
3937 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3938 , D.toSimpleNote $
3939 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
3940 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
3941 \ or missing brackets) that is confusing me."
3945 TupleOperatorClose row col ->
3946 let
3947 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3948 region = toRegion row col
3949 in
3950 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
3951 Code.toSnippet source surroundings (Just region)
3953 D.reflow "I was expecting a closing parenthesis here:"
3955 D.stack
3956 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3957 , D.toSimpleNote $
3958 "I think I am parsing an operator function right now, so I am expecting to see\
3959 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
3960 \ no extra spaces."
3964 TupleOperatorReserved operator row col ->
3965 let
3966 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3967 region = toRegion row col
3968 in
3969 Report.Report "UNEXPECTED SYMBOL" region [] $
3970 Code.toSnippet source surroundings (Just region)
3972 D.reflow $
3973 "I ran into an unexpected symbol here:"
3975 D.fillSep $
3976 case operator of
3977 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
3978 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
3979 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
3980 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
3981 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
3984 TupleIndentExpr1 row col ->
3985 let
3986 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3987 region = toRegion row col
3988 in
3989 Report.Report "UNFINISHED PARENTHESES" region [] $
3990 Code.toSnippet source surroundings (Just region)
3992 D.reflow $
3993 "I just saw an open parenthesis, so I was expecting to see an expression next."
3995 D.stack
3996 [ D.fillSep $
3997 ["Something","like",D.dullyellow "(4 + 5)","or"
3998 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
3999 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
4001 , D.toSimpleNote $
4002 "I can get confused by indentation in cases like this, so\
4003 \ maybe you have an expression but it is not indented enough?"
4007 TupleIndentExprN row col ->
4008 let
4009 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4010 region = toRegion row col
4011 in
4012 Report.Report "UNFINISHED TUPLE" region [] $
4013 Code.toSnippet source surroundings (Just region)
4015 D.reflow $
4016 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see an expression next."
4018 D.stack
4019 [ D.fillSep $
4020 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
4021 ,D.dullyellow "(\"Tom\",42)" <> ","
4022 ,"so","I","think","there","is","an","expression","missing","here?"
4024 , D.toSimpleNote $
4025 "I can get confused by indentation in cases like this, so\
4026 \ maybe you have an expression but it is not indented enough?"
4030 TupleIndentEnd row col ->
4031 let
4032 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4033 region = toRegion row col
4034 in
4035 Report.Report "UNFINISHED PARENTHESES" region [] $
4036 Code.toSnippet source surroundings (Just region)
4038 D.reflow $
4039 "I was expecting to see a closing parenthesis next:"
4041 D.stack
4042 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4043 , D.toSimpleNote $
4044 "I can get confused by indentation in cases like this, so\
4045 \ maybe you have a closing parenthesis but it is not indented enough?"
4050toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
4051toListReport source context list startRow startCol =
4052 case list of
4053 ListSpace space row col ->
4054 toSpaceReport source space row col
4056 ListOpen row col ->
4057 let
4058 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4059 region = toRegion row col
4060 in
4061 Report.Report "UNFINISHED LIST" region [] $
4062 Code.toSnippet source surroundings (Just region)
4064 D.reflow $
4065 "I am partway through parsing a list, but I got stuck here:"
4067 D.stack
4068 [ D.fillSep
4069 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4070 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4072 , D.toSimpleNote $
4073 "When I get stuck like this, it usually means that there is a missing parenthesis\
4074 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4078 ListExpr expr row col ->
4079 case expr of
4080 Start r c ->
4081 let
4082 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
4083 region = toRegion r c
4084 in
4085 Report.Report "UNFINISHED LIST" region [] $
4086 Code.toSnippet source surroundings (Just region)
4088 D.reflow $
4089 "I was expecting to see another list entry after that last comma:"
4091 D.stack
4092 [ D.reflow $
4093 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4094 , D.toSimpleNote
4095 "I recommend using the following format for lists that span multiple lines:"
4096 , D.indent 4 $ D.vcat $
4097 [ "[ \"Alice\""
4098 , ", \"Bob\""
4099 , ", \"Chuck\""
4100 , "]"
4102 , D.reflow $
4103 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4104 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4105 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4109 _ ->
4110 toExprReport source (InNode NList startRow startCol context) expr row col
4112 ListEnd row col ->
4113 let
4114 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4115 region = toRegion row col
4116 in
4117 Report.Report "UNFINISHED LIST" region [] $
4118 Code.toSnippet source surroundings (Just region)
4120 D.reflow $
4121 "I am partway through parsing a list, but I got stuck here:"
4123 D.stack
4124 [ D.fillSep
4125 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4126 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4128 , D.toSimpleNote $
4129 "When I get stuck like this, it usually means that there is a missing parenthesis\
4130 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4134 ListIndentOpen row col ->
4135 let
4136 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4137 region = toRegion row col
4138 in
4139 Report.Report "UNFINISHED LIST" region [] $
4140 Code.toSnippet source surroundings (Just region)
4142 D.reflow $
4143 "I cannot find the end of this list:"
4145 D.stack
4146 [ D.fillSep $
4147 ["You","could","change","it","to","something","like"
4148 ,D.dullyellow "[3,4,5]"
4149 ,"or","even","just"
4150 ,D.dullyellow "[]" <> "."
4151 ,"Anything","where","there","is","an","open","and","close","square","brace,"
4152 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
4154 , D.toSimpleNote
4155 "I may be confused by indentation. For example, if you are trying to define\
4156 \ a list across multiple lines, I recommend using this format:"
4157 , D.indent 4 $ D.vcat $
4158 [ "[ \"Alice\""
4159 , ", \"Bob\""
4160 , ", \"Chuck\""
4161 , "]"
4163 , D.reflow $
4164 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4165 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4166 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4170 ListIndentEnd row col ->
4171 let
4172 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4173 region = toRegion row col
4174 in
4175 Report.Report "UNFINISHED LIST" region [] $
4176 Code.toSnippet source surroundings (Just region)
4178 D.reflow $
4179 "I cannot find the end of this list:"
4181 D.stack
4182 [ D.fillSep $
4183 ["You","can","just","add","a","closing",D.dullyellow "]"
4184 ,"right","here,","and","I","will","be","all","set!"
4186 , D.toSimpleNote
4187 "I may be confused by indentation. For example, if you are trying to define\
4188 \ a list across multiple lines, I recommend using this format:"
4189 , D.indent 4 $ D.vcat $
4190 [ "[ \"Alice\""
4191 , ", \"Bob\""
4192 , ", \"Chuck\""
4193 , "]"
4195 , D.reflow $
4196 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4197 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4198 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4202 ListIndentExpr row col ->
4203 let
4204 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4205 region = toRegion row col
4206 in
4207 Report.Report "UNFINISHED LIST" region [] $
4208 Code.toSnippet source surroundings (Just region)
4210 D.reflow $
4211 "I was expecting to see another list entry after this comma:"
4213 D.stack
4214 [ D.reflow $
4215 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4216 , D.toSimpleNote
4217 "I recommend using the following format for lists that span multiple lines:"
4218 , D.indent 4 $ D.vcat $
4219 [ "[ \"Alice\""
4220 , ", \"Bob\""
4221 , ", \"Chuck\""
4222 , "]"
4224 , D.reflow $
4225 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4226 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4227 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4232toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
4233toFuncReport source context func startRow startCol =
4234 case func of
4235 FuncSpace space row col ->
4236 toSpaceReport source space row col
4238 FuncArg pattern row col ->
4239 toPatternReport source PArg pattern row col
4241 FuncBody expr row col ->
4242 toExprReport source (InNode NFunc startRow startCol context) expr row col
4244 FuncArrow row col ->
4245 case Code.whatIsNext source row col of
4246 Code.Keyword keyword ->
4247 let
4248 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4249 region = toKeywordRegion row col keyword
4250 in
4251 Report.Report "RESERVED WORD" region [] $
4252 Code.toSnippet source surroundings (Just region)
4254 D.reflow $
4255 "I was parsing an anonymous function, but I got stuck here:"
4257 D.reflow $
4258 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
4259 \ it is a reserved word in this language. Try using a different argument name!"
4262 _ ->
4263 let
4264 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4265 region = toRegion row col
4266 in
4267 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4268 Code.toSnippet source surroundings (Just region)
4270 D.reflow $
4271 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4273 D.fillSep $
4274 ["The","syntax","for","anonymous","functions","is"
4275 ,D.dullyellow "(\\x -> x + 1)"
4276 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4280 FuncIndentArg row col ->
4281 let
4282 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4283 region = toRegion row col
4284 in
4285 Report.Report "MISSING ARGUMENT" region [] $
4286 Code.toSnippet source surroundings (Just region)
4288 D.reflow $
4289 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
4291 D.stack
4292 [ D.fillSep
4293 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
4294 ,"Anything","that","starts","with","a","lower","case","letter!"
4296 , D.toSimpleNote $
4297 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
4298 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
4299 \ like a better idea at the time!"
4303 FuncIndentArrow row col ->
4304 let
4305 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4306 region = toRegion row col
4307 in
4308 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4309 Code.toSnippet source surroundings (Just region)
4311 D.reflow $
4312 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4314 D.stack
4315 [ D.fillSep $
4316 ["The","syntax","for","anonymous","functions","is"
4317 ,D.dullyellow "(\\x -> x + 1)"
4318 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4320 , D.toSimpleNote $
4321 "It is possible that I am confused about indetation! I generally recommend\
4322 \ switching to named functions if the definition cannot fit inline nicely, so\
4323 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4324 \ the whole thing out into a named function. Things tend to be clearer that way!"
4328 FuncIndentBody row col ->
4329 let
4330 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4331 region = toRegion row col
4332 in
4333 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4334 Code.toSnippet source surroundings (Just region)
4336 D.reflow $
4337 "I was expecting to see the body of your anonymous function next:"
4339 D.stack
4340 [ D.fillSep $
4341 ["The","syntax","for","anonymous","functions","is"
4342 ,D.dullyellow "(\\x -> x + 1)"
4343 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
4345 , D.toSimpleNote $
4346 "It is possible that I am confused about indetation! I generally recommend\
4347 \ switching to named functions if the definition cannot fit inline nicely, so\
4348 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4349 \ the whole thing out into a named function. Things tend to be clearer that way!"
4355-- PATTERN
4358data PContext
4359 = PCase
4360 | PArg
4361 | PLet
4364toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
4365toPatternReport source context pattern startRow startCol =
4366 case pattern of
4367 PRecord record row col ->
4368 toPRecordReport source record row col
4370 PTuple tuple row col ->
4371 toPTupleReport source context tuple row col
4373 PList list row col ->
4374 toPListReport source context list row col
4376 PStart row col ->
4377 case Code.whatIsNext source row col of
4378 Code.Keyword keyword ->
4379 let
4380 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4381 region = toKeywordRegion row col keyword
4382 inThisThing =
4383 case context of
4384 PArg -> "as an argument"
4385 PCase -> "in this pattern"
4386 PLet -> "in this pattern"
4387 in
4388 Report.Report "RESERVED WORD" region [] $
4389 Code.toSnippet source surroundings (Just region)
4391 D.reflow $
4392 "It looks like you are trying to use `" ++ keyword ++ "` " ++ inThisThing ++ ":"
4394 D.reflow $
4395 "This is a reserved word! Try using some other name?"
4398 Code.Operator "-" ->
4399 let
4400 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4401 region = toRegion row col
4402 in
4403 Report.Report "UNEXPECTED SYMBOL" region [] $
4404 Code.toSnippet source surroundings (Just region)
4406 D.reflow $
4407 "I ran into a minus sign unexpectedly in this pattern:"
4409 D.reflow $
4410 "It is not possible to pattern match on negative numbers at this\
4411 \ time. Try using an `if` expression for that sort of thing for now."
4414 _ ->
4415 let
4416 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4417 region = toRegion row col
4418 in
4419 Report.Report "PROBLEM IN PATTERN" region [] $
4420 Code.toSnippet source surroundings (Just region)
4422 D.reflow $
4423 "I wanted to parse a pattern next, but I got stuck here:"
4425 D.fillSep $
4426 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4427 ,"I","just","know","that","I","want","a","pattern","next."
4428 ,"Something","as","simple","as"
4429 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4430 ,"would","work!"
4434 PChar char row col ->
4435 toCharReport source char row col
4437 PString string row col ->
4438 toStringReport source string row col
4440 PNumber number row col ->
4441 toNumberReport source number row col
4443 PFloat width row col ->
4444 let
4445 region = toWiderRegion row col width
4446 in
4447 Report.Report "UNEXPECTED PATTERN" region [] $
4448 Code.toSnippet source region Nothing
4450 D.reflow $
4451 "I cannot pattern match with floating point numbers:"
4453 D.fillSep $
4454 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
4455 ,"to","check","that","they","are","nearby","with","some","sort","of"
4456 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
4460 PAlias row col ->
4461 let
4462 region = toRegion row col
4463 in
4464 Report.Report "UNFINISHED PATTERN" region [] $
4465 Code.toSnippet source region Nothing $
4467 D.reflow $
4468 "I was expecting to see a variable name after the `as` keyword:"
4470 D.stack
4471 [ D.fillSep $
4472 ["The","`as`","keyword","lets","you","write","patterns","like"
4473 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4474 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4475 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4476 ,"thing","with",D.dullyellow "point" <> "."
4478 , D.reflow $
4479 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4480 \ people just want to use `as` as a variable name though. Try using a different name\
4481 \ in that case!"
4485 PWildcardNotVar name width row col ->
4486 let
4487 region = toWiderRegion row col (fromIntegral width)
4488 examples =
4489 case dropWhile (=='_') (Name.toChars name) of
4490 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
4491 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
4492 in
4493 Report.Report "UNEXPECTED NAME" region [] $
4494 Code.toSnippet source region Nothing $
4496 D.reflow $
4497 "Variable names cannot start with underscores like this:"
4499 D.fillSep $
4500 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
4501 ,"ignore","the","value,","or","you","can","have","a","name","like"
4502 ] ++ examples ++ ["to","use","the","matched","value." ]
4505 PSpace space row col ->
4506 toSpaceReport source space row col
4508 PIndentStart row col ->
4509 let
4510 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4511 region = toRegion row col
4512 in
4513 Report.Report "UNFINISHED PATTERN" region [] $
4514 Code.toSnippet source surroundings (Just region)
4516 D.reflow $
4517 "I wanted to parse a pattern next, but I got stuck here:"
4519 D.stack
4520 [ D.fillSep $
4521 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4522 ,"I","just","know","that","I","want","a","pattern","next."
4523 ,"Something","as","simple","as"
4524 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4525 ,"would","work!"
4527 , D.toSimpleNote $
4528 "I can get confused by indentation. If you think there is a pattern next, maybe\
4529 \ it needs to be indented a bit more?"
4533 PIndentAlias row col ->
4534 let
4535 region = toRegion row col
4536 in
4537 Report.Report "UNFINISHED PATTERN" region [] $
4538 Code.toSnippet source region Nothing $
4540 D.reflow $
4541 "I was expecting to see a variable name after the `as` keyword:"
4543 D.stack
4544 [ D.fillSep $
4545 ["The","`as`","keyword","lets","you","write","patterns","like"
4546 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4547 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4548 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4549 ,"thing","with",D.dullyellow "point."
4551 , D.reflow $
4552 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4553 \ people just want to use `as` as a variable name though. Try using a different name\
4554 \ in that case!"
4559toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
4560toPRecordReport source record startRow startCol =
4561 case record of
4562 PRecordOpen row col ->
4563 toUnfinishRecordPatternReport source row col startRow startCol $
4564 D.reflow "I was expecting to see a field name next."
4566 PRecordEnd row col ->
4567 toUnfinishRecordPatternReport source row col startRow startCol $
4568 D.fillSep
4569 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4570 ,"Try","adding","a",D.dullyellow "}","here?"
4573 PRecordField row col ->
4574 case Code.whatIsNext source row col of
4575 Code.Keyword keyword ->
4576 let
4577 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4578 region = toKeywordRegion row col keyword
4579 in
4580 Report.Report "RESERVED WORD" region [] $
4581 Code.toSnippet source surroundings (Just region)
4583 D.reflow $
4584 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
4586 D.reflow $
4587 "This is a reserved word, not available for variable names. Try another name!"
4590 _ ->
4591 toUnfinishRecordPatternReport source row col startRow startCol $
4592 D.reflow "I was expecting to see a field name next."
4594 PRecordSpace space row col ->
4595 toSpaceReport source space row col
4597 PRecordIndentOpen row col ->
4598 toUnfinishRecordPatternReport source row col startRow startCol $
4599 D.reflow "I was expecting to see a field name next."
4601 PRecordIndentEnd row col ->
4602 toUnfinishRecordPatternReport source row col startRow startCol $
4603 D.fillSep
4604 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4605 ,"Try","adding","a",D.dullyellow "}","here?"
4608 PRecordIndentField row col ->
4609 toUnfinishRecordPatternReport source row col startRow startCol $
4610 D.reflow "I was expecting to see a field name next."
4613toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4614toUnfinishRecordPatternReport source row col startRow startCol message =
4615 let
4616 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4617 region = toRegion row col
4618 in
4619 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4620 Code.toSnippet source surroundings (Just region)
4622 D.reflow $
4623 "I was partway through parsing a record pattern, but I got stuck here:"
4625 D.stack
4626 [ message
4627 , D.toFancyHint $
4628 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4629 ,"where","you","list","the","field","names","you","want","to","access."
4636toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4637toPTupleReport source context tuple startRow startCol =
4638 case tuple of
4639 PTupleOpen row col ->
4640 case Code.whatIsNext source row col of
4641 Code.Keyword keyword ->
4642 let
4643 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4644 region = toKeywordRegion row col keyword
4645 in
4646 Report.Report "RESERVED WORD" region [] $
4647 Code.toSnippet source surroundings (Just region)
4649 D.reflow $
4650 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4652 D.reflow $
4653 "This is a reserved word! Try using some other name?"
4656 _ ->
4657 let
4658 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4659 region = toRegion row col
4660 in
4661 Report.Report "UNFINISHED PARENTHESES" region [] $
4662 Code.toSnippet source surroundings (Just region)
4664 D.reflow $
4665 "I just saw an open parenthesis, but I got stuck here:"
4667 D.fillSep
4668 ["I","was","expecting","to","see","a","pattern","next."
4669 ,"Maybe","it","will","end","up","being","something"
4670 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4674 PTupleEnd row col ->
4675 case Code.whatIsNext source row col of
4676 Code.Keyword keyword ->
4677 let
4678 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4679 region = toKeywordRegion row col keyword
4680 in
4681 Report.Report "RESERVED WORD" region [] $
4682 Code.toSnippet source surroundings (Just region) $
4684 D.reflow $
4685 "I ran into a reserved word in this pattern:"
4687 D.reflow $
4688 "The `" ++ keyword ++ "` keyword is reserved. Try using a different name instead!"
4691 Code.Operator op ->
4692 let
4693 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4694 region = toKeywordRegion row col op
4695 in
4696 Report.Report "UNEXPECTED SYMBOL" region [] $
4697 Code.toSnippet source surroundings (Just region) $
4699 D.reflow $
4700 "I ran into the " ++ op ++ " symbol unexpectedly in this pattern:"
4702 D.reflow $
4703 "Only the :: symbol that works in patterns. It is useful if you\
4704 \ are pattern matching on lists, trying to get the first element\
4705 \ off the front. Did you want that instead?"
4708 Code.Close term bracket ->
4709 let
4710 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4711 region = toRegion row col
4712 in
4713 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
4714 Code.toSnippet source surroundings (Just region) $
4716 D.reflow $
4717 "I ran into a an unexpected " ++ term ++ " in this pattern:"
4719 D.reflow $
4720 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
4723 _ ->
4724 let
4725 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4726 region = toRegion row col
4727 in
4728 Report.Report "UNFINISHED PARENTHESES" region [] $
4729 Code.toSnippet source surroundings (Just region) $
4731 D.reflow $
4732 "I was partway through parsing a pattern, but I got stuck here:"
4734 D.fillSep
4735 ["I","was","expecting","a","closing","parenthesis","next,","so"
4736 ,"try","adding","a",D.dullyellow ")","to","see","if","that","helps?"
4740 PTupleExpr pattern row col ->
4741 toPatternReport source context pattern row col
4743 PTupleSpace space row col ->
4744 toSpaceReport source space row col
4746 PTupleIndentEnd row col ->
4747 let
4748 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4749 region = toRegion row col
4750 in
4751 Report.Report "UNFINISHED PARENTHESES" region [] $
4752 Code.toSnippet source surroundings (Just region) $
4754 D.reflow $
4755 "I was expecting a closing parenthesis next:"
4757 D.stack
4758 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4759 , D.toSimpleNote $
4760 "I can get confused by indentation in cases like this, so\
4761 \ maybe you have a closing parenthesis but it is not indented enough?"
4765 PTupleIndentExpr1 row col ->
4766 let
4767 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4768 region = toRegion row col
4769 in
4770 Report.Report "UNFINISHED PARENTHESES" region [] $
4771 Code.toSnippet source surroundings (Just region) $
4773 D.reflow $
4774 "I just saw an open parenthesis, but then I got stuck here:"
4776 D.fillSep
4777 ["I","was","expecting","to","see","a","pattern","next."
4778 ,"Maybe","it","will","end","up","being","something"
4779 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4783 PTupleIndentExprN row col ->
4784 let
4785 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4786 region = toRegion row col
4787 in
4788 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4789 Code.toSnippet source surroundings (Just region) $
4791 D.reflow $
4792 "I am partway through parsing a tuple pattern, but I got stuck here:"
4794 D.stack
4795 [ D.fillSep
4796 ["I","was","expecting","to","see","a","pattern","next."
4797 ,"I","am","expecting","the","final","result","to","be","something"
4798 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
4800 , D.toSimpleNote $
4801 "I can get confused by indentation in cases like this, so the problem\
4802 \ may be that the next part is not indented enough?"
4807toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
4808toPListReport source context list startRow startCol =
4809 case list of
4810 PListOpen row col ->
4811 case Code.whatIsNext source row col of
4812 Code.Keyword keyword ->
4813 let
4814 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4815 region = toKeywordRegion row col keyword
4816 in
4817 Report.Report "RESERVED WORD" region [] $
4818 Code.toSnippet source surroundings (Just region)
4820 D.reflow $
4821 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
4823 D.reflow $
4824 "This is a reserved word though! Try using some other name?"
4827 _ ->
4828 let
4829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4830 region = toRegion row col
4831 in
4832 Report.Report "UNFINISHED LIST PATTERN" region [] $
4833 Code.toSnippet source surroundings (Just region) $
4835 D.reflow $
4836 "I just saw an open square bracket, but then I got stuck here:"
4838 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4841 PListEnd row col ->
4842 let
4843 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4844 region = toRegion row col
4845 in
4846 Report.Report "UNFINISHED LIST PATTERN" region [] $
4847 Code.toSnippet source surroundings (Just region) $
4849 D.reflow $
4850 "I was expecting a closing square bracket to end this list pattern:"
4852 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4855 PListExpr pattern row col ->
4856 toPatternReport source context pattern row col
4858 PListSpace space row col ->
4859 toSpaceReport source space row col
4861 PListIndentOpen row col ->
4862 let
4863 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4864 region = toRegion row col
4865 in
4866 Report.Report "UNFINISHED LIST PATTERN" region [] $
4867 Code.toSnippet source surroundings (Just region) $
4869 D.reflow $
4870 "I just saw an open square bracket, but then I got stuck here:"
4872 D.stack
4873 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4874 , D.toSimpleNote $
4875 "I can get confused by indentation in cases like this, so\
4876 \ maybe there is something next, but it is not indented enough?"
4880 PListIndentEnd row col ->
4881 let
4882 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4883 region = toRegion row col
4884 in
4885 Report.Report "UNFINISHED LIST PATTERN" region [] $
4886 Code.toSnippet source surroundings (Just region) $
4888 D.reflow $
4889 "I was expecting a closing square bracket to end this list pattern:"
4891 D.stack
4892 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4893 , D.toSimpleNote $
4894 "I can get confused by indentation in cases like this, so\
4895 \ maybe you have a closing square bracket but it is not indented enough?"
4899 PListIndentExpr row col ->
4900 let
4901 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4902 region = toRegion row col
4903 in
4904 Report.Report "UNFINISHED LIST PATTERN" region [] $
4905 Code.toSnippet source surroundings (Just region) $
4907 D.reflow $
4908 "I am partway through parsing a list pattern, but I got stuck here:"
4910 D.stack
4911 [ D.reflow $
4912 "I was expecting to see another pattern next. Maybe a variable name."
4913 , D.toSimpleNote $
4914 "I can get confused by indentation in cases like this, so\
4915 \ maybe there is more to this pattern but it is not indented enough?"
4921-- TYPES
4924data TContext
4925 = TC_Annotation Name.Name
4926 | TC_CustomType
4927 | TC_TypeAlias
4928 | TC_Port
4931toTypeReport :: Code.Source -> TContext -> Type -> Row -> Col -> Report.Report
4932toTypeReport source context tipe startRow startCol =
4933 case tipe of
4934 TRecord record row col ->
4935 toTRecordReport source context record row col
4937 TTuple tuple row col ->
4938 toTTupleReport source context tuple row col
4940 TStart row col ->
4941 case Code.whatIsNext source row col of
4942 Code.Keyword keyword ->
4943 let
4944 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4945 region = toKeywordRegion row col keyword
4946 in
4947 Report.Report "RESERVED WORD" region [] $
4948 Code.toSnippet source surroundings (Just region)
4950 D.reflow $
4951 "I was expecting to see a type next, but I got stuck on this reserved word:"
4953 D.reflow $
4954 "It looks like you are trying to use `" ++ keyword ++ "` as a type variable, but \
4955 \ it is a reserved word. Try using a different name!"
4958 _ ->
4959 let
4960 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4961 region = toRegion row col
4963 thing =
4964 case context of
4965 TC_Annotation _ -> "type annotation"
4966 TC_CustomType -> "custom type"
4967 TC_TypeAlias -> "type alias"
4968 TC_Port -> "port"
4970 something =
4971 case context of
4972 TC_Annotation name -> "the `" ++ Name.toChars name ++ "` type annotation"
4973 TC_CustomType -> "a custom type"
4974 TC_TypeAlias -> "a type alias"
4975 TC_Port -> "a port"
4976 in
4977 Report.Report ("PROBLEM IN " ++ map Char.toUpper thing) region [] $
4978 Code.toSnippet source surroundings (Just region)
4980 D.reflow $
4981 "I was partway through parsing " ++ something ++ ", but I got stuck here:"
4983 D.fillSep $
4984 ["I","was","expecting","to","see","a","type","next."
4985 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4989 TSpace space row col ->
4990 toSpaceReport source space row col
4992 TIndentStart row col ->
4993 let
4994 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4995 region = toRegion row col
4997 thing =
4998 case context of
4999 TC_Annotation _ -> "type annotation"
5000 TC_CustomType -> "custom type"
5001 TC_TypeAlias -> "type alias"
5002 TC_Port -> "port"
5003 in
5004 Report.Report ("UNFINISHED " ++ map Char.toUpper thing) region [] $
5005 Code.toSnippet source surroundings (Just region)
5007 D.reflow $
5008 "I was partway through parsing a " ++ thing ++ ", but I got stuck here:"
5010 D.stack
5011 [ D.fillSep $
5012 ["I","was","expecting","to","see","a","type","next."
5013 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5015 , D.toSimpleNote $
5016 "I can get confused by indentation. If you think there is already a type\
5017 \ next, maybe it is not indented enough?"
5022toTRecordReport :: Code.Source -> TContext -> TRecord -> Row -> Col -> Report.Report
5023toTRecordReport source context record startRow startCol =
5024 case record of
5025 TRecordOpen row col ->
5026 case Code.whatIsNext source row col of
5027 Code.Keyword keyword ->
5028 let
5029 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5030 region = toKeywordRegion row col keyword
5031 in
5032 Report.Report "RESERVED WORD" region [] $
5033 Code.toSnippet source surroundings (Just region)
5035 D.reflow $
5036 "I just started parsing a record type, but I got stuck on this field name:"
5038 D.reflow $
5039 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5040 \ that is a reserved word. Try using a different name!"
5043 _ ->
5044 let
5045 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5046 region = toRegion row col
5047 in
5048 Report.Report "UNFINISHED RECORD TYPE" region [] $
5049 Code.toSnippet source surroundings (Just region)
5051 D.reflow $
5052 "I just started parsing a record type, but I got stuck here:"
5054 D.fillSep
5055 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
5056 ,"so","I","was","expecting","to","see","a","field","name","next."
5060 TRecordEnd row col ->
5061 let
5062 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5063 region = toRegion row col
5064 in
5065 Report.Report "UNFINISHED RECORD TYPE" region [] $
5066 Code.toSnippet source surroundings (Just region)
5068 D.reflow $
5069 "I am partway through parsing a record type, but I got stuck here:"
5071 D.stack
5072 [ D.fillSep
5073 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
5074 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
5076 , D.toSimpleNote $
5077 "When I get stuck like this, it usually means that there is a missing parenthesis\
5078 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
5082 TRecordField row col ->
5083 case Code.whatIsNext source row col of
5084 Code.Keyword keyword ->
5085 let
5086 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5087 region = toKeywordRegion row col keyword
5088 in
5089 Report.Report "RESERVED WORD" region [] $
5090 Code.toSnippet source surroundings (Just region)
5092 D.reflow $
5093 "I am partway through parsing a record type, but I got stuck on this field name:"
5095 D.reflow $
5096 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5097 \ that is a reserved word. Try using a different name!"
5100 _ ->
5101 let
5102 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5103 region = toRegion row col
5104 in
5105 Report.Report "UNFINISHED RECORD TYPE" region [] $
5106 Code.toSnippet source surroundings (Just region)
5108 D.reflow $
5109 "I am partway through parsing a record type, but I got stuck after that last comma:"
5111 addNoteForRecordTypeError $
5112 D.reflow $
5113 "Trailing commas are not allowed in records, so I was expecting to see another\
5114 \ record field defined next. If you are done defining the record, the fix may\
5115 \ be to delete that last comma?"
5118 TRecordColon row col ->
5119 let
5120 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5121 region = toRegion row col
5122 in
5123 Report.Report "UNFINISHED RECORD TYPE" region [] $
5124 Code.toSnippet source surroundings (Just region)
5126 D.reflow $
5127 "I am partway through parsing a record type, but I got stuck here:"
5129 addNoteForRecordTypeError $
5130 D.fillSep $
5131 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5132 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5136 TRecordType tipe row col ->
5137 toTypeReport source context tipe row col
5139 TRecordSpace space row col ->
5140 toSpaceReport source space row col
5142 TRecordIndentOpen row col ->
5143 let
5144 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5145 region = toRegion row col
5146 in
5147 Report.Report "UNFINISHED RECORD TYPE" region [] $
5148 Code.toSnippet source surroundings (Just region)
5150 D.reflow $
5151 "I just saw the opening curly brace of a record type, but then I got stuck here:"
5153 addNoteForRecordTypeIndentError $
5154 D.fillSep $
5155 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5156 ,"Try","defining","some","fields","of","your","own?"
5160 TRecordIndentEnd row col ->
5161 let
5162 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5163 region = toRegion row col
5164 in
5165 Report.Report "UNFINISHED RECORD TYPE" region [] $
5166 Code.toSnippet source surroundings (Just region)
5168 D.reflow $
5169 "I was expecting to see a closing curly brace next:"
5171 addNoteForRecordTypeIndentError $
5172 D.fillSep $
5173 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
5177 TRecordIndentField row col ->
5178 let
5179 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5180 region = toRegion row col
5181 in
5182 Report.Report "UNFINISHED RECORD TYPE" region [] $
5183 Code.toSnippet source surroundings (Just region)
5185 D.reflow $
5186 "I am partway through parsing a record type, but I got stuck after that last comma:"
5188 addNoteForRecordTypeIndentError $
5189 D.reflow $
5190 "Trailing commas are not allowed in record types, so the fix may be to\
5191 \ delete that last comma? Or maybe you were in the middle of defining\
5192 \ an additional field?"
5195 TRecordIndentColon row col ->
5196 let
5197 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5198 region = toRegion row col
5199 in
5200 Report.Report "UNFINISHED RECORD TYPE" region [] $
5201 Code.toSnippet source surroundings (Just region)
5203 D.reflow $
5204 "I am partway through parsing a record type. I just saw a record\
5205 \ field, so I was expecting to see a colon next:"
5207 addNoteForRecordTypeIndentError $
5208 D.fillSep $
5209 ["Try","putting","an",D.green ":","followed","by","a","type?"
5213 TRecordIndentType row col ->
5214 let
5215 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5216 region = toRegion row col
5217 in
5218 Report.Report "UNFINISHED RECORD TYPE" region [] $
5219 Code.toSnippet source surroundings (Just region)
5221 D.reflow $
5222 "I am partway through parsing a record type, and I was expecting to run into a type next:"
5224 addNoteForRecordTypeIndentError $
5225 D.fillSep $
5226 ["Try","putting","something","like"
5227 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5232addNoteForRecordTypeError :: D.Doc -> D.Doc
5233addNoteForRecordTypeError normalRecommendation =
5234 D.stack $
5235 normalRecommendation
5237 [ D.toSimpleNote
5238 "If you are trying to define a record type across multiple lines, I recommend using this format:"
5239 , D.indent 4 $ D.vcat $
5240 [ "{ name : String"
5241 , ", age : Int"
5242 , ", height : Float"
5243 , "}"
5245 , D.reflow $
5246 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5247 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5248 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5252addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
5253addNoteForRecordTypeIndentError normalRecommendation =
5254 D.stack $
5255 normalRecommendation
5257 [ D.toSimpleNote
5258 "I may be confused by indentation. For example, if you are trying to define\
5259 \ a record type across multiple lines, I recommend using this format:"
5260 , D.indent 4 $ D.vcat $
5261 [ "{ name : String"
5262 , ", age : Int"
5263 , ", height : Float"
5264 , "}"
5266 , D.reflow $
5267 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5268 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5269 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5273toTTupleReport :: Code.Source -> TContext -> TTuple -> Row -> Col -> Report.Report
5274toTTupleReport source context tuple startRow startCol =
5275 case tuple of
5276 TTupleOpen row col ->
5277 case Code.whatIsNext source row col of
5278 Code.Keyword keyword ->
5279 let
5280 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5281 region = toKeywordRegion row col keyword
5282 in
5283 Report.Report "RESERVED WORD" region [] $
5284 Code.toSnippet source surroundings (Just region)
5286 D.reflow $
5287 "I ran into a reserved word unexpectedly:"
5289 D.reflow $
5290 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
5291 \ it is a reserved word. Try using a different name!"
5294 _ ->
5295 let
5296 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5297 region = toRegion row col
5298 in
5299 Report.Report "UNFINISHED PARENTHESES" region [] $
5300 Code.toSnippet source surroundings (Just region)
5302 D.reflow $
5303 "I just saw an open parenthesis, so I was expecting to see a type next."
5305 D.fillSep $
5306 ["Something","like",D.dullyellow "(Maybe Int)","or"
5307 ,D.dullyellow "(List Person)" <> "."
5308 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5312 TTupleEnd row col ->
5313 let
5314 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5315 region = toRegion row col
5316 in
5317 Report.Report "UNFINISHED PARENTHESES" region [] $
5318 Code.toSnippet source surroundings (Just region)
5320 D.reflow $
5321 "I was expecting to see a closing parenthesis next, but I got stuck here:"
5323 D.stack
5324 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
5325 , D.toSimpleNote $
5326 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
5327 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
5328 \ or missing brackets) that is confusing me."
5332 TTupleType tipe row col ->
5333 toTypeReport source context tipe row col
5335 TTupleSpace space row col ->
5336 toSpaceReport source space row col
5338 TTupleIndentType1 row col ->
5339 let
5340 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5341 region = toRegion row col
5342 in
5343 Report.Report "UNFINISHED PARENTHESES" region [] $
5344 Code.toSnippet source surroundings (Just region)
5346 D.reflow $
5347 "I just saw an open parenthesis, so I was expecting to see a type next."
5349 D.stack
5350 [ D.fillSep $
5351 ["Something","like",D.dullyellow "(Maybe Int)","or"
5352 ,D.dullyellow "(List Person)" <> "."
5353 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5355 , D.toSimpleNote $
5356 "I can get confused by indentation in cases like this, so\
5357 \ maybe you have a type but it is not indented enough?"
5361 TTupleIndentTypeN row col ->
5362 let
5363 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5364 region = toRegion row col
5365 in
5366 Report.Report "UNFINISHED TUPLE TYPE" region [] $
5367 Code.toSnippet source surroundings (Just region)
5369 D.reflow $
5370 "I think I am in the middle of parsing a tuple type. I just saw a comma, so I was expecting to see a type next."
5372 D.stack
5373 [ D.fillSep $
5374 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
5375 ,D.dullyellow "(String,Int)" <> ","
5376 ,"so","I","think","there","is","a","type","missing","here?"
5378 , D.toSimpleNote $
5379 "I can get confused by indentation in cases like this, so\
5380 \ maybe you have an expression but it is not indented enough?"
5384 TTupleIndentEnd row col ->
5385 let
5386 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5387 region = toRegion row col
5388 in
5389 Report.Report "UNFINISHED PARENTHESES" region [] $
5390 Code.toSnippet source surroundings (Just region)
5392 D.reflow $
5393 "I was expecting to see a closing parenthesis next:"
5395 D.stack
5396 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
5397 , D.toSimpleNote $
5398 "I can get confused by indentation in cases like this, so\
5399 \ maybe you have a closing parenthesis but it is not indented enough?"