on 11ffbf5 help sign in
5673 lines 206 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 declaration, but I am getting stuck here:"
1412 D.stack
1413 [ case Code.whatIsNext source row col of
1414 Code.Other (Just char) | Char.isUpper char ->
1415 D.reflow $
1416 "All declarations start with lower-case letters in Elm, so maybe this letter can\
1417 \ be changed to lower-case?"
1419 _ ->
1420 D.reflow $
1421 "Declarations normally start with a lower-case name or the `type` keyword."
1422 , D.toSimpleHint $
1423 "Here are a couple valid declarations for reference:"
1424 , D.vcat
1425 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1426 , D.fillSep [D.green "add","x","y","="]
1427 , D.fillSep [" ","x","+","y"]
1429 , D.fillSep [D.cyan "type",D.green "User","=","Anonymous","|","LoggedIn String"]
1430 , D.reflow $
1431 "Notice that these declarations start with lower-case letters. Capitalization\
1432 \ makes a difference in Elm!"
1436 DeclSpace space row col ->
1437 toSpaceReport source space row col
1439 Port port_ row col ->
1440 toPortReport source port_ row col
1442 DeclType declType row col ->
1443 toDeclTypeReport source declType row col
1445 DeclDef name declDef row col ->
1446 toDeclDefReport source name declDef row col
1448 DeclFreshLineAfterDocComment row col ->
1449 let
1450 region = toRegion row col
1451 in
1452 Report.Report "EXPECTING DECLARATION" region [] $
1453 Code.toSnippet source region Nothing
1455 D.reflow $
1456 "I just saw a doc comment, but then I got stuck here:"
1458 D.reflow $
1459 "I was expecting to see the corresponding declaration next, starting on a fresh\
1460 \ line with no indentation."
1465-- PORT
1468toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1469toPortReport source port_ startRow startCol =
1470 case port_ of
1471 PortSpace space row col ->
1472 toSpaceReport source space row col
1474 PortName row col ->
1475 case Code.whatIsNext source row col of
1476 Code.Keyword keyword ->
1477 let
1478 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1479 region = toKeywordRegion row col keyword
1480 in
1481 Report.Report "RESERVED WORD" region [] $
1482 Code.toSnippet source surroundings (Just region)
1484 D.reflow $
1485 "I cannot handle ports with names like this:"
1487 D.reflow $
1488 "You are trying to make a port named `" ++ keyword
1489 ++ "` but that is a reserved word. Try using some other name?"
1492 _ ->
1493 let
1494 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1495 region = toRegion row col
1496 in
1497 Report.Report "PORT PROBLEM" region [] $
1498 Code.toSnippet source surroundings (Just region)
1500 D.reflow $
1501 "I just saw the start of a `port` declaration, but then I got stuck here:"
1503 D.stack
1504 [ D.fillSep
1505 ["I","was","expecting","to","see","a","name","like"
1506 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1507 ,"Something","that","starts","with","a","lower-case","letter."
1509 , portNote
1513 PortColon row col ->
1514 let
1515 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1516 region = toRegion row col
1517 in
1518 Report.Report "PORT PROBLEM" region [] $
1519 Code.toSnippet source surroundings (Just region)
1521 D.reflow $
1522 "I just saw the start of a `port` declaration, but then I got stuck here:"
1524 D.stack
1525 [ D.reflow $
1526 "I was expecting to see a colon next. And then a type that tells me\
1527 \ what type of values are going to flow through."
1528 , portNote
1532 PortType tipe row col ->
1533 toTypeReport source TC_Port tipe row col
1535 PortIndentName row col ->
1536 let
1537 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1538 region = toRegion row col
1539 in
1540 Report.Report "UNFINISHED PORT" region [] $
1541 Code.toSnippet source surroundings (Just region)
1543 D.reflow $
1544 "I just saw the start of a `port` declaration, but then I got stuck here:"
1546 D.stack
1547 [ D.fillSep
1548 ["I","was","expecting","to","see","a","name","like"
1549 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1550 ,"Something","that","starts","with","a","lower-case","letter."
1552 , portNote
1556 PortIndentColon row col ->
1557 let
1558 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1559 region = toRegion row col
1560 in
1561 Report.Report "UNFINISHED PORT" region [] $
1562 Code.toSnippet source surroundings (Just region)
1564 D.reflow $
1565 "I just saw the start of a `port` declaration, but then I got stuck here:"
1567 D.stack
1568 [ D.reflow $
1569 "I was expecting to see a colon next. And then a type that tells me\
1570 \ what type of values are going to flow through."
1571 , portNote
1575 PortIndentType row col ->
1576 let
1577 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1578 region = toRegion row col
1579 in
1580 Report.Report "UNFINISHED PORT" region [] $
1581 Code.toSnippet source surroundings (Just region)
1583 D.reflow $
1584 "I just saw the start of a `port` declaration, but then I got stuck here:"
1586 D.stack
1587 [ D.reflow $
1588 "I was expecting to see a type next. Here are examples of outgoing and\
1589 \ incoming ports for reference:"
1590 , D.vcat
1591 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1592 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1594 , D.reflow $
1595 "The first line defines a `send` port so you can send strings out to JavaScript.\
1596 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1597 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1598 \ get receive messages when new WebSocket messages come in or when an entry in\
1599 \ IndexedDB changes for some external reason."
1604portNote :: D.Doc
1605portNote =
1606 D.stack
1607 [ D.toSimpleNote $
1608 "Here are some example `port` declarations for reference:"
1609 , D.vcat
1610 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1611 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1613 , D.reflow $
1614 "The first line defines a `send` port so you can send strings out to JavaScript.\
1615 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1616 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1617 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1618 \ is changed for some external reason."
1623-- DECL TYPE
1626toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1627toDeclTypeReport source declType startRow startCol =
1628 case declType of
1629 DT_Space space row col ->
1630 toSpaceReport source space row col
1632 DT_Name row col ->
1633 let
1634 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1635 region = toRegion row col
1636 in
1637 Report.Report "EXPECTING TYPE NAME" region [] $
1638 Code.toSnippet source surroundings (Just region)
1640 D.reflow $
1641 "I think I am parsing a type declaration, but I got stuck here:"
1643 D.stack
1644 [ D.fillSep $
1645 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1646 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1648 , customTypeNote
1652 DT_Alias typeAlias row col ->
1653 toTypeAliasReport source typeAlias row col
1655 DT_Union customType row col ->
1656 toCustomTypeReport source customType row col
1658 DT_IndentName row col ->
1659 let
1660 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1661 region = toRegion row col
1662 in
1663 Report.Report "EXPECTING TYPE NAME" region [] $
1664 Code.toSnippet source surroundings (Just region)
1666 D.reflow $
1667 "I think I am parsing a type declaration, but I got stuck here:"
1669 D.stack
1670 [ D.fillSep $
1671 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1672 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1674 , customTypeNote
1679toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1680toTypeAliasReport source typeAlias startRow startCol =
1681 case typeAlias of
1682 AliasSpace space row col ->
1683 toSpaceReport source space row col
1685 AliasName row col ->
1686 let
1687 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1688 region = toRegion row col
1689 in
1690 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1691 Code.toSnippet source surroundings (Just region)
1693 D.reflow $
1694 "I am partway through parsing a type alias, but I got stuck here:"
1696 D.stack
1697 [ D.fillSep $
1698 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1699 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1701 , typeAliasNote
1705 AliasEquals row col ->
1706 case Code.whatIsNext source row col of
1707 Code.Keyword keyword ->
1708 let
1709 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1710 region = toKeywordRegion row col keyword
1711 in
1712 Report.Report "RESERVED WORD" region [] $
1713 Code.toSnippet source surroundings (Just region)
1715 D.reflow $
1716 "I ran into a reserved word unexpectedly while parsing this type alias:"
1718 D.stack
1719 [ D.reflow $
1720 "It looks like you are trying use `" ++ keyword
1721 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1722 , typeAliasNote
1726 _ ->
1727 let
1728 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1729 region = toRegion row col
1730 in
1731 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1732 Code.toSnippet source surroundings (Just region)
1734 D.reflow $
1735 "I am partway through parsing a type alias, but I got stuck here:"
1737 D.stack
1738 [ D.reflow $
1739 "I was expecting to see a type variable or an equals sign next."
1740 , typeAliasNote
1744 AliasBody tipe row col ->
1745 toTypeReport source TC_TypeAlias tipe row col
1747 AliasIndentEquals row col ->
1748 let
1749 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1750 region = toRegion row col
1751 in
1752 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1753 Code.toSnippet source surroundings (Just region)
1755 D.reflow $
1756 "I am partway through parsing a type alias, but I got stuck here:"
1758 D.stack
1759 [ D.reflow $
1760 "I was expecting to see a type variable or an equals sign next."
1761 , typeAliasNote
1765 AliasIndentBody row col ->
1766 let
1767 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1768 region = toRegion row col
1769 in
1770 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1771 Code.toSnippet source surroundings (Just region)
1773 D.reflow $
1774 "I am partway through parsing a type alias, but I got stuck here:"
1776 D.stack
1777 [ D.fillSep $
1778 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1779 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1781 , typeAliasNote
1786typeAliasNote :: D.Doc
1787typeAliasNote =
1788 D.stack
1789 [ D.toSimpleNote $
1790 "Here is an example of a valid `type alias` for reference:"
1791 , D.vcat $
1792 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1793 , D.indent 2 $ D.vcat $
1794 ["{ name : String"
1795 ,", age : Int"
1796 ,", height : Float"
1797 ,"}"
1800 , D.reflow $
1801 "This would let us use `Person` as a shorthand for that record type. Using this\
1802 \ shorthand makes type annotations much easier to read, and makes changing code\
1803 \ easier if you decide later that there is more to a person than age and height!"
1807toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1808toCustomTypeReport source customType startRow startCol =
1809 case customType of
1810 CT_Space space row col ->
1811 toSpaceReport source space row col
1813 CT_Name row col ->
1814 let
1815 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1816 region = toRegion row col
1817 in
1818 Report.Report "EXPECTING TYPE NAME" region [] $
1819 Code.toSnippet source surroundings (Just region)
1821 D.reflow $
1822 "I think I am parsing a type declaration, but I got stuck here:"
1824 D.stack
1825 [ D.fillSep $
1826 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1827 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1829 , customTypeNote
1833 CT_Equals row col ->
1834 case Code.whatIsNext source row col of
1835 Code.Keyword keyword ->
1836 let
1837 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1838 region = toKeywordRegion row col keyword
1839 in
1840 Report.Report "RESERVED WORD" region [] $
1841 Code.toSnippet source surroundings (Just region)
1843 D.reflow $
1844 "I ran into a reserved word unexpectedly while parsing this custom type:"
1846 D.stack
1847 [ D.reflow $
1848 "It looks like you are trying use `" ++ keyword
1849 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1850 , customTypeNote
1854 _ ->
1855 let
1856 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1857 region = toRegion row col
1858 in
1859 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1860 Code.toSnippet source surroundings (Just region)
1862 D.reflow $
1863 "I am partway through parsing a custom type, but I got stuck here:"
1865 D.stack
1866 [ D.reflow $
1867 "I was expecting to see a type variable or an equals sign next."
1868 , customTypeNote
1872 CT_Bar row col ->
1873 let
1874 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1875 region = toRegion row col
1876 in
1877 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1878 Code.toSnippet source surroundings (Just region)
1880 D.reflow $
1881 "I am partway through parsing a custom type, but I got stuck here:"
1883 D.stack
1884 [ D.reflow $
1885 "I was expecting to see a vertical bar like | next."
1886 , customTypeNote
1890 CT_Variant row col ->
1891 let
1892 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1893 region = toRegion row col
1894 in
1895 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1896 Code.toSnippet source surroundings (Just region)
1898 D.reflow $
1899 "I am partway through parsing a custom type, but I got stuck here:"
1901 D.stack
1902 [ D.fillSep $
1903 ["I","was","expecting","to","see","a","variant","name","next."
1904 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1905 ,"Any","name","that","starts","with","a","capital","letter","really!"
1907 , customTypeNote
1911 CT_VariantArg tipe row col ->
1912 toTypeReport source TC_CustomType tipe row col
1914 CT_IndentEquals row col ->
1915 let
1916 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1917 region = toRegion row col
1918 in
1919 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1920 Code.toSnippet source surroundings (Just region)
1922 D.reflow $
1923 "I am partway through parsing a custom type, but I got stuck here:"
1925 D.stack
1926 [ D.reflow $
1927 "I was expecting to see a type variable or an equals sign next."
1928 , customTypeNote
1932 CT_IndentBar row col ->
1933 let
1934 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1935 region = toRegion row col
1936 in
1937 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1938 Code.toSnippet source surroundings (Just region)
1940 D.reflow $
1941 "I am partway through parsing a custom type, but I got stuck here:"
1943 D.stack
1944 [ D.reflow $
1945 "I was expecting to see a vertical bar like | next."
1946 , customTypeNote
1950 CT_IndentAfterBar row col ->
1951 let
1952 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1953 region = toRegion row col
1954 in
1955 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1956 Code.toSnippet source surroundings (Just region)
1958 D.reflow $
1959 "I am partway through parsing a custom type, but I got stuck here:"
1961 D.stack
1962 [ D.reflow $
1963 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1964 , customTypeNote
1968 CT_IndentAfterEquals row col ->
1969 let
1970 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1971 region = toRegion row col
1972 in
1973 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1974 Code.toSnippet source surroundings (Just region)
1976 D.reflow $
1977 "I am partway through parsing a custom type, but I got stuck here:"
1979 D.stack
1980 [ D.reflow $
1981 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1982 , customTypeNote
1987customTypeNote :: D.Doc
1988customTypeNote =
1989 D.stack
1990 [ D.toSimpleNote $
1991 "Here is an example of a valid `type` declaration for reference:"
1992 , D.vcat $
1993 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1994 , D.indent 2 $ D.fillSep ["=","Failure"]
1995 , D.indent 2 $ D.fillSep ["|","Waiting"]
1996 , D.indent 2 $ D.fillSep ["|","Success","String"]
1998 , D.reflow $
1999 "This defines a new `Status` type with three variants. This could be useful if\
2000 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
2001 \ switch to `Failure` or `Success \"message from server\"` depending on how\
2002 \ things go. Notice that the Success variant has some associated data, allowing\
2003 \ us to store a String if the request goes well!"
2008-- DECL DEF
2011toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
2012toDeclDefReport source name declDef startRow startCol =
2013 case declDef of
2014 DeclDefSpace space row col ->
2015 toSpaceReport source space row col
2017 DeclDefEquals row col ->
2018 case Code.whatIsNext source row col of
2019 Code.Keyword keyword ->
2020 let
2021 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2022 region = toKeywordRegion row col keyword
2023 in
2024 Report.Report "RESERVED WORD" region [] $
2025 Code.toSnippet source surroundings (Just region)
2027 D.fillSep
2028 ["The","name"
2029 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
2030 ,"is","reserved","in","Elm,","so","it","cannot"
2031 ,"be","used","as","an","argument","here:"
2034 D.stack
2035 [ D.reflow $
2036 "Try renaming it to something else."
2037 , case keyword of
2038 "as" ->
2039 D.toFancyNote
2040 ["This","keyword","is","reserved","for","pattern","matches","like"
2041 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
2042 ,"the","values","it","contains."
2045 _ ->
2046 D.toSimpleNote $
2047 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
2051 Code.Operator "->" ->
2052 let
2053 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2054 region = toWiderRegion row col 2
2055 in
2056 Report.Report "MISSING COLON?" region [] $
2057 Code.toSnippet source surroundings (Just region)
2059 D.reflow $
2060 "I was not expecting to see an arrow here:"
2062 D.stack
2063 [ D.fillSep
2064 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
2065 ,"a","type","annotation.","It","could","be","something","else","though,","so"
2066 ,"here","is","a","valid","definition","for","reference:"
2068 , D.vcat
2069 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2070 , D.fillSep [D.green "add","x","y","="]
2071 , D.fillSep [" ","x","+","y"]
2073 , D.reflow $
2074 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2078 Code.Operator op ->
2079 let
2080 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2081 region = toKeywordRegion row col op
2082 in
2083 Report.Report "UNEXPECTED SYMBOL" region [] $
2084 Code.toSnippet source surroundings (Just region)
2086 D.reflow $
2087 "I was not expecting to see this symbol here:"
2089 D.stack
2090 [ D.reflow $
2091 "I am not sure what is going wrong exactly, so here is a valid\
2092 \ definition (with an optional type annotation) for reference:"
2093 , D.vcat
2094 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2095 , D.fillSep [D.green "add","x","y","="]
2096 , D.fillSep [" ","x","+","y"]
2098 , D.reflow $
2099 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2103 _ ->
2104 let
2105 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2106 region = toRegion row col
2107 in
2108 Report.Report "PROBLEM IN DEFINITION" region [] $
2109 Code.toSnippet source surroundings (Just region)
2111 D.reflow $
2112 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2114 D.stack
2115 [ D.reflow $
2116 "I am not sure what is going wrong exactly, so here is a valid\
2117 \ definition (with an optional type annotation) for reference:"
2118 , D.vcat
2119 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2120 , D.fillSep [D.green "add","x","y","="]
2121 , D.fillSep [" ","x","+","y"]
2123 , D.reflow $
2124 "Try to use that format!"
2128 DeclDefType tipe row col ->
2129 toTypeReport source (TC_Annotation name) tipe row col
2131 DeclDefArg pattern row col ->
2132 toPatternReport source PArg pattern row col
2134 DeclDefBody expr row col ->
2135 toExprReport source (InDef name startRow startCol) expr row col
2137 DeclDefNameRepeat row col ->
2138 let
2139 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2140 region = toRegion row col
2141 in
2142 Report.Report "EXPECTING DEFINITION" region [] $
2143 Code.toSnippet source surroundings (Just region)
2145 D.reflow $
2146 "I just saw the type annotation for `" ++ Name.toChars name
2147 ++ "` so I was expecting to see its definition here:"
2149 D.stack
2150 [ D.reflow $
2151 "Type annotations always appear directly above the relevant\
2152 \ definition, without anything else in between. (Not even doc comments!)"
2153 , declDefNote
2157 DeclDefNameMatch defName row col ->
2158 let
2159 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2160 region = toRegion row col
2161 in
2162 Report.Report "NAME MISMATCH" region [] $
2163 Code.toSnippet source surroundings (Just region)
2165 D.reflow $
2166 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2168 D.stack
2169 [ D.reflow $
2170 "These names do not match! Is there a typo?"
2171 , D.indent 4 $ D.fillSep $
2172 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2176 DeclDefIndentType row col ->
2177 let
2178 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2179 region = toRegion row col
2180 in
2181 Report.Report "UNFINISHED DEFINITION" region [] $
2182 Code.toSnippet source surroundings (Just region)
2184 D.reflow $
2185 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
2187 D.stack
2188 [ D.reflow $
2189 "I just saw a colon, so I am expecting to see a type next."
2190 , declDefNote
2194 DeclDefIndentEquals row col ->
2195 let
2196 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2197 region = toRegion row col
2198 in
2199 Report.Report "UNFINISHED DEFINITION" region [] $
2200 Code.toSnippet source surroundings (Just region)
2202 D.reflow $
2203 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2205 D.stack
2206 [ D.reflow $
2207 "I was expecting to see an argument or an equals sign next."
2208 , declDefNote
2212 DeclDefIndentBody row col ->
2213 let
2214 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2215 region = toRegion row col
2216 in
2217 Report.Report "UNFINISHED DEFINITION" region [] $
2218 Code.toSnippet source surroundings (Just region)
2220 D.reflow $
2221 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
2223 D.stack
2224 [ D.reflow $
2225 "I was expecting to see an expression next. What is it equal to?"
2226 , declDefNote
2231declDefNote :: D.Doc
2232declDefNote =
2233 D.stack
2234 [ D.reflow $
2235 "Here is a valid definition (with a type annotation) for reference:"
2236 , D.vcat
2237 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2238 , D.fillSep [D.green "add","x","y","="]
2239 , D.fillSep [" ","x","+","y"]
2241 , D.reflow $
2242 "The top line (called a \"type annotation\") is optional. You can leave it off\
2243 \ if you want. As you get more comfortable with Elm and as your project grows,\
2244 \ it becomes more and more valuable to add them though! They work great as\
2245 \ compiler-verified documentation, and they often improve error messages!"
2250-- CONTEXT
2253data Context
2254 = InNode Node Row Col Context
2255 | InDef Name.Name Row Col
2256 | InDestruct Row Col
2259data Node
2260 = NRecord
2261 | NParens
2262 | NList
2263 | NFunc
2264 | NCond
2265 | NThen
2266 | NElse
2267 | NCase
2268 | NBranch
2269 deriving (Eq)
2272getDefName :: Context -> Maybe Name.Name
2273getDefName context =
2274 case context of
2275 InDestruct _ _ -> Nothing
2276 InDef name _ _ -> Just name
2277 InNode _ _ _ c -> getDefName c
2280isWithin :: Node -> Context -> Bool
2281isWithin desiredNode context =
2282 case context of
2283 InDestruct _ _ -> False
2284 InDef _ _ _ -> False
2285 InNode actualNode _ _ _ -> desiredNode == actualNode
2289-- EXPR REPORTS
2292toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2293toExprReport source context expr startRow startCol =
2294 case expr of
2295 Let let_ row col ->
2296 toLetReport source context let_ row col
2298 Case case_ row col ->
2299 toCaseReport source context case_ row col
2301 If if_ row col ->
2302 toIfReport source context if_ row col
2304 List list row col ->
2305 toListReport source context list row col
2307 Record record row col ->
2308 toRecordReport source context record row col
2310 Tuple tuple row col ->
2311 toTupleReport source context tuple row col
2313 Func func row col ->
2314 toFuncReport source context func row col
2316 Dot row col ->
2317 let region = toRegion row col in
2318 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2319 Code.toSnippet source region Nothing
2321 D.reflow $
2322 "I was expecting to see a record accessor here:"
2324 D.fillSep
2325 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2326 ,"that","accesses","a","value","from","a","record."
2330 Access row col ->
2331 let region = toRegion row col in
2332 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2333 Code.toSnippet source region Nothing
2335 D.reflow $
2336 "I am trying to parse a record accessor here:"
2338 D.stack
2340 D.fillSep
2341 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2342 ,"that","accesses","a","value","from","a","record."
2345 D.toSimpleNote $
2346 "Record field names must start with a lower case letter!"
2350 OperatorRight op row col ->
2351 let
2352 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2353 region = toRegion row col
2354 isMath = elem op ["-","+","*","/","^"]
2355 in
2356 Report.Report "MISSING EXPRESSION" region [] $
2357 Code.toSnippet source surroundings (Just region)
2359 D.reflow $
2360 "I just saw a " ++ Name.toChars op ++ " "
2361 ++ (if isMath then "sign" else "operator")
2362 ++ ", so I am getting stuck here:"
2364 if isMath then
2365 D.fillSep
2366 ["I","was","expecting","to","see","an","expression","next."
2367 ,"Something","like",D.dullyellow "42","or",D.dullyellow "1000"
2368 ,"that","makes","sense","with","a",D.fromName op,"sign."
2370 else if op == "&&" || op == "||" then
2371 D.fillSep
2372 ["I","was","expecting","to","see","an","expression","next."
2373 ,"Something","like",D.dullyellow "True","or",D.dullyellow "False"
2374 ,"that","makes","sense","with","boolean","logic."
2376 else if op == "|>" then
2377 D.reflow $
2378 "I was expecting to see a function next."
2379 else if op == "<|" then
2380 D.reflow $
2381 "I was expecting to see an argument next."
2382 else
2383 D.reflow $
2384 "I was expecting to see an expression next."
2387 OperatorReserved operator row col ->
2388 toOperatorReport source context operator row col
2390 Start row col ->
2391 let
2392 (contextRow, contextCol, aThing) =
2393 case context of
2394 InDestruct r c -> (r, c, "a definition")
2395 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2396 InNode NRecord r c _ -> (r, c, "a record")
2397 InNode NParens r c _ -> (r, c, "some parentheses")
2398 InNode NList r c _ -> (r, c, "a list")
2399 InNode NFunc r c _ -> (r, c, "an anonymous function")
2400 InNode NCond r c _ -> (r, c, "an `if` expression")
2401 InNode NThen r c _ -> (r, c, "an `if` expression")
2402 InNode NElse r c _ -> (r, c, "an `if` expression")
2403 InNode NCase r c _ -> (r, c, "a `case` expression")
2404 InNode NBranch r c _ -> (r, c, "a `case` expression")
2406 surroundings = A.Region (A.Position contextRow contextCol) (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 am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2415 D.stack
2416 [ D.fillSep $
2417 ["I","was","expecting","to","see","an","expression","like"
2418 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2419 ,"Once","there","is","something","there,","I","can","probably"
2420 ,"give","a","more","specific","hint!"
2422 , D.toSimpleNote $
2423 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2424 \ Or if I run into operators in unexpected spots. Point is, there are a\
2425 \ couple ways I can get confused and give sort of weird advice!"
2429 Char char row col ->
2430 toCharReport source char row col
2432 String string row col ->
2433 toStringReport source string row col
2435 Number number row col ->
2436 toNumberReport source number row col
2438 Space space row col ->
2439 toSpaceReport source space row col
2441 EndlessShader row col ->
2442 let
2443 region = toWiderRegion row col 6
2444 in
2445 Report.Report "ENDLESS SHADER" region [] $
2446 Code.toSnippet source region Nothing
2448 D.reflow "I cannot find the end of this shader:"
2450 D.reflow "Add a |] somewhere after this to end the shader."
2453 ShaderProblem problem row col ->
2454 let
2455 region = toRegion row col
2456 in
2457 Report.Report "SHADER PROBLEM" region [] $
2458 Code.toSnippet source region Nothing
2460 D.reflow $
2461 "I ran into a problem while parsing this GLSL block."
2463 D.stack
2464 [ D.reflow $
2465 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2466 , D.indent 4 $ D.vcat $
2467 map D.fromChars (filter (/="") (lines problem))
2471 IndentOperatorRight op row col ->
2472 let
2473 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2474 region = toRegion row col
2475 in
2476 Report.Report "MISSING EXPRESSION" region [] $
2477 Code.toSnippet source surroundings (Just region)
2479 D.reflow $
2480 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2482 D.stack
2484 D.fillSep $
2485 ["You","can","just","put","anything","for","now,","like"
2486 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2487 ,"Once","there","is","something","there,","I","can","probably"
2488 ,"give","a","more","specific","hint!"
2491 D.toSimpleNote $
2492 "I may be getting confused by your indentation? The easiest way to make sure\
2493 \ this is not an indentation problem is to put the expression on the right of\
2494 \ the " ++ Name.toChars op ++ " operator on the same line."
2500-- CHAR
2503toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2504toCharReport source char row col =
2505 case char of
2506 CharEndless ->
2507 let
2508 region = toRegion row col
2509 in
2510 Report.Report "MISSING SINGLE QUOTE" region [] $
2511 Code.toSnippet source region Nothing
2513 D.reflow $
2514 "I thought I was parsing a character, but I got to the end of\
2515 \ the line without seeing the closing single quote:"
2517 D.reflow $
2518 "Add a closing single quote here!"
2521 CharEscape escape ->
2522 toEscapeReport source escape row col
2524 CharNotString width ->
2525 let
2526 region = toWiderRegion row col width
2527 in
2528 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2529 Code.toSnippet source region Nothing
2531 "The following string uses single quotes:"
2533 D.stack
2534 [ "Please switch to double quotes instead:"
2535 , D.indent 4 $
2536 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2537 , D.toSimpleNote $
2538 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2539 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2540 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2541 \ individual characters."
2547-- STRING
2550toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2551toStringReport source string row col =
2552 case string of
2553 StringEndless_Single ->
2554 let
2555 region = toRegion row col
2556 in
2557 Report.Report "ENDLESS STRING" region [] $
2558 Code.toSnippet source region Nothing
2560 D.reflow $
2561 "I got to the end of the line without seeing the closing double quote:"
2563 D.stack
2564 [ D.fillSep $
2565 ["Strings","look","like",D.green "\"this\"","with","double"
2566 ,"quotes","on","each","end.","Is","the","closing","double"
2567 ,"quote","missing","in","your","code?"
2569 , D.toSimpleNote $
2570 "For a string that spans multiple lines, you can use the multi-line string\
2571 \ syntax like this:"
2572 , D.vcat
2573 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2574 , mempty
2575 , D.dullyellow "# Multi-line Strings"
2576 , mempty
2577 , D.dullyellow "- start with triple double quotes"
2578 , D.dullyellow "- write whatever you want"
2579 , D.dullyellow "- no need to escape newlines or double quotes"
2580 , D.dullyellow "- end with triple double quotes"
2581 , mempty
2582 , D.dullyellow "\"\"\""
2587 StringEndless_Multi ->
2588 let
2589 region = toWiderRegion row col 3
2590 in
2591 Report.Report "ENDLESS STRING" region [] $
2592 Code.toSnippet source region Nothing
2594 D.reflow $
2595 "I cannot find the end of this multi-line string:"
2597 D.stack
2598 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2599 , D.toSimpleNote $
2600 "Here is a valid multi-line string for reference:"
2601 , D.vcat
2602 [ D.fillSep [D.green "markdown","=",D.dullyellow "\"\"\""]
2603 , mempty
2604 , D.dullyellow "# Multi-line Strings"
2605 , mempty
2606 , D.dullyellow "- start with triple double quotes"
2607 , D.dullyellow "- write whatever you want"
2608 , D.dullyellow "- no need to escape newlines or double quotes"
2609 , D.dullyellow "- end with triple double quotes"
2610 , mempty
2611 , D.dullyellow "\"\"\""
2616 StringEscape escape ->
2617 toEscapeReport source escape row col
2621-- ESCAPES
2624toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2625toEscapeReport source escape row col =
2626 case escape of
2627 EscapeUnknown ->
2628 let
2629 region = toWiderRegion row col 2
2630 in
2631 Report.Report "UNKNOWN ESCAPE" region [] $
2632 Code.toSnippet source region Nothing
2634 D.reflow $
2635 "Backslashes always start escaped characters, but I do not recognize this one:"
2637 D.stack
2638 [ D.reflow $
2639 "Valid escape characters include:"
2640 , D.dullyellow $ D.indent 4 $ D.vcat $
2641 [ "\\n"
2642 , "\\r"
2643 , "\\t"
2644 , "\\\""
2645 , "\\\'"
2646 , "\\\\"
2647 , "\\u{003D}"
2649 , D.reflow $
2650 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2651 , D.toSimpleNote $
2652 "The last style lets encode ANY character by its Unicode code\
2653 \ point. That means \\u{0009} and \\t are the same. You can use\
2654 \ that style for anything not covered by the other six escapes!"
2658 BadUnicodeFormat width ->
2659 let
2660 region = toWiderRegion row col width
2661 in
2662 Report.Report "BAD UNICODE ESCAPE" region [] $
2663 Code.toSnippet source region Nothing
2665 D.reflow $
2666 "I ran into an invalid Unicode escape:"
2668 D.stack
2669 [ D.reflow $
2670 "Here are some examples of valid Unicode escapes:"
2671 , D.dullyellow $ D.indent 4 $ D.vcat $
2672 [ "\\u{0041}"
2673 , "\\u{03BB}"
2674 , "\\u{6728}"
2675 , "\\u{1F60A}"
2677 , D.reflow $
2678 "Notice that the code point is always surrounded by curly braces.\
2679 \ Maybe you are missing the opening or closing curly brace?"
2682 BadUnicodeCode width ->
2683 let
2684 region = toWiderRegion row col width
2685 in
2686 Report.Report "BAD UNICODE ESCAPE" region [] $
2687 Code.toSnippet source region Nothing
2689 D.reflow $
2690 "This is not a valid code point:"
2692 D.reflow $
2693 "The valid code points are between 0 and 10FFFF inclusive."
2696 BadUnicodeLength width numDigits badCode ->
2697 let
2698 region = toWiderRegion row col width
2699 in
2700 Report.Report "BAD UNICODE ESCAPE" region [] $
2701 Code.toSnippet source region Nothing $
2702 if numDigits < 4 then
2704 D.reflow $
2705 "Every code point needs at least four digits:"
2707 let
2708 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2709 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2710 in
2711 D.fillSep ["Try",D.green suggestion,"instead?"]
2714 else
2716 D.reflow $
2717 "This code point has too many digits:"
2719 D.fillSep $
2720 ["Valid","code","points","are","between"
2721 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2722 ,"so","try","trimming","any","leading","zeros","until"
2723 ,"you","have","between","four","and","six","digits."
2729-- NUMBERS
2732toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2733toNumberReport source number row col =
2734 let
2735 region = toRegion row col
2736 in
2737 case number of
2738 NumberEnd ->
2739 Report.Report "WEIRD NUMBER" region [] $
2740 Code.toSnippet source region Nothing
2742 D.reflow $
2743 "I thought I was reading a number, but I ran into some weird stuff here:"
2745 D.stack
2746 [ D.reflow $
2747 "I recognize numbers in the following formats:"
2748 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2749 , D.reflow $
2750 "So is there a way to write it like one of those?"
2754 NumberDot int ->
2755 Report.Report "WEIRD NUMBER" region [] $
2756 Code.toSnippet source region Nothing
2758 D.reflow $
2759 "Numbers cannot end with a dot like this:"
2761 D.fillSep
2762 ["Switching","to",D.green (D.fromChars (show int))
2763 ,"or",D.green (D.fromChars (show int ++ ".0"))
2764 ,"will","work","though!"
2768 NumberHexDigit ->
2769 Report.Report "WEIRD HEXIDECIMAL" region [] $
2770 Code.toSnippet source region Nothing
2772 D.reflow $
2773 "I thought I was reading a hexidecimal number until I got here:"
2775 D.stack
2776 [ D.reflow $
2777 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2778 \ only recognize things like this:"
2779 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2783 NumberNoLeadingZero ->
2784 Report.Report "LEADING ZEROS" region [] $
2785 Code.toSnippet source region Nothing
2787 D.reflow $
2788 "I do not accept numbers with leading zeros:"
2790 D.stack
2791 [ D.reflow $
2792 "Just delete the leading zeros and it should work!"
2793 , D.toSimpleNote $
2794 "Some languages let you to specify octal numbers by adding a leading zero.\
2795 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2796 \ that, but others probably want it to equal 111. Either path is going to\
2797 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2798 \ situation."
2804-- OPERATORS
2807toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2808toOperatorReport source context operator row col =
2809 case operator of
2810 BadDot ->
2811 let
2812 region = toRegion row col
2813 in
2814 Report.Report "UNEXPECTED SYMBOL" region [] $
2815 Code.toSnippet source region Nothing
2817 "I was not expecting this dot:"
2819 D.reflow $
2820 "Dots are for record access and decimal points, so\
2821 \ they cannot float around on their own. Maybe\
2822 \ there is some extra whitespace?"
2825 BadPipe ->
2826 let
2827 region = toRegion row col
2828 in
2829 Report.Report "UNEXPECTED SYMBOL" region [] $
2830 Code.toSnippet source region Nothing
2832 D.reflow $
2833 "I was not expecting this vertical bar:"
2835 D.reflow $
2836 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2839 BadArrow ->
2840 let
2841 region = toWiderRegion row col 2
2842 in
2843 Report.Report "UNEXPECTED ARROW" region [] $
2844 Code.toSnippet source region Nothing $
2845 if isWithin NCase context then
2847 D.reflow $
2848 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2850 D.stack
2851 [ D.reflow "Maybe the `of` keyword is missing on a previous line?"
2852 , noteForCaseError
2856 else if isWithin NBranch context then
2858 D.reflow $
2859 "I am parsing a `case` expression right now, but this arrow is confusing me:"
2861 D.stack
2862 [ D.reflow $
2863 "It makes sense to see arrows around here, so I suspect it is something earlier. Maybe this pattern is indented a bit farther than the previous patterns?"
2864 , noteForCaseIndentError
2868 else
2870 D.reflow $
2871 "I was partway through parsing an expression when I got stuck on this arrow:"
2873 D.stack
2874 [ "Arrows should only appear in `case` expressions and anonymous functions.\n\
2875 \Maybe it was supposed to be a > sign instead?"
2876 , D.toSimpleNote $
2877 "The syntax for anonymous functions is (\\x -> x + 1) so the arguments all appear\
2878 \ after the backslash and before the arrow. Maybe a backslash is missing earlier?"
2882 BadEquals ->
2883 let
2884 region = toRegion row col
2885 in
2886 Report.Report "UNEXPECTED EQUALS" region [] $
2887 Code.toSnippet source region Nothing
2889 D.reflow $
2890 "I was not expecting to see this equals sign:"
2892 D.stack
2894 D.reflow "Maybe you want == instead? To check if two values are equal?"
2896 D.toSimpleNote $
2897 if isWithin NRecord context then
2898 "Records look like { x = 3, y = 4 } with the equals sign right\
2899 \ after the field name. So maybe you forgot a comma?"
2900 else
2901 case getDefName context of
2902 Nothing ->
2903 "I may be getting confused by your indentation. I need all definitions to be indented\
2904 \ exactly the same amount, so if this is meant to be a new definition, it may have too\
2905 \ many spaces in front of it."
2907 Just name ->
2908 "I may be getting confused by your indentation. I think I am still parsing the `"
2909 ++ Name.toChars name ++ "` definition. Is this supposed to be part of a definition\
2910 \ after that? If so, the problem may be a bit before the equals sign. I need all\
2911 \ definitions to be indented exactly the same amount, so the problem may be that\
2912 \ this new definition has too many spaces in front of it."
2916 BadHasType ->
2917 let
2918 region = toRegion row col
2919 in
2920 Report.Report "UNEXPECTED SYMBOL" region [] $
2921 Code.toSnippet source region Nothing $
2923 D.reflow $
2924 "I was not expecting to run into the \"has type\" symbol here:"
2926 case getDefName context of
2927 Nothing ->
2928 D.fillSep
2929 ["Maybe","you","want",D.green "::","instead?"
2930 ,"To","put","something","on","the","front","of","a","list?"
2933 Just name ->
2934 D.stack
2936 D.fillSep
2937 ["Maybe","you","want",D.green "::","instead?"
2938 ,"To","put","something","on","the","front","of","a","list?"
2940 , D.toSimpleNote $
2941 "The single colon is reserved for type annotations and record types, but I think\
2942 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2944 D.toSimpleNote $
2945 "I may be getting confused by your indentation. Is this supposed to be part of\
2946 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2947 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2948 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2949 \ this new definition is indented a bit too much."
2955-- CASE
2958toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2959toLetReport source context let_ startRow startCol =
2960 case let_ of
2961 LetSpace space row col ->
2962 toSpaceReport source space row col
2964 LetIn row col ->
2965 let
2966 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2967 region = toRegion row col
2968 in
2969 Report.Report "LET PROBLEM" region [] $
2970 Code.toSnippet source surroundings (Just region)
2972 D.reflow $
2973 "I was partway through parsing a `let` expression, but I got stuck here:"
2975 D.stack
2976 [ D.fillSep $
2977 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2978 ,"keyword","next.","Is","there","a","typo?"
2980 , D.toSimpleNote $
2981 "This can also happen if you are trying to define another value within the `let` but\
2982 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2983 \ spaces before it. They should line up exactly!"
2987 LetDefAlignment _ row col ->
2988 let
2989 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2990 region = toRegion row col
2991 in
2992 Report.Report "LET PROBLEM" region [] $
2993 Code.toSnippet source surroundings (Just region)
2995 D.reflow $
2996 "I was partway through parsing a `let` expression, but I got stuck here:"
2998 D.stack
2999 [ D.fillSep $
3000 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
3001 ,"keyword","next.","Is","there","a","typo?"
3003 , D.toSimpleNote $
3004 "This can also happen if you are trying to define another value within the `let` but\
3005 \ it is not indented enough. Make sure each definition has exactly the same amount of\
3006 \ spaces before it. They should line up exactly!"
3010 LetDefName row col ->
3011 case Code.whatIsNext source row col of
3012 Code.Keyword keyword ->
3013 let
3014 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3015 region = toKeywordRegion row col keyword
3016 in
3017 Report.Report "RESERVED WORD" region [] $
3018 Code.toSnippet source surroundings (Just region)
3020 D.reflow $
3021 "I was partway through parsing a `let` expression, but I got stuck here:"
3023 D.reflow $
3024 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
3025 \ it is a reserved word! Try using a different name instead."
3028 _ ->
3029 toUnfinishLetReport source row col startRow startCol $
3030 D.reflow $
3031 "I was expecting the name of a definition next."
3033 LetDef name def row col ->
3034 toLetDefReport source name def row col
3036 LetDestruct destruct row col ->
3037 toLetDestructReport source destruct row col
3039 LetBody expr row col ->
3040 toExprReport source context expr row col
3042 LetIndentDef row col ->
3043 toUnfinishLetReport source row col startRow startCol $
3044 D.reflow $
3045 "I was expecting a value to be defined here."
3047 LetIndentIn row col ->
3048 toUnfinishLetReport source row col startRow startCol $
3049 D.fillSep $
3050 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
3051 ,"Or","maybe","more","of","that","expression?"
3054 LetIndentBody row col ->
3055 toUnfinishLetReport source row col startRow startCol $
3056 D.reflow $
3057 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
3060toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3061toUnfinishLetReport source row col startRow startCol message =
3062 let
3063 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3064 region = toRegion row col
3065 in
3066 Report.Report "UNFINISHED LET" region [] $
3067 Code.toSnippet source surroundings (Just region)
3069 D.reflow $
3070 "I was partway through parsing a `let` expression, but I got stuck here:"
3072 D.stack
3073 [ message
3074 , D.toSimpleNote $
3075 "Here is an example with a valid `let` expression for reference:"
3076 , D.vcat $
3077 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
3078 , D.indent 2 $ D.fillSep [D.cyan "let"]
3079 , D.indent 4 $ D.fillSep ["fullName","="]
3080 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
3081 , D.indent 2 $ D.fillSep [D.cyan "in"]
3082 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
3084 , D.reflow $
3085 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
3086 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
3087 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
3088 \ indented a bit more than that. That is important!"
3093toLetDefReport :: Code.Source -> Name.Name -> Def -> Row -> Col -> Report.Report
3094toLetDefReport source name def startRow startCol =
3095 case def of
3096 DefSpace space row col ->
3097 toSpaceReport source space row col
3099 DefType tipe row col ->
3100 toTypeReport source (TC_Annotation name) tipe row col
3102 DefNameRepeat row col ->
3103 let
3104 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3105 region = toRegion row col
3106 in
3107 Report.Report "EXPECTING DEFINITION" region [] $
3108 Code.toSnippet source surroundings (Just region)
3110 D.reflow $
3111 "I just saw the type annotation for `" ++ Name.toChars name
3112 ++ "` so I was expecting to see its definition here:"
3114 D.stack
3115 [ D.reflow $
3116 "Type annotations always appear directly above the relevant\
3117 \ definition, without anything else in between."
3118 , defNote
3122 DefNameMatch defName row col ->
3123 let
3124 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3125 region = toRegion row col
3126 in
3127 Report.Report "NAME MISMATCH" region [] $
3128 Code.toSnippet source surroundings (Just region)
3130 D.reflow $
3131 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
3133 D.stack
3134 [ D.reflow $
3135 "These names do not match! Is there a typo?"
3136 , D.indent 4 $ D.fillSep $
3137 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
3141 DefArg pattern row col ->
3142 toPatternReport source PArg pattern row col
3144 DefEquals row col ->
3145 case Code.whatIsNext source row col of
3146 Code.Keyword keyword ->
3147 let
3148 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3149 region = toKeywordRegion row col keyword
3150 in
3151 Report.Report "RESERVED WORD" region [] $
3152 Code.toSnippet source surroundings (Just region)
3154 D.fillSep
3155 ["The","name"
3156 ,"`" <> D.cyan (D.fromChars keyword) <> "`"
3157 ,"is","reserved","in","Elm,","so","it","cannot"
3158 ,"be","used","as","an","argument","here:"
3161 D.stack
3162 [ D.reflow $
3163 "Try renaming it to something else."
3164 , case keyword of
3165 "as" ->
3166 D.toFancyNote
3167 ["This","keyword","is","reserved","for","pattern","matches","like"
3168 ,"((x,y)",D.cyan "as","point)","where","you","want","to","name","a","tuple","and"
3169 ,"the","values","it","contains."
3172 _ ->
3173 D.toSimpleNote $
3174 "The `" ++ keyword ++ "` keyword has a special meaning in Elm, so it can only be used in certain situations."
3178 Code.Operator "->" ->
3179 let
3180 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3181 region = toWiderRegion row col 2
3182 in
3183 Report.Report "MISSING COLON?" region [] $
3184 Code.toSnippet source surroundings (Just region)
3186 D.reflow $
3187 "I was not expecting to see an arrow here:"
3189 D.stack
3190 [ D.fillSep
3191 ["This","usually","means","a",D.green ":","is","missing","a","bit","earlier","in"
3192 ,"a","type","annotation.","It","could","be","something","else","though,","so"
3193 ,"here","is","a","valid","definition","for","reference:"
3195 , D.vcat
3196 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3197 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3198 , D.indent 6 $ D.fillSep ["x","+","y"]
3200 , D.reflow $
3201 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3205 Code.Operator op ->
3206 let
3207 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3208 region = toKeywordRegion row col op
3209 in
3210 Report.Report "UNEXPECTED SYMBOL" region [] $
3211 Code.toSnippet source surroundings (Just region)
3213 D.reflow $
3214 "I was not expecting to see this symbol here:"
3216 D.stack
3217 [ D.reflow $
3218 "I am not sure what is going wrong exactly, so here is a valid\
3219 \ definition (with an optional type annotation) for reference:"
3220 , D.vcat
3221 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3222 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3223 , D.indent 6 $ D.fillSep ["x","+","y"]
3225 , D.reflow $
3226 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
3230 _ ->
3231 let
3232 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3233 region = toRegion row col
3234 in
3235 Report.Report "PROBLEM IN DEFINITION" region [] $
3236 Code.toSnippet source surroundings (Just region)
3238 D.reflow $
3239 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3241 D.stack
3242 [ D.reflow $
3243 "I am not sure what is going wrong exactly, so here is a valid\
3244 \ definition (with an optional type annotation) for reference:"
3245 , D.vcat
3246 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3247 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3248 , D.indent 4 $ D.fillSep ["x","+","y"]
3250 , D.reflow $
3251 "Try to use that format!"
3255 DefBody expr row col ->
3256 toExprReport source (InDef name startRow startCol) expr row col
3258 DefIndentEquals row col ->
3259 let
3260 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3261 region = toRegion row col
3262 in
3263 Report.Report "UNFINISHED DEFINITION" region [] $
3264 Code.toSnippet source surroundings (Just region)
3266 D.reflow $
3267 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3269 D.stack
3270 [ D.reflow $
3271 "I was expecting to see an argument or an equals sign next."
3272 , defNote
3276 DefIndentType row col ->
3277 let
3278 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3279 region = toRegion row col
3280 in
3281 Report.Report "UNFINISHED DEFINITION" region [] $
3282 Code.toSnippet source surroundings (Just region)
3284 D.reflow $
3285 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
3287 D.stack
3288 [ D.reflow $
3289 "I just saw a colon, so I am expecting to see a type next."
3290 , defNote
3294 DefIndentBody 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 the `" ++ Name.toChars name ++ "` definition:"
3305 D.stack
3306 [ D.reflow $
3307 "I was expecting to see an expression next. What is it equal to?"
3308 , declDefNote
3312 DefAlignment indent row col ->
3313 let
3314 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3315 region = toRegion row col
3316 offset = indent - col
3317 in
3318 Report.Report "PROBLEM IN DEFINITION" region [] $
3319 Code.toSnippet source surroundings (Just region)
3321 D.reflow $
3322 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3324 D.reflow $
3325 "I just saw a type annotation indented " ++ show indent ++ " spaces, so I was\
3326 \ expecting to see the corresponding definition next with the exact same amount\
3327 \ of indentation. It looks like this line needs "
3328 ++ show offset ++ " more " ++ (if offset == 1 then "space" else "spaces") ++ "?"
3333defNote :: D.Doc
3334defNote =
3335 D.stack
3336 [ D.reflow $
3337 "Here is a valid definition (with a type annotation) for reference:"
3338 , D.vcat
3339 [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3340 , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3341 , D.indent 6 $ D.fillSep ["x","+","y"]
3343 , D.reflow $
3344 "The top line (called a \"type annotation\") is optional. You can leave it off\
3345 \ if you want. As you get more comfortable with Elm and as your project grows,\
3346 \ it becomes more and more valuable to add them though! They work great as\
3347 \ compiler-verified documentation, and they often improve error messages!"
3351toLetDestructReport :: Code.Source -> Destruct -> Row -> Col -> Report.Report
3352toLetDestructReport source destruct startRow startCol =
3353 case destruct of
3354 DestructSpace space row col ->
3355 toSpaceReport source space row col
3357 DestructPattern pattern row col ->
3358 toPatternReport source PLet pattern row col
3360 DestructEquals row col ->
3361 let
3362 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3363 region = toRegion row col
3364 in
3365 Report.Report "PROBLEM IN DEFINITION" region [] $
3366 Code.toSnippet source surroundings (Just region)
3368 D.reflow $
3369 "I got stuck trying to parse this definition:"
3371 case Code.whatIsNext source row col of
3372 Code.Operator ":" ->
3373 D.stack
3374 [ D.reflow $
3375 "I was expecting to see an equals sign next, followed by an expression\
3376 \ telling me what to compute."
3377 , D.toSimpleNote $
3378 "It looks like you may be trying to write a type annotation? It is not\
3379 \ possible to add type annotations on destructuring definitions like this.\
3380 \ You can assign a name to the overall structure, put a type annotation on\
3381 \ that, and then destructure separately though."
3384 _ ->
3385 D.reflow $
3386 "I was expecting to see an equals sign next, followed by an expression\
3387 \ telling me what to compute."
3390 DestructBody expr row col ->
3391 toExprReport source (InDestruct startRow startCol) expr row col
3393 DestructIndentEquals row col ->
3394 let
3395 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3396 region = toRegion row col
3397 in
3398 Report.Report "UNFINISHED DEFINITION" region [] $
3399 Code.toSnippet source surroundings (Just region)
3401 D.reflow $
3402 "I got stuck trying to parse this definition:"
3404 D.reflow $
3405 "I was expecting to see an equals sign next, followed by an expression\
3406 \ telling me what to compute."
3409 DestructIndentBody row col ->
3410 let
3411 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3412 region = toRegion row col
3413 in
3414 Report.Report "UNFINISHED DEFINITION" region [] $
3415 Code.toSnippet source surroundings (Just region)
3417 D.reflow $
3418 "I got stuck while parsing this definition:"
3420 D.reflow $
3421 "I was expecting to see an expression next. What is it equal to?"
3426-- CASE
3429toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
3430toCaseReport source context case_ startRow startCol =
3431 case case_ of
3432 CaseSpace space row col ->
3433 toSpaceReport source space row col
3435 CaseOf row col ->
3436 toUnfinishCaseReport source row col startRow startCol $
3437 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3439 CasePattern pattern row col ->
3440 toPatternReport source PCase pattern row col
3442 CaseArrow row col ->
3443 case Code.whatIsNext source row col of
3444 Code.Keyword keyword ->
3445 let
3446 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3447 region = toKeywordRegion row col keyword
3448 in
3449 Report.Report "RESERVED WORD" region [] $
3450 Code.toSnippet source surroundings (Just region)
3452 D.reflow $
3453 "I am partway through parsing a `case` expression, but I got stuck here:"
3455 D.reflow $
3456 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
3457 \ patterns, but it is a reserved word. Try using a different name?"
3460 Code.Operator ":" ->
3461 let
3462 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3463 region = toRegion row col
3464 in
3465 Report.Report "UNEXPECTED OPERATOR" region [] $
3466 Code.toSnippet source surroundings (Just region)
3468 D.reflow $
3469 "I am partway through parsing a `case` expression, but I got stuck here:"
3471 D.fillSep $
3472 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
3473 ,"For","pattern","matching","on","lists?"
3477 Code.Operator "=" ->
3478 let
3479 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3480 region = toRegion row col
3481 in
3482 Report.Report "UNEXPECTED OPERATOR" region [] $
3483 Code.toSnippet source surroundings (Just region)
3485 D.reflow $
3486 "I am partway through parsing a `case` expression, but I got stuck here:"
3488 D.fillSep $
3489 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
3493 _ ->
3494 let
3495 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3496 region = toRegion row col
3497 in
3498 Report.Report "MISSING ARROW" region [] $
3499 Code.toSnippet source surroundings (Just region)
3501 D.reflow $
3502 "I am partway through parsing a `case` expression, but I got stuck here:"
3504 D.stack
3505 [ D.reflow "I was expecting to see an arrow next."
3506 , noteForCaseIndentError
3510 CaseExpr expr row col ->
3511 toExprReport source (InNode NCase startRow startCol context) expr row col
3513 CaseBranch expr row col ->
3514 toExprReport source (InNode NBranch startRow startCol context) expr row col
3516 CaseIndentOf row col ->
3517 toUnfinishCaseReport source row col startRow startCol $
3518 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
3520 CaseIndentExpr row col ->
3521 toUnfinishCaseReport source row col startRow startCol $
3522 D.reflow "I was expecting to see a expression next."
3524 CaseIndentPattern row col ->
3525 toUnfinishCaseReport source row col startRow startCol $
3526 D.reflow "I was expecting to see a pattern next."
3528 CaseIndentArrow row col ->
3529 toUnfinishCaseReport source row col startRow startCol $
3530 D.fillSep
3531 ["I","just","saw","a","pattern,","so","I","was","expecting"
3532 ,"to","see","a",D.dullyellow "->","next."
3535 CaseIndentBranch row col ->
3536 toUnfinishCaseReport source row col startRow startCol $
3537 D.reflow $
3538 "I was expecting to see an expression next. What should I do when\
3539 \ I run into this particular pattern?"
3541 CasePatternAlignment indent row col ->
3542 toUnfinishCaseReport source row col startRow startCol $
3543 D.reflow $
3544 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
3547toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3548toUnfinishCaseReport source row col startRow startCol message =
3549 let
3550 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3551 region = toRegion row col
3552 in
3553 Report.Report "UNFINISHED CASE" region [] $
3554 Code.toSnippet source surroundings (Just region)
3556 D.reflow $
3557 "I was partway through parsing a `case` expression, but I got stuck here:"
3559 D.stack
3560 [ message
3561 , noteForCaseError
3566noteForCaseError :: D.Doc
3567noteForCaseError =
3568 D.stack
3569 [ D.toSimpleNote $
3570 "Here is an example of a valid `case` expression for reference."
3571 , D.vcat $
3572 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3573 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3574 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3575 , ""
3576 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3577 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3579 , D.reflow $
3580 "Notice the indentation. Each pattern is aligned, and each branch is indented\
3581 \ a bit more than the corresponding pattern. That is important!"
3585noteForCaseIndentError :: D.Doc
3586noteForCaseIndentError =
3587 D.stack
3588 [ D.toSimpleNote $
3589 "Sometimes I get confused by indentation, so try to make your `case` look\
3590 \ something like this:"
3591 , D.vcat $
3592 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
3593 , D.indent 6 $ D.fillSep [D.blue "Just","width","->"]
3594 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
3595 , ""
3596 , D.indent 6 $ D.fillSep [D.blue "Nothing","->"]
3597 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
3599 , D.reflow $
3600 "Notice the indentation! Patterns are aligned with each other. Same indentation.\
3601 \ The expressions after each arrow are all indented a bit more than the patterns.\
3602 \ That is important!"
3607-- IF
3610toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
3611toIfReport source context if_ startRow startCol =
3612 case if_ of
3613 IfSpace space row col ->
3614 toSpaceReport source space row col
3616 IfThen row col ->
3617 let
3618 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3619 region = toRegion row col
3620 in
3621 Report.Report "UNFINISHED IF" region [] $
3622 Code.toSnippet source surroundings (Just region)
3624 D.reflow $
3625 "I was expecting to see more of this `if` expression, but I got stuck here:"
3627 D.fillSep $
3628 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3632 IfElse row col ->
3633 let
3634 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3635 region = toRegion row col
3636 in
3637 Report.Report "UNFINISHED IF" region [] $
3638 Code.toSnippet source surroundings (Just region)
3640 D.reflow $
3641 "I was expecting to see more of this `if` expression, but I got stuck here:"
3643 D.fillSep $
3644 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
3648 IfElseBranchStart row col ->
3649 let
3650 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3651 region = toRegion row col
3652 in
3653 Report.Report "UNFINISHED IF" region [] $
3654 Code.toSnippet source surroundings (Just region)
3656 D.reflow $
3657 "I just saw the start of an `else` branch, but then I got stuck here:"
3659 D.reflow $
3660 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3663 IfCondition expr row col ->
3664 toExprReport source (InNode NCond startRow startCol context) expr row col
3666 IfThenBranch expr row col ->
3667 toExprReport source (InNode NThen startRow startCol context) expr row col
3669 IfElseBranch expr row col ->
3670 toExprReport source (InNode NElse startRow startCol context) expr row col
3672 IfIndentCondition row col ->
3673 let
3674 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3675 region = toRegion row col
3676 in
3677 Report.Report "UNFINISHED IF" region [] $
3678 Code.toSnippet source surroundings (Just region)
3680 D.reflow $
3681 "I was expecting to see more of this `if` expression, but I got stuck here:"
3683 D.stack
3684 [ D.fillSep $
3685 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3686 ,"that","evaluates","to","True","or","False."
3688 , D.toSimpleNote $
3689 "I can be confused by indentation. Maybe something is not indented enough?"
3693 IfIndentThen row col ->
3694 let
3695 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3696 region = toRegion row col
3697 in
3698 Report.Report "UNFINISHED IF" region [] $
3699 Code.toSnippet source surroundings (Just region)
3701 D.reflow $
3702 "I was expecting to see more of this `if` expression, but I got stuck here:"
3704 D.stack
3705 [ D.fillSep $
3706 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3708 , D.toSimpleNote $
3709 "I can be confused by indentation. Maybe something is not indented enough?"
3713 IfIndentThenBranch row col ->
3714 let
3715 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3716 region = toRegion row col
3717 in
3718 Report.Report "UNFINISHED IF" region [] $
3719 Code.toSnippet source surroundings (Just region)
3721 D.reflow $
3722 "I got stuck after the start of this `then` branch:"
3724 D.stack
3725 [ D.reflow $
3726 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3727 , D.toSimpleNote $
3728 "I can be confused by indentation, so if the `then` branch is already\
3729 \ present, it may not be indented enough for me to recognize it."
3733 IfIndentElseBranch row col ->
3734 let
3735 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3736 region = toRegion row col
3737 in
3738 Report.Report "UNFINISHED IF" region [] $
3739 Code.toSnippet source surroundings (Just region)
3741 D.reflow $
3742 "I got stuck after the start of this `else` branch:"
3744 D.stack
3745 [ D.reflow $
3746 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3747 , D.toSimpleNote $
3748 "I can be confused by indentation, so if the `else` branch is already\
3749 \ present, it may not be indented enough for me to recognize it."
3753 IfIndentElse row col ->
3754 case Code.nextLineStartsWithKeyword "else" source row of
3755 Just (elseRow, elseCol) ->
3756 let
3757 surroundings = A.Region (A.Position startRow startCol) (A.Position elseRow elseCol)
3758 region = toWiderRegion elseRow elseCol 4
3759 in
3760 Report.Report "WEIRD ELSE BRANCH" region [] $
3761 Code.toSnippet source surroundings (Just region)
3763 D.reflow $
3764 "I was partway through an `if` expression when I got stuck here:"
3766 D.fillSep $
3767 ["I","think","this",D.cyan "else","keyword","needs","to","be","indented","more."
3768 ,"Try","adding","some","spaces","before","it."
3772 Nothing ->
3773 let
3774 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3775 region = toRegion row col
3776 in
3777 Report.Report "UNFINISHED IF" region [] $
3778 Code.toSnippet source surroundings (Just region)
3780 D.reflow $
3781 "I was expecting to see an `else` branch after this:"
3783 D.stack
3784 [ D.fillSep
3785 ["I","know","what","to","do","when","the","condition","is","True,"
3786 ,"but","what","happens","when","it","is","False?"
3787 ,"Add","an",D.cyan "else","branch","to","handle","that","scenario!"
3794-- RECORD
3797toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3798toRecordReport source context record startRow startCol =
3799 case record of
3800 RecordOpen row col ->
3801 case Code.whatIsNext source row col of
3802 Code.Keyword keyword ->
3803 let
3804 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3805 region = toKeywordRegion row col keyword
3806 in
3807 Report.Report "RESERVED WORD" region [] $
3808 Code.toSnippet source surroundings (Just region)
3810 D.reflow $
3811 "I just started parsing a record, but I got stuck on this field name:"
3813 D.reflow $
3814 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3815 \ that is a reserved word. Try using a different name!"
3818 _ ->
3819 let
3820 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3821 region = toRegion row col
3822 in
3823 Report.Report "UNFINISHED RECORD" region [] $
3824 Code.toSnippet source surroundings (Just region)
3826 D.reflow $
3827 "I just started parsing a record, but I got stuck here:"
3829 D.fillSep
3830 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3831 ,"so","I","was","expecting","to","see","a","field","name","next."
3835 RecordEnd row col ->
3836 let
3837 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3838 region = toRegion row col
3839 in
3840 Report.Report "UNFINISHED RECORD" region [] $
3841 Code.toSnippet source surroundings (Just region)
3843 D.reflow $
3844 "I am partway through parsing a record, but I got stuck here:"
3846 D.stack
3847 [ D.fillSep
3848 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3849 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3851 , D.toSimpleNote $
3852 "When I get stuck like this, it usually means that there is a missing parenthesis\
3853 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3857 RecordField row col ->
3858 case Code.whatIsNext source row col of
3859 Code.Keyword keyword ->
3860 let
3861 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3862 region = toKeywordRegion row col keyword
3863 in
3864 Report.Report "RESERVED WORD" region [] $
3865 Code.toSnippet source surroundings (Just region)
3867 D.reflow $
3868 "I am partway through parsing a record, but I got stuck on this field name:"
3870 D.reflow $
3871 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3872 \ that is a reserved word. Try using a different name!"
3875 Code.Other (Just ',') ->
3876 let
3877 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3878 region = toRegion row col
3879 in
3880 Report.Report "EXTRA COMMA" region [] $
3881 Code.toSnippet source surroundings (Just region)
3883 D.reflow $
3884 "I am partway through parsing a record, but I got stuck here:"
3886 D.stack
3887 [ D.reflow $
3888 "I am seeing two commas in a row. This is the second one!"
3889 , D.reflow $
3890 "Just delete one of the commas and you should be all set!"
3891 , noteForRecordError
3895 Code.Close _ '}' ->
3896 let
3897 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3898 region = toRegion row col
3899 in
3900 Report.Report "EXTRA COMMA" region [] $
3901 Code.toSnippet source surroundings (Just region)
3903 D.reflow $
3904 "I am partway through parsing a record, but I got stuck here:"
3906 D.stack
3907 [ D.reflow $
3908 "Trailing commas are not allowed in records. Try deleting the comma that appears\
3909 \ before this closing curly brace."
3910 , noteForRecordError
3914 _ ->
3915 let
3916 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3917 region = toRegion row col
3918 in
3919 Report.Report "PROBLEM IN RECORD" region [] $
3920 Code.toSnippet source surroundings (Just region)
3922 D.reflow $
3923 "I am partway through parsing a record, but I got stuck here:"
3925 D.stack
3926 [ D.fillSep
3927 ["I","was","expecting","to","see","another","record","field","defined","next,"
3928 ,"so","I","am","looking","for","a","lower-case","name","like"
3929 ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
3931 , noteForRecordError
3935 RecordEquals row col ->
3936 let
3937 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3938 region = toRegion row col
3939 in
3940 Report.Report "UNFINISHED RECORD" region [] $
3941 Code.toSnippet source surroundings (Just region)
3943 D.reflow $
3944 "I am partway through parsing a record, but I got stuck here:"
3946 D.stack
3947 [ D.fillSep $
3948 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3949 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3951 , noteForRecordError
3955 RecordExpr expr row col ->
3956 toExprReport source (InNode NRecord startRow startCol context) expr row col
3958 RecordSpace space row col ->
3959 toSpaceReport source space row col
3961 RecordIndentOpen row col ->
3962 let
3963 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3964 region = toRegion row col
3965 in
3966 Report.Report "UNFINISHED RECORD" region [] $
3967 Code.toSnippet source surroundings (Just region)
3969 D.reflow $
3970 "I just saw the opening curly brace of a record, but then I got stuck here:"
3972 addNoteForRecordIndentError $
3973 D.fillSep $
3974 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3975 ,"Try","defining","some","fields","of","your","own?"
3979 RecordIndentEnd row col ->
3980 case Code.nextLineStartsWithCloseCurly source row of
3981 Just (curlyRow, curlyCol) ->
3982 let
3983 surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
3984 region = toRegion curlyRow curlyCol
3985 in
3986 Report.Report "NEED MORE INDENTATION" region [] $
3987 Code.toSnippet source surroundings (Just region)
3989 D.reflow $
3990 "I was partway through parsing a record, but I got stuck here:"
3992 D.stack
3993 [ D.reflow $
3994 "I need this curly brace to be indented more. Try adding some spaces before it!"
3995 , noteForRecordError
3999 Nothing ->
4000 let
4001 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4002 region = toRegion row col
4003 in
4004 Report.Report "UNFINISHED RECORD" region [] $
4005 Code.toSnippet source surroundings (Just region)
4007 D.reflow $
4008 "I was partway through parsing a record, but I got stuck here:"
4010 addNoteForRecordIndentError $
4011 D.fillSep $
4012 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4013 ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
4017 RecordIndentField row col ->
4018 let
4019 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4020 region = toRegion row col
4021 in
4022 Report.Report "UNFINISHED RECORD" region [] $
4023 Code.toSnippet source surroundings (Just region)
4025 D.reflow $
4026 "I am partway through parsing a record, but I got stuck after that last comma:"
4028 D.stack
4029 [ D.reflow $
4030 "Trailing commas are not allowed in records, so the fix may be to\
4031 \ delete that last comma? Or maybe you were in the middle of defining\
4032 \ an additional field?"
4033 , noteForRecordError
4037 RecordIndentEquals row col ->
4038 let
4039 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4040 region = toRegion row col
4041 in
4042 Report.Report "UNFINISHED RECORD" region [] $
4043 Code.toSnippet source surroundings (Just region)
4045 D.reflow $
4046 "I am partway through parsing a record. I just saw a record\
4047 \ field, so I was expecting to see an equals sign next:"
4049 addNoteForRecordIndentError $
4050 D.fillSep $
4051 ["Try","putting","an",D.green "=","followed","by","an","expression?"
4055 RecordIndentExpr row col ->
4056 let
4057 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4058 region = toRegion row col
4059 in
4060 Report.Report "UNFINISHED RECORD" region [] $
4061 Code.toSnippet source surroundings (Just region)
4063 D.reflow $
4064 "I am partway through parsing a record, and I was expecting to run into an expression next:"
4066 addNoteForRecordIndentError $
4067 D.fillSep $
4068 ["Try","putting","something","like"
4069 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
4074noteForRecordError :: D.Doc
4075noteForRecordError =
4076 D.stack $
4077 [ D.toSimpleNote
4078 "If you are trying to define a record across multiple lines, I recommend using this format:"
4079 , D.indent 4 $ D.vcat $
4080 [ "{ name = \"Alice\""
4081 , ", age = 42"
4082 , ", height = 1.75"
4083 , "}"
4085 , D.reflow $
4086 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4087 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4088 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4092addNoteForRecordIndentError :: D.Doc -> D.Doc
4093addNoteForRecordIndentError normalRecommendation =
4094 D.stack $
4095 normalRecommendation
4097 [ D.toSimpleNote
4098 "I may be confused by indentation. For example, if you are trying to define\
4099 \ a record across multiple lines, I recommend using this format:"
4100 , D.indent 4 $ D.vcat $
4101 [ "{ name = \"Alice\""
4102 , ", age = 42"
4103 , ", height = 1.75"
4104 , "}"
4106 , D.reflow $
4107 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4108 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4109 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4114-- TUPLE
4117toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
4118toTupleReport source context tuple startRow startCol =
4119 case tuple of
4120 TupleExpr expr row col ->
4121 toExprReport source (InNode NParens startRow startCol context) expr row col
4123 TupleSpace space row col ->
4124 toSpaceReport source space row col
4126 TupleEnd row col ->
4127 let
4128 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4129 region = toRegion row col
4130 in
4131 Report.Report "UNFINISHED PARENTHESES" region [] $
4132 Code.toSnippet source surroundings (Just region)
4134 D.reflow $
4135 "I was expecting to see a closing parentheses next, but I got stuck here:"
4137 D.stack
4138 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4139 , D.toSimpleNote $
4140 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4141 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4142 \ or missing brackets) that is confusing me."
4146 TupleOperatorClose row col ->
4147 let
4148 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4149 region = toRegion row col
4150 in
4151 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
4152 Code.toSnippet source surroundings (Just region)
4154 D.reflow "I was expecting a closing parenthesis here:"
4156 D.stack
4157 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4158 , D.toSimpleNote $
4159 "I think I am parsing an operator function right now, so I am expecting to see\
4160 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
4161 \ no extra spaces."
4165 TupleOperatorReserved operator row col ->
4166 let
4167 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4168 region = toRegion row col
4169 in
4170 Report.Report "UNEXPECTED SYMBOL" region [] $
4171 Code.toSnippet source surroundings (Just region)
4173 D.reflow $
4174 "I ran into an unexpected symbol here:"
4176 D.fillSep $
4177 case operator of
4178 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
4179 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
4180 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
4181 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
4182 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
4185 TupleIndentExpr1 row col ->
4186 let
4187 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4188 region = toRegion row col
4189 in
4190 Report.Report "UNFINISHED PARENTHESES" region [] $
4191 Code.toSnippet source surroundings (Just region)
4193 D.reflow $
4194 "I just saw an open parenthesis, so I was expecting to see an expression next."
4196 D.stack
4197 [ D.fillSep $
4198 ["Something","like",D.dullyellow "(4 + 5)","or"
4199 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
4200 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
4202 , D.toSimpleNote $
4203 "I can get confused by indentation in cases like this, so\
4204 \ maybe you have an expression but it is not indented enough?"
4208 TupleIndentExprN row col ->
4209 let
4210 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4211 region = toRegion row col
4212 in
4213 Report.Report "UNFINISHED TUPLE" region [] $
4214 Code.toSnippet source surroundings (Just region)
4216 D.reflow $
4217 "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."
4219 D.stack
4220 [ D.fillSep $
4221 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
4222 ,D.dullyellow "(\"Tom\",42)" <> ","
4223 ,"so","I","think","there","is","an","expression","missing","here?"
4225 , D.toSimpleNote $
4226 "I can get confused by indentation in cases like this, so\
4227 \ maybe you have an expression but it is not indented enough?"
4231 TupleIndentEnd row col ->
4232 let
4233 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4234 region = toRegion row col
4235 in
4236 Report.Report "UNFINISHED PARENTHESES" region [] $
4237 Code.toSnippet source surroundings (Just region)
4239 D.reflow $
4240 "I was expecting to see a closing parenthesis next:"
4242 D.stack
4243 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4244 , D.toSimpleNote $
4245 "I can get confused by indentation in cases like this, so\
4246 \ maybe you have a closing parenthesis but it is not indented enough?"
4251toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
4252toListReport source context list startRow startCol =
4253 case list of
4254 ListSpace space row col ->
4255 toSpaceReport source space row col
4257 ListOpen row col ->
4258 let
4259 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4260 region = toRegion row col
4261 in
4262 Report.Report "UNFINISHED LIST" region [] $
4263 Code.toSnippet source surroundings (Just region)
4265 D.reflow $
4266 "I am partway through parsing a list, but I got stuck here:"
4268 D.stack
4269 [ D.fillSep
4270 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4271 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4273 , D.toSimpleNote $
4274 "When I get stuck like this, it usually means that there is a missing parenthesis\
4275 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4279 ListExpr expr row col ->
4280 case expr of
4281 Start r c ->
4282 let
4283 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
4284 region = toRegion r c
4285 in
4286 Report.Report "UNFINISHED LIST" region [] $
4287 Code.toSnippet source surroundings (Just region)
4289 D.reflow $
4290 "I was expecting to see another list entry after that last comma:"
4292 D.stack
4293 [ D.reflow $
4294 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4295 , D.toSimpleNote
4296 "I recommend using the following format for lists that span multiple lines:"
4297 , D.indent 4 $ D.vcat $
4298 [ "[ \"Alice\""
4299 , ", \"Bob\""
4300 , ", \"Chuck\""
4301 , "]"
4303 , D.reflow $
4304 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4305 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4306 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4310 _ ->
4311 toExprReport source (InNode NList startRow startCol context) expr row col
4313 ListEnd row col ->
4314 let
4315 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4316 region = toRegion row col
4317 in
4318 Report.Report "UNFINISHED LIST" region [] $
4319 Code.toSnippet source surroundings (Just region)
4321 D.reflow $
4322 "I am partway through parsing a list, but I got stuck here:"
4324 D.stack
4325 [ D.fillSep
4326 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
4327 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
4329 , D.toSimpleNote $
4330 "When I get stuck like this, it usually means that there is a missing parenthesis\
4331 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4335 ListIndentOpen row col ->
4336 let
4337 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4338 region = toRegion row col
4339 in
4340 Report.Report "UNFINISHED LIST" region [] $
4341 Code.toSnippet source surroundings (Just region)
4343 D.reflow $
4344 "I cannot find the end of this list:"
4346 D.stack
4347 [ D.fillSep $
4348 ["You","could","change","it","to","something","like"
4349 ,D.dullyellow "[3,4,5]"
4350 ,"or","even","just"
4351 ,D.dullyellow "[]" <> "."
4352 ,"Anything","where","there","is","an","open","and","close","square","brace,"
4353 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
4355 , D.toSimpleNote
4356 "I may be confused by indentation. For example, if you are trying to define\
4357 \ a list across multiple lines, I recommend using this format:"
4358 , D.indent 4 $ D.vcat $
4359 [ "[ \"Alice\""
4360 , ", \"Bob\""
4361 , ", \"Chuck\""
4362 , "]"
4364 , D.reflow $
4365 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4366 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4367 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4371 ListIndentEnd row col ->
4372 let
4373 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4374 region = toRegion row col
4375 in
4376 Report.Report "UNFINISHED LIST" region [] $
4377 Code.toSnippet source surroundings (Just region)
4379 D.reflow $
4380 "I cannot find the end of this list:"
4382 D.stack
4383 [ D.fillSep $
4384 ["You","can","just","add","a","closing",D.dullyellow "]"
4385 ,"right","here,","and","I","will","be","all","set!"
4387 , D.toSimpleNote
4388 "I may be confused by indentation. For example, if you are trying to define\
4389 \ a list across multiple lines, I recommend using this format:"
4390 , D.indent 4 $ D.vcat $
4391 [ "[ \"Alice\""
4392 , ", \"Bob\""
4393 , ", \"Chuck\""
4394 , "]"
4396 , D.reflow $
4397 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4398 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4399 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4403 ListIndentExpr row col ->
4404 let
4405 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4406 region = toRegion row col
4407 in
4408 Report.Report "UNFINISHED LIST" region [] $
4409 Code.toSnippet source surroundings (Just region)
4411 D.reflow $
4412 "I was expecting to see another list entry after this comma:"
4414 D.stack
4415 [ D.reflow $
4416 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
4417 , D.toSimpleNote
4418 "I recommend using the following format for lists that span multiple lines:"
4419 , D.indent 4 $ D.vcat $
4420 [ "[ \"Alice\""
4421 , ", \"Bob\""
4422 , ", \"Chuck\""
4423 , "]"
4425 , D.reflow $
4426 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
4427 \ This style can be jarring for people coming from C-like syntax, but folks generally\
4428 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4433toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
4434toFuncReport source context func startRow startCol =
4435 case func of
4436 FuncSpace space row col ->
4437 toSpaceReport source space row col
4439 FuncArg pattern row col ->
4440 toPatternReport source PArg pattern row col
4442 FuncBody expr row col ->
4443 toExprReport source (InNode NFunc startRow startCol context) expr row col
4445 FuncArrow row col ->
4446 case Code.whatIsNext source row col of
4447 Code.Keyword keyword ->
4448 let
4449 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4450 region = toKeywordRegion row col keyword
4451 in
4452 Report.Report "RESERVED WORD" region [] $
4453 Code.toSnippet source surroundings (Just region)
4455 D.reflow $
4456 "I was parsing an anonymous function, but I got stuck here:"
4458 D.reflow $
4459 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
4460 \ it is a reserved word in this language. Try using a different argument name!"
4463 _ ->
4464 let
4465 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4466 region = toRegion row col
4467 in
4468 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4469 Code.toSnippet source surroundings (Just region)
4471 D.reflow $
4472 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4474 D.fillSep $
4475 ["The","syntax","for","anonymous","functions","is"
4476 ,D.dullyellow "(\\x -> x + 1)"
4477 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4481 FuncIndentArg row col ->
4482 let
4483 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4484 region = toRegion row col
4485 in
4486 Report.Report "MISSING ARGUMENT" region [] $
4487 Code.toSnippet source surroundings (Just region)
4489 D.reflow $
4490 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
4492 D.stack
4493 [ D.fillSep
4494 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
4495 ,"Anything","that","starts","with","a","lower","case","letter!"
4497 , D.toSimpleNote $
4498 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
4499 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
4500 \ like a better idea at the time!"
4504 FuncIndentArrow row col ->
4505 let
4506 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4507 region = toRegion row col
4508 in
4509 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4510 Code.toSnippet source surroundings (Just region)
4512 D.reflow $
4513 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
4515 D.stack
4516 [ D.fillSep $
4517 ["The","syntax","for","anonymous","functions","is"
4518 ,D.dullyellow "(\\x -> x + 1)"
4519 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
4521 , D.toSimpleNote $
4522 "It is possible that I am confused about indetation! I generally recommend\
4523 \ switching to named functions if the definition cannot fit inline nicely, so\
4524 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4525 \ the whole thing out into a named function. Things tend to be clearer that way!"
4529 FuncIndentBody row col ->
4530 let
4531 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4532 region = toRegion row col
4533 in
4534 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
4535 Code.toSnippet source surroundings (Just region)
4537 D.reflow $
4538 "I was expecting to see the body of your anonymous function next:"
4540 D.stack
4541 [ D.fillSep $
4542 ["The","syntax","for","anonymous","functions","is"
4543 ,D.dullyellow "(\\x -> x + 1)"
4544 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
4546 , D.toSimpleNote $
4547 "It is possible that I am confused about indetation! I generally recommend\
4548 \ switching to named functions if the definition cannot fit inline nicely, so\
4549 \ either (1) try to fit the whole anonymous function on one line or (2) break\
4550 \ the whole thing out into a named function. Things tend to be clearer that way!"
4556-- PATTERN
4559data PContext
4560 = PCase
4561 | PArg
4562 | PLet
4565toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
4566toPatternReport source context pattern startRow startCol =
4567 case pattern of
4568 PRecord record row col ->
4569 toPRecordReport source record row col
4571 PTuple tuple row col ->
4572 toPTupleReport source context tuple row col
4574 PList list row col ->
4575 toPListReport source context list row col
4577 PStart row col ->
4578 case Code.whatIsNext source row col of
4579 Code.Keyword keyword ->
4580 let
4581 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4582 region = toKeywordRegion row col keyword
4583 inThisThing =
4584 case context of
4585 PArg -> "as an argument"
4586 PCase -> "in this pattern"
4587 PLet -> "in this pattern"
4588 in
4589 Report.Report "RESERVED WORD" region [] $
4590 Code.toSnippet source surroundings (Just region)
4592 D.reflow $
4593 "It looks like you are trying to use `" ++ keyword ++ "` " ++ inThisThing ++ ":"
4595 D.reflow $
4596 "This is a reserved word! Try using some other name?"
4599 Code.Operator "-" ->
4600 let
4601 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4602 region = toRegion row col
4603 in
4604 Report.Report "UNEXPECTED SYMBOL" region [] $
4605 Code.toSnippet source surroundings (Just region)
4607 D.reflow $
4608 "I ran into a minus sign unexpectedly in this pattern:"
4610 D.reflow $
4611 "It is not possible to pattern match on negative numbers at this\
4612 \ time. Try using an `if` expression for that sort of thing for now."
4615 _ ->
4616 let
4617 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4618 region = toRegion row col
4619 in
4620 Report.Report "PROBLEM IN PATTERN" region [] $
4621 Code.toSnippet source surroundings (Just region)
4623 D.reflow $
4624 "I wanted to parse a pattern next, but I got stuck here:"
4626 D.fillSep $
4627 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4628 ,"I","just","know","that","I","want","a","pattern","next."
4629 ,"Something","as","simple","as"
4630 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4631 ,"would","work!"
4635 PChar char row col ->
4636 toCharReport source char row col
4638 PString string row col ->
4639 toStringReport source string row col
4641 PNumber number row col ->
4642 toNumberReport source number row col
4644 PFloat width row col ->
4645 let
4646 region = toWiderRegion row col width
4647 in
4648 Report.Report "UNEXPECTED PATTERN" region [] $
4649 Code.toSnippet source region Nothing
4651 D.reflow $
4652 "I cannot pattern match with floating point numbers:"
4654 D.fillSep $
4655 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
4656 ,"to","check","that","they","are","nearby","with","some","sort","of"
4657 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
4661 PAlias row col ->
4662 let
4663 region = toRegion row col
4664 in
4665 Report.Report "UNFINISHED PATTERN" region [] $
4666 Code.toSnippet source region Nothing $
4668 D.reflow $
4669 "I was expecting to see a variable name after the `as` keyword:"
4671 D.stack
4672 [ D.fillSep $
4673 ["The","`as`","keyword","lets","you","write","patterns","like"
4674 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4675 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4676 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4677 ,"thing","with",D.dullyellow "point" <> "."
4679 , D.reflow $
4680 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4681 \ people just want to use `as` as a variable name though. Try using a different name\
4682 \ in that case!"
4686 PWildcardNotVar name width row col ->
4687 let
4688 region = toWiderRegion row col (fromIntegral width)
4689 examples =
4690 case dropWhile (=='_') (Name.toChars name) of
4691 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
4692 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
4693 in
4694 Report.Report "UNEXPECTED NAME" region [] $
4695 Code.toSnippet source region Nothing $
4697 D.reflow $
4698 "Variable names cannot start with underscores like this:"
4700 D.fillSep $
4701 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
4702 ,"ignore","the","value,","or","you","can","have","a","name","like"
4703 ] ++ examples ++ ["to","use","the","matched","value." ]
4706 PSpace space row col ->
4707 toSpaceReport source space row col
4709 PIndentStart row col ->
4710 let
4711 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4712 region = toRegion row col
4713 in
4714 Report.Report "UNFINISHED PATTERN" region [] $
4715 Code.toSnippet source surroundings (Just region)
4717 D.reflow $
4718 "I wanted to parse a pattern next, but I got stuck here:"
4720 D.stack
4721 [ D.fillSep $
4722 ["I","am","not","sure","why","I","am","getting","stuck","exactly."
4723 ,"I","just","know","that","I","want","a","pattern","next."
4724 ,"Something","as","simple","as"
4725 ,D.dullyellow "maybeHeight","or",D.dullyellow "result"
4726 ,"would","work!"
4728 , D.toSimpleNote $
4729 "I can get confused by indentation. If you think there is a pattern next, maybe\
4730 \ it needs to be indented a bit more?"
4734 PIndentAlias row col ->
4735 let
4736 region = toRegion row col
4737 in
4738 Report.Report "UNFINISHED PATTERN" region [] $
4739 Code.toSnippet source region Nothing $
4741 D.reflow $
4742 "I was expecting to see a variable name after the `as` keyword:"
4744 D.stack
4745 [ D.fillSep $
4746 ["The","`as`","keyword","lets","you","write","patterns","like"
4747 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
4748 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
4749 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
4750 ,"thing","with",D.dullyellow "point."
4752 , D.reflow $
4753 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
4754 \ people just want to use `as` as a variable name though. Try using a different name\
4755 \ in that case!"
4760toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
4761toPRecordReport source record startRow startCol =
4762 case record of
4763 PRecordOpen row col ->
4764 toUnfinishRecordPatternReport source row col startRow startCol $
4765 D.reflow "I was expecting to see a field name next."
4767 PRecordEnd row col ->
4768 toUnfinishRecordPatternReport source row col startRow startCol $
4769 D.fillSep
4770 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4771 ,"Try","adding","a",D.dullyellow "}","here?"
4774 PRecordField row col ->
4775 case Code.whatIsNext source row col of
4776 Code.Keyword keyword ->
4777 let
4778 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4779 region = toKeywordRegion row col keyword
4780 in
4781 Report.Report "RESERVED WORD" region [] $
4782 Code.toSnippet source surroundings (Just region)
4784 D.reflow $
4785 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
4787 D.reflow $
4788 "This is a reserved word, not available for variable names. Try another name!"
4791 _ ->
4792 toUnfinishRecordPatternReport source row col startRow startCol $
4793 D.reflow "I was expecting to see a field name next."
4795 PRecordSpace space row col ->
4796 toSpaceReport source space row col
4798 PRecordIndentOpen row col ->
4799 toUnfinishRecordPatternReport source row col startRow startCol $
4800 D.reflow "I was expecting to see a field name next."
4802 PRecordIndentEnd row col ->
4803 toUnfinishRecordPatternReport source row col startRow startCol $
4804 D.fillSep
4805 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4806 ,"Try","adding","a",D.dullyellow "}","here?"
4809 PRecordIndentField row col ->
4810 toUnfinishRecordPatternReport source row col startRow startCol $
4811 D.reflow "I was expecting to see a field name next."
4814toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4815toUnfinishRecordPatternReport source row col startRow startCol message =
4816 let
4817 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4818 region = toRegion row col
4819 in
4820 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4821 Code.toSnippet source surroundings (Just region)
4823 D.reflow $
4824 "I was partway through parsing a record pattern, but I got stuck here:"
4826 D.stack
4827 [ message
4828 , D.toFancyHint $
4829 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4830 ,"where","you","list","the","field","names","you","want","to","access."
4837toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4838toPTupleReport source context tuple startRow startCol =
4839 case tuple of
4840 PTupleOpen row col ->
4841 case Code.whatIsNext source row col of
4842 Code.Keyword keyword ->
4843 let
4844 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4845 region = toKeywordRegion row col keyword
4846 in
4847 Report.Report "RESERVED WORD" region [] $
4848 Code.toSnippet source surroundings (Just region)
4850 D.reflow $
4851 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4853 D.reflow $
4854 "This is a reserved word! Try using some other name?"
4857 _ ->
4858 let
4859 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4860 region = toRegion row col
4861 in
4862 Report.Report "UNFINISHED PARENTHESES" region [] $
4863 Code.toSnippet source surroundings (Just region)
4865 D.reflow $
4866 "I just saw an open parenthesis, but I got stuck here:"
4868 D.fillSep
4869 ["I","was","expecting","to","see","a","pattern","next."
4870 ,"Maybe","it","will","end","up","being","something"
4871 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4875 PTupleEnd row col ->
4876 case Code.whatIsNext source row col of
4877 Code.Keyword keyword ->
4878 let
4879 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4880 region = toKeywordRegion row col keyword
4881 in
4882 Report.Report "RESERVED WORD" region [] $
4883 Code.toSnippet source surroundings (Just region) $
4885 D.reflow $
4886 "I ran into a reserved word in this pattern:"
4888 D.reflow $
4889 "The `" ++ keyword ++ "` keyword is reserved. Try using a different name instead!"
4892 Code.Operator op ->
4893 let
4894 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4895 region = toKeywordRegion row col op
4896 in
4897 Report.Report "UNEXPECTED SYMBOL" region [] $
4898 Code.toSnippet source surroundings (Just region) $
4900 D.reflow $
4901 "I ran into the " ++ op ++ " symbol unexpectedly in this pattern:"
4903 D.reflow $
4904 "Only the :: symbol that works in patterns. It is useful if you\
4905 \ are pattern matching on lists, trying to get the first element\
4906 \ off the front. Did you want that instead?"
4909 Code.Close term bracket ->
4910 let
4911 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4912 region = toRegion row col
4913 in
4914 Report.Report ("STRAY " ++ map Char.toUpper term) region [] $
4915 Code.toSnippet source surroundings (Just region) $
4917 D.reflow $
4918 "I ran into a an unexpected " ++ term ++ " in this pattern:"
4920 D.reflow $
4921 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
4924 _ ->
4925 let
4926 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4927 region = toRegion row col
4928 in
4929 Report.Report "UNFINISHED PARENTHESES" region [] $
4930 Code.toSnippet source surroundings (Just region) $
4932 D.reflow $
4933 "I was partway through parsing a pattern, but I got stuck here:"
4935 D.fillSep
4936 ["I","was","expecting","a","closing","parenthesis","next,","so"
4937 ,"try","adding","a",D.dullyellow ")","to","see","if","that","helps?"
4941 PTupleExpr pattern row col ->
4942 toPatternReport source context pattern row col
4944 PTupleSpace space row col ->
4945 toSpaceReport source space row col
4947 PTupleIndentEnd row col ->
4948 let
4949 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4950 region = toRegion row col
4951 in
4952 Report.Report "UNFINISHED PARENTHESES" region [] $
4953 Code.toSnippet source surroundings (Just region) $
4955 D.reflow $
4956 "I was expecting a closing parenthesis next:"
4958 D.stack
4959 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4960 , D.toSimpleNote $
4961 "I can get confused by indentation in cases like this, so\
4962 \ maybe you have a closing parenthesis but it is not indented enough?"
4966 PTupleIndentExpr1 row col ->
4967 let
4968 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4969 region = toRegion row col
4970 in
4971 Report.Report "UNFINISHED PARENTHESES" region [] $
4972 Code.toSnippet source surroundings (Just region) $
4974 D.reflow $
4975 "I just saw an open parenthesis, but then I got stuck here:"
4977 D.fillSep
4978 ["I","was","expecting","to","see","a","pattern","next."
4979 ,"Maybe","it","will","end","up","being","something"
4980 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4984 PTupleIndentExprN row col ->
4985 let
4986 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4987 region = toRegion row col
4988 in
4989 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4990 Code.toSnippet source surroundings (Just region) $
4992 D.reflow $
4993 "I am partway through parsing a tuple pattern, but I got stuck here:"
4995 D.stack
4996 [ D.fillSep
4997 ["I","was","expecting","to","see","a","pattern","next."
4998 ,"I","am","expecting","the","final","result","to","be","something"
4999 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
5001 , D.toSimpleNote $
5002 "I can get confused by indentation in cases like this, so the problem\
5003 \ may be that the next part is not indented enough?"
5008toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
5009toPListReport source context list startRow startCol =
5010 case list of
5011 PListOpen row col ->
5012 case Code.whatIsNext source row col of
5013 Code.Keyword keyword ->
5014 let
5015 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5016 region = toKeywordRegion row col keyword
5017 in
5018 Report.Report "RESERVED WORD" region [] $
5019 Code.toSnippet source surroundings (Just region)
5021 D.reflow $
5022 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
5024 D.reflow $
5025 "This is a reserved word though! Try using some other name?"
5028 _ ->
5029 let
5030 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5031 region = toRegion row col
5032 in
5033 Report.Report "UNFINISHED LIST PATTERN" region [] $
5034 Code.toSnippet source surroundings (Just region) $
5036 D.reflow $
5037 "I just saw an open square bracket, but then I got stuck here:"
5039 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5042 PListEnd row col ->
5043 let
5044 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5045 region = toRegion row col
5046 in
5047 Report.Report "UNFINISHED LIST PATTERN" region [] $
5048 Code.toSnippet source surroundings (Just region) $
5050 D.reflow $
5051 "I was expecting a closing square bracket to end this list pattern:"
5053 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5056 PListExpr pattern row col ->
5057 toPatternReport source context pattern row col
5059 PListSpace space row col ->
5060 toSpaceReport source space row col
5062 PListIndentOpen row col ->
5063 let
5064 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5065 region = toRegion row col
5066 in
5067 Report.Report "UNFINISHED LIST PATTERN" region [] $
5068 Code.toSnippet source surroundings (Just region) $
5070 D.reflow $
5071 "I just saw an open square bracket, but then I got stuck here:"
5073 D.stack
5074 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5075 , D.toSimpleNote $
5076 "I can get confused by indentation in cases like this, so\
5077 \ maybe there is something next, but it is not indented enough?"
5081 PListIndentEnd row col ->
5082 let
5083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5084 region = toRegion row col
5085 in
5086 Report.Report "UNFINISHED LIST PATTERN" region [] $
5087 Code.toSnippet source surroundings (Just region) $
5089 D.reflow $
5090 "I was expecting a closing square bracket to end this list pattern:"
5092 D.stack
5093 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
5094 , D.toSimpleNote $
5095 "I can get confused by indentation in cases like this, so\
5096 \ maybe you have a closing square bracket but it is not indented enough?"
5100 PListIndentExpr row col ->
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 LIST PATTERN" region [] $
5106 Code.toSnippet source surroundings (Just region) $
5108 D.reflow $
5109 "I am partway through parsing a list pattern, but I got stuck here:"
5111 D.stack
5112 [ D.reflow $
5113 "I was expecting to see another pattern next. Maybe a variable name."
5114 , D.toSimpleNote $
5115 "I can get confused by indentation in cases like this, so\
5116 \ maybe there is more to this pattern but it is not indented enough?"
5122-- TYPES
5125data TContext
5126 = TC_Annotation Name.Name
5127 | TC_CustomType
5128 | TC_TypeAlias
5129 | TC_Port
5132toTypeReport :: Code.Source -> TContext -> Type -> Row -> Col -> Report.Report
5133toTypeReport source context tipe startRow startCol =
5134 case tipe of
5135 TRecord record row col ->
5136 toTRecordReport source context record row col
5138 TTuple tuple row col ->
5139 toTTupleReport source context tuple row col
5141 TStart row col ->
5142 case Code.whatIsNext source row col of
5143 Code.Keyword keyword ->
5144 let
5145 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5146 region = toKeywordRegion row col keyword
5147 in
5148 Report.Report "RESERVED WORD" region [] $
5149 Code.toSnippet source surroundings (Just region)
5151 D.reflow $
5152 "I was expecting to see a type next, but I got stuck on this reserved word:"
5154 D.reflow $
5155 "It looks like you are trying to use `" ++ keyword ++ "` as a type variable, but \
5156 \ it is a reserved word. Try using a different name!"
5159 _ ->
5160 let
5161 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5162 region = toRegion row col
5164 thing =
5165 case context of
5166 TC_Annotation _ -> "type annotation"
5167 TC_CustomType -> "custom type"
5168 TC_TypeAlias -> "type alias"
5169 TC_Port -> "port"
5171 something =
5172 case context of
5173 TC_Annotation name -> "the `" ++ Name.toChars name ++ "` type annotation"
5174 TC_CustomType -> "a custom type"
5175 TC_TypeAlias -> "a type alias"
5176 TC_Port -> "a port"
5177 in
5178 Report.Report ("PROBLEM IN " ++ map Char.toUpper thing) region [] $
5179 Code.toSnippet source surroundings (Just region)
5181 D.reflow $
5182 "I was partway through parsing " ++ something ++ ", but I got stuck here:"
5184 D.fillSep $
5185 ["I","was","expecting","to","see","a","type","next."
5186 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5190 TSpace space row col ->
5191 toSpaceReport source space row col
5193 TIndentStart row col ->
5194 let
5195 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5196 region = toRegion row col
5198 thing =
5199 case context of
5200 TC_Annotation _ -> "type annotation"
5201 TC_CustomType -> "custom type"
5202 TC_TypeAlias -> "type alias"
5203 TC_Port -> "port"
5204 in
5205 Report.Report ("UNFINISHED " ++ map Char.toUpper thing) region [] $
5206 Code.toSnippet source surroundings (Just region)
5208 D.reflow $
5209 "I was partway through parsing a " ++ thing ++ ", but I got stuck here:"
5211 D.stack
5212 [ D.fillSep $
5213 ["I","was","expecting","to","see","a","type","next."
5214 ,"Try","putting",D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5216 , D.toSimpleNote $
5217 "I can get confused by indentation. If you think there is already a type\
5218 \ next, maybe it is not indented enough?"
5223toTRecordReport :: Code.Source -> TContext -> TRecord -> Row -> Col -> Report.Report
5224toTRecordReport source context record startRow startCol =
5225 case record of
5226 TRecordOpen row col ->
5227 case Code.whatIsNext source row col of
5228 Code.Keyword keyword ->
5229 let
5230 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5231 region = toKeywordRegion row col keyword
5232 in
5233 Report.Report "RESERVED WORD" region [] $
5234 Code.toSnippet source surroundings (Just region)
5236 D.reflow $
5237 "I just started parsing a record type, but I got stuck on this field name:"
5239 D.reflow $
5240 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5241 \ that is a reserved word. Try using a different name!"
5244 _ ->
5245 let
5246 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5247 region = toRegion row col
5248 in
5249 Report.Report "UNFINISHED RECORD TYPE" region [] $
5250 Code.toSnippet source surroundings (Just region)
5252 D.reflow $
5253 "I just started parsing a record type, but I got stuck here:"
5255 D.fillSep
5256 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
5257 ,"so","I","was","expecting","to","see","a","field","name","next."
5261 TRecordEnd row col ->
5262 let
5263 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5264 region = toRegion row col
5265 in
5266 Report.Report "UNFINISHED RECORD TYPE" region [] $
5267 Code.toSnippet source surroundings (Just region)
5269 D.reflow $
5270 "I am partway through parsing a record type, but I got stuck here:"
5272 D.stack
5273 [ D.fillSep
5274 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
5275 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
5277 , D.toSimpleNote $
5278 "When I get stuck like this, it usually means that there is a missing parenthesis\
5279 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
5283 TRecordField row col ->
5284 case Code.whatIsNext source row col of
5285 Code.Keyword keyword ->
5286 let
5287 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5288 region = toKeywordRegion row col keyword
5289 in
5290 Report.Report "RESERVED WORD" region [] $
5291 Code.toSnippet source surroundings (Just region)
5293 D.reflow $
5294 "I am partway through parsing a record type, but I got stuck on this field name:"
5296 D.reflow $
5297 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
5298 \ that is a reserved word. Try using a different name!"
5301 Code.Other (Just ',') ->
5302 let
5303 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5304 region = toRegion row col
5305 in
5306 Report.Report "EXTRA COMMA" region [] $
5307 Code.toSnippet source surroundings (Just region)
5309 D.reflow $
5310 "I am partway through parsing a record type, but I got stuck here:"
5312 D.stack
5313 [ D.reflow $
5314 "I am seeing two commas in a row. This is the second one!"
5315 , D.reflow $
5316 "Just delete one of the commas and you should be all set!"
5317 , noteForRecordTypeError
5321 Code.Close _ '}' ->
5322 let
5323 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5324 region = toRegion row col
5325 in
5326 Report.Report "EXTRA COMMA" region [] $
5327 Code.toSnippet source surroundings (Just region)
5329 D.reflow $
5330 "I am partway through parsing a record type, but I got stuck here:"
5332 D.stack
5333 [ D.reflow $
5334 "Trailing commas are not allowed in record types. Try deleting the comma that\
5335 \ appears before this closing curly brace."
5336 , noteForRecordTypeError
5340 _ ->
5341 let
5342 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5343 region = toRegion row col
5344 in
5345 Report.Report "PROBLEM IN RECORD TYPE" region [] $
5346 Code.toSnippet source surroundings (Just region)
5348 D.reflow $
5349 "I am partway through parsing a record type, but I got stuck here:"
5351 D.stack
5352 [ D.fillSep
5353 ["I","was","expecting","to","see","another","record","field","defined","next,"
5354 ,"so","I","am","looking","for","a","lower-case","name","like"
5355 ,D.dullyellow "userName","or",D.dullyellow "plantHeight" <> "."
5357 , noteForRecordTypeError
5361 TRecordColon 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 RECORD TYPE" region [] $
5367 Code.toSnippet source surroundings (Just region)
5369 D.reflow $
5370 "I am partway through parsing a record type, but I got stuck here:"
5372 D.stack
5373 [ D.fillSep $
5374 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
5375 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
5377 , noteForRecordTypeError
5381 TRecordType tipe row col ->
5382 toTypeReport source context tipe row col
5384 TRecordSpace space row col ->
5385 toSpaceReport source space row col
5387 TRecordIndentOpen row col ->
5388 let
5389 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5390 region = toRegion row col
5391 in
5392 Report.Report "UNFINISHED RECORD TYPE" region [] $
5393 Code.toSnippet source surroundings (Just region)
5395 D.reflow $
5396 "I just saw the opening curly brace of a record type, but then I got stuck here:"
5398 D.stack
5399 [ D.fillSep $
5400 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
5401 ,"Try","defining","some","fields","of","your","own?"
5403 , noteForRecordTypeIndentError
5407 TRecordIndentEnd row col ->
5408 case Code.nextLineStartsWithCloseCurly source row of
5409 Just (curlyRow, curlyCol) ->
5410 let
5411 surroundings = A.Region (A.Position startRow startCol) (A.Position curlyRow curlyCol)
5412 region = toRegion curlyRow curlyCol
5413 in
5414 Report.Report "NEED MORE INDENTATION" region [] $
5415 Code.toSnippet source surroundings (Just region)
5417 D.reflow $
5418 "I was partway through parsing a record type, but I got stuck here:"
5420 D.stack
5421 [ D.reflow $
5422 "I need this curly brace to be indented more. Try adding some spaces before it!"
5423 , noteForRecordTypeError
5427 Nothing ->
5428 let
5429 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5430 region = toRegion row col
5431 in
5432 Report.Report "UNFINISHED RECORD TYPE" region [] $
5433 Code.toSnippet source surroundings (Just region)
5435 D.reflow $
5436 "I was partway through parsing a record type, but I got stuck here:"
5438 D.stack
5439 [ D.fillSep $
5440 ["I","was","expecting","to","see","a","closing","curly","brace","next."
5441 ,"Try","putting","a",D.green "}","next","and","see","if","that","helps?"
5443 , noteForRecordTypeIndentError
5447 TRecordIndentField row col ->
5448 let
5449 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5450 region = toRegion row col
5451 in
5452 Report.Report "UNFINISHED RECORD TYPE" region [] $
5453 Code.toSnippet source surroundings (Just region)
5455 D.reflow $
5456 "I am partway through parsing a record type, but I got stuck after that last comma:"
5458 D.stack
5459 [ D.reflow $
5460 "Trailing commas are not allowed in record types, so the fix may be to\
5461 \ delete that last comma? Or maybe you were in the middle of defining\
5462 \ an additional field?"
5463 , noteForRecordTypeIndentError
5467 TRecordIndentColon row col ->
5468 let
5469 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5470 region = toRegion row col
5471 in
5472 Report.Report "UNFINISHED RECORD TYPE" region [] $
5473 Code.toSnippet source surroundings (Just region)
5475 D.reflow $
5476 "I am partway through parsing a record type. I just saw a record\
5477 \ field, so I was expecting to see a colon next:"
5479 D.stack
5480 [ D.fillSep $
5481 ["Try","putting","an",D.green ":","followed","by","a","type?"
5483 , noteForRecordTypeIndentError
5487 TRecordIndentType row col ->
5488 let
5489 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5490 region = toRegion row col
5491 in
5492 Report.Report "UNFINISHED RECORD TYPE" region [] $
5493 Code.toSnippet source surroundings (Just region)
5495 D.reflow $
5496 "I am partway through parsing a record type, and I was expecting to run into a type next:"
5498 D.stack
5499 [ D.fillSep $
5500 ["Try","putting","something","like"
5501 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
5503 , noteForRecordTypeIndentError
5508noteForRecordTypeError :: D.Doc
5509noteForRecordTypeError =
5510 D.stack $
5511 [ D.toSimpleNote
5512 "If you are trying to define a record type across multiple lines, I recommend using this format:"
5513 , D.indent 4 $ D.vcat $
5514 [ "{ name : String"
5515 , ", age : Int"
5516 , ", height : Float"
5517 , "}"
5519 , D.reflow $
5520 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5521 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5522 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5526noteForRecordTypeIndentError :: D.Doc
5527noteForRecordTypeIndentError =
5528 D.stack $
5529 [ D.toSimpleNote
5530 "I may be confused by indentation. For example, if you are trying to define\
5531 \ a record type across multiple lines, I recommend using this format:"
5532 , D.indent 4 $ D.vcat $
5533 [ "{ name : String"
5534 , ", age : Int"
5535 , ", height : Float"
5536 , "}"
5538 , D.reflow $
5539 "Notice that each line starts with some indentation. Usually two or four spaces. I\
5540 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
5541 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
5545toTTupleReport :: Code.Source -> TContext -> TTuple -> Row -> Col -> Report.Report
5546toTTupleReport source context tuple startRow startCol =
5547 case tuple of
5548 TTupleOpen row col ->
5549 case Code.whatIsNext source row col of
5550 Code.Keyword keyword ->
5551 let
5552 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5553 region = toKeywordRegion row col keyword
5554 in
5555 Report.Report "RESERVED WORD" region [] $
5556 Code.toSnippet source surroundings (Just region)
5558 D.reflow $
5559 "I ran into a reserved word unexpectedly:"
5561 D.reflow $
5562 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
5563 \ it is a reserved word. Try using a different name!"
5566 _ ->
5567 let
5568 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5569 region = toRegion row col
5570 in
5571 Report.Report "UNFINISHED PARENTHESES" region [] $
5572 Code.toSnippet source surroundings (Just region)
5574 D.reflow $
5575 "I just saw an open parenthesis, so I was expecting to see a type next."
5577 D.fillSep $
5578 ["Something","like",D.dullyellow "(Maybe Int)","or"
5579 ,D.dullyellow "(List Person)" <> "."
5580 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5584 TTupleEnd row col ->
5585 let
5586 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5587 region = toRegion row col
5588 in
5589 Report.Report "UNFINISHED PARENTHESES" region [] $
5590 Code.toSnippet source surroundings (Just region)
5592 D.reflow $
5593 "I was expecting to see a closing parenthesis next, but I got stuck here:"
5595 D.stack
5596 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
5597 , D.toSimpleNote $
5598 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
5599 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
5600 \ or missing brackets) that is confusing me."
5604 TTupleType tipe row col ->
5605 toTypeReport source context tipe row col
5607 TTupleSpace space row col ->
5608 toSpaceReport source space row col
5610 TTupleIndentType1 row col ->
5611 let
5612 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5613 region = toRegion row col
5614 in
5615 Report.Report "UNFINISHED PARENTHESES" region [] $
5616 Code.toSnippet source surroundings (Just region)
5618 D.reflow $
5619 "I just saw an open parenthesis, so I was expecting to see a type next."
5621 D.stack
5622 [ D.fillSep $
5623 ["Something","like",D.dullyellow "(Maybe Int)","or"
5624 ,D.dullyellow "(List Person)" <> "."
5625 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
5627 , D.toSimpleNote $
5628 "I can get confused by indentation in cases like this, so\
5629 \ maybe you have a type but it is not indented enough?"
5633 TTupleIndentTypeN row col ->
5634 let
5635 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5636 region = toRegion row col
5637 in
5638 Report.Report "UNFINISHED TUPLE TYPE" region [] $
5639 Code.toSnippet source surroundings (Just region)
5641 D.reflow $
5642 "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."
5644 D.stack
5645 [ D.fillSep $
5646 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
5647 ,D.dullyellow "(String,Int)" <> ","
5648 ,"so","I","think","there","is","a","type","missing","here?"
5650 , D.toSimpleNote $
5651 "I can get confused by indentation in cases like this, so\
5652 \ maybe you have an expression but it is not indented enough?"
5656 TTupleIndentEnd row col ->
5657 let
5658 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
5659 region = toRegion row col
5660 in
5661 Report.Report "UNFINISHED PARENTHESES" region [] $
5662 Code.toSnippet source surroundings (Just region)
5664 D.reflow $
5665 "I was expecting to see a closing parenthesis next:"
5667 D.stack
5668 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
5669 , D.toSimpleNote $
5670 "I can get confused by indentation in cases like this, so\
5671 \ maybe you have a closing parenthesis but it is not indented enough?"