on 2a1ace1 help sign in
4683 lines 165 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Error.Syntax
4 ( Error(..)
5 --
6 , Module(..)
7 , Exposing(..)
8 --
9 , Decl(..)
10 , DeclType(..)
11 , TypeAlias(..)
12 , CustomType(..)
13 , DeclDef(..)
14 , Port(..)
15 --
16 , Expr(..)
17 , Record(..)
18 , Tuple(..)
19 , List(..)
20 , Func(..)
21 , Case(..)
22 , If(..)
23 , Let(..)
24 , Def(..)
25 , Destruct(..)
26 --
27 , Pattern(..)
28 , PRecord(..)
29 , PTuple(..)
30 , PList(..)
31 --
32 , Type(..)
33 , TRecord(..)
34 , TTuple(..)
35 --
36 , Char(..)
37 , String(..)
38 , Escape(..)
39 , Number(..)
40 --
41 , Space(..)
42 , toReport
43 )
44 where
47import Prelude hiding (Char, String)
48import qualified Data.Char as Char
49import qualified Data.Name as Name
50import Data.Word (Word16)
51import Numeric (showHex)
53import qualified Elm.ModuleName as ModuleName
54import Parse.Primitives (Row, Col)
55import Parse.Symbol (BadOperator(..))
56import qualified Reporting.Annotation as A
57import qualified Reporting.Doc as D
58import qualified Reporting.Report as Report
59import qualified Reporting.Render.Code as Code
63-- ALL SYNTAX ERRORS
66data Error
67 = ModuleNameUnspecified ModuleName.Raw
68 | ModuleNameMismatch ModuleName.Raw (A.Located ModuleName.Raw)
69 | UnexpectedPort A.Region
70 | NoPorts A.Region
71 | ParseError Module
75-- MODULE
78data Module
79 = ModuleSpace Space Row Col
80 | ModuleEndOfFile Row Col
81 --
82 | ModuleProblem Row Col
83 | ModuleName Row Col
84 | ModuleExposing Exposing Row Col
85 --
86 | PortModuleProblem Row Col
87 | PortModuleName Row Col
88 | PortModuleExposing Exposing Row Col
89 --
90 | Effect Row Col
91 --
92 | FreshLine Row Col
93 --
94 | ImportStart Row Col
95 | ImportName Row Col
96 | ImportAs Row Col
97 | ImportAlias Row Col
98 | ImportExposing Row Col
99 | ImportExposingList Exposing Row Col
100 | ImportEnd Row Col -- different based on col=1 or if greater
101 --
102 | ImportIndentName Row Col
103 | ImportIndentAlias Row Col
104 | ImportIndentExposingList Row Col
105 --
106 | Infix Row Col
107 --
108 | Declarations Decl Row Col
111data Exposing
112 = ExposingSpace Space Row Col
113 | ExposingStart Row Col
114 | ExposingValue Row Col
115 | ExposingOperator Row Col
116 | ExposingOperatorReserved BadOperator Row Col
117 | ExposingOperatorRightParen Row Col
118 | ExposingTypePrivacy Row Col
119 | ExposingEnd Row Col
120 --
121 | ExposingIndentEnd Row Col
122 | ExposingIndentValue Row Col
126-- DECLARATIONS
129data Decl
130 = DeclStart Row Col
131 | DeclSpace Space Row Col
132 --
133 | Port Port Row Col
134 | DeclType DeclType Row Col
135 | DeclDef Name.Name DeclDef Row Col
136 --
137 | DeclFreshLineStart Row Col
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
228 | IndentMoreExpr Row Col
231data Record
232 = RecordOpen Row Col
233 | RecordEnd Row Col
234 | RecordField Row Col
235 | RecordEquals Row Col
236 | RecordExpr Expr Row Col
237 | RecordSpace Space Row Col
238 --
239 | RecordIndentOpen Row Col
240 | RecordIndentEnd Row Col
241 | RecordIndentField Row Col
242 | RecordIndentEquals Row Col
243 | RecordIndentExpr Row Col
246data Tuple
247 = TupleExpr Expr Row Col
248 | TupleSpace Space Row Col
249 | TupleEnd Row Col
250 | TupleOperatorClose Row Col
251 | TupleOperatorReserved BadOperator Row Col
252 --
253 | TupleIndentExpr1 Row Col
254 | TupleIndentExprN Row Col
255 | TupleIndentEnd Row Col
258data List
259 = ListSpace Space Row Col
260 | ListOpen Row Col
261 | ListExpr Expr Row Col
262 | ListEnd Row Col
263 --
264 | ListIndentOpen Row Col
265 | ListIndentEnd Row Col
266 | ListIndentExpr Row Col
269data Func
270 = FuncSpace Space Row Col
271 | FuncArg Pattern Row Col
272 | FuncBody Expr Row Col
273 | FuncArrow Row Col
274 --
275 | FuncIndentArg Row Col
276 | FuncIndentArrow Row Col
277 | FuncIndentBody Row Col
280data Case
281 = CaseSpace Space Row Col
282 | CaseOf Row Col
283 | CasePattern Pattern Row Col
284 | CaseArrow Row Col
285 | CaseExpr Expr Row Col
286 | CaseBranch Expr Row Col
287 --
288 | CaseIndentOf Row Col
289 | CaseIndentExpr Row Col
290 | CaseIndentPattern Row Col
291 | CaseIndentArrow Row Col
292 | CaseIndentBranch Row Col
293 | CasePatternAlignment Word16 Row Col
296data If
297 = IfSpace Space Row Col
298 | IfThen Row Col
299 | IfElse Row Col
300 | IfElseBranchStart Row Col
301 --
302 | IfCondition Expr Row Col
303 | IfThenBranch Expr Row Col
304 | IfElseBranch Expr Row Col
305 --
306 | IfIndentCondition Row Col
307 | IfIndentThen Row Col
308 | IfIndentThenBranch Row Col
309 | IfIndentElseBranch Row Col
310 | IfIndentElse Row Col
313data Let
314 = LetSpace Space Row Col
315 | LetIn Row Col
316 | LetDefAlignment Word16 Row Col
317 | LetDefName Row Col
318 | LetDef Name.Name Def Row Col
319 | LetDestruct Destruct Row Col
320 | LetBody Expr Row Col
321 | LetIndentDef Row Col
322 | LetIndentIn Row Col
323 | LetIndentBody Row Col
326data Def
327 = DefSpace Space Row Col
328 | DefType Type Row Col
329 | DefNameRepeat Name.Name Row Col
330 | DefNameMatch Name.Name Name.Name Row Col
331 | DefArg Pattern Row Col
332 | DefEquals Row Col
333 | DefBody Expr Row Col
334 | DefIndentEquals Row Col
335 | DefIndentType Row Col
336 | DefIndentBody Row Col
337 | DefAlignment Word16 Row Col
340data Destruct
341 = DestructSpace Space Row Col
342 | DestructPattern Pattern Row Col
343 | DestructEquals Row Col
344 | DestructBody Expr Row Col
345 | DestructIndentEquals Row Col
346 | DestructIndentBody Row Col
350-- PATTERNS
353data Pattern
354 = PRecord PRecord Row Col
355 | PTuple PTuple Row Col
356 | PList PList Row Col
357 --
358 | PStart Row Col
359 | PChar Char Row Col
360 | PString String Row Col
361 | PNumber Number Row Col
362 | PFloat Word16 Row Col
363 | PAlias Row Col
364 | PWildcardNotVar Name.Name Int Row Col
365 | PSpace Space Row Col
366 --
367 | PIndentStart Row Col
368 | PIndentAlias Row Col
371data PRecord
372 = PRecordOpen Row Col
373 | PRecordEnd Row Col
374 | PRecordField Row Col
375 | PRecordSpace Space Row Col
376 --
377 | PRecordIndentOpen Row Col
378 | PRecordIndentEnd Row Col
379 | PRecordIndentField Row Col
382data PTuple
383 = PTupleOpen Row Col
384 | PTupleEnd Row Col
385 | PTupleExpr Pattern Row Col
386 | PTupleSpace Space Row Col
387 --
388 | PTupleIndentEnd Row Col
389 | PTupleIndentExpr1 Row Col
390 | PTupleIndentExprN Row Col
393data PList
394 = PListOpen Row Col
395 | PListEnd Row Col
396 | PListExpr Pattern Row Col
397 | PListSpace Space Row Col
398 --
399 | PListIndentOpen Row Col
400 | PListIndentEnd Row Col
401 | PListIndentExpr Row Col
405-- TYPES
408data Type
409 = TRecord TRecord Row Col
410 | TTuple TTuple Row Col
411 | TArrow Row Col
412 --
413 | TStart Row Col
414 | TSpace Space Row Col
415 --
416 | TIndentStart Row Col
419data TRecord
420 = TRecordOpen Row Col
421 | TRecordEnd Row Col
422 --
423 | TRecordField Row Col
424 | TRecordColon Row Col
425 | TRecordType Type Row Col
426 --
427 | TRecordSpace Space Row Col
428 --
429 | TRecordIndentOpen Row Col
430 | TRecordIndentField Row Col
431 | TRecordIndentColon Row Col
432 | TRecordIndentType Row Col
433 | TRecordIndentEnd Row Col
436data TTuple
437 = TTupleOpen Row Col
438 | TTupleEnd Row Col
439 | TTupleType Type Row Col
440 | TTupleSpace Space Row Col
441 --
442 | TTupleIndentType1 Row Col
443 | TTupleIndentTypeN Row Col
444 | TTupleIndentEnd Row Col
448-- LITERALS
451data Char
452 = CharEndless
453 | CharEscape Escape
454 | CharNotString Word16
457data String
458 = StringEndless_Single
459 | StringEndless_Multi
460 | StringEscape Escape
463data Escape
464 = EscapeUnknown
465 | BadUnicodeFormat Word16
466 | BadUnicodeCode Word16
467 | BadUnicodeLength Word16 Int Int
470data Number
471 = NumberEnd
472 | NumberDot Int
473 | NumberHexDigit
474 | NumberNoLeadingZero
478-- MISC
481data Space
482 = HasTab
483 | EndlessMultiComment
487-- TO REPORT
490toReport :: Code.Source -> Error -> Report.Report
491toReport source err =
492 case err of
493 ModuleNameUnspecified name ->
494 let
495 region = toRegion 1 1
496 in
497 Report.Report "MODULE NAME MISSING" region [] $
498 D.stack
499 [ D.reflow $
500 "I need the module name to be declared at the top of this file, like this:"
501 , D.indent 4 $ D.fillSep $
502 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
503 , D.reflow $
504 "Try adding that as the first line of your file!"
505 , D.toSimpleNote $
506 "It is best to replace (..) with an explicit list of types and\
507 \ functions you want to expose. When you know a value is only used\
508 \ within this module, you can refactor without worrying about uses\
509 \ elsewhere. Limiting exposed values can also speed up compilation\
510 \ because I can skip a bunch of work if I see that the exposed API\
511 \ has not changed."
512 ]
514 ModuleNameMismatch expectedName (A.At region actualName) ->
515 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
516 Code.toSnippet source region Nothing
517 (
518 "It looks like this module name is out of sync:"
519 ,
520 D.stack
521 [ D.reflow $
522 "I need it to match the file path, so I was expecting it to see `"
523 ++ ModuleName.toChars expectedName
524 ++ "` here. Make the following change, and you should be all set!"
525 , D.indent 4 $
526 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
527 , D.toSimpleNote $
528 "I require that module names correspond to file paths. This makes it much\
529 \ easier to explore unfamiliar codebases! So if you want to keep the current\
530 \ module name, try renaming the file instead."
531 ]
532 )
534 UnexpectedPort region ->
535 Report.Report "UNEXPECTED PORTS" region [] $
536 Code.toSnippet source region Nothing
537 (
538 D.reflow $
539 "You are declaring ports in a normal module."
540 ,
541 D.stack
542 [ D.fillSep
543 ["Switch","this","to","say",D.cyan "port module","instead,"
544 ,"marking","that","this","module","contains","port","declarations."
545 ]
546 , D.link "Note"
547 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
548 "ports"
549 "to learn the syntax and how to use it effectively."
550 ]
551 )
553 NoPorts region ->
554 Report.Report "NO PORTS" region [] $
555 Code.toSnippet source region Nothing
556 (
557 D.reflow $
558 "This module does not declare any ports, but it says it will:"
559 ,
560 D.fillSep
561 ["Switch","this","to",D.cyan "module"
562 ,"and","you","should","be","all","set!"
563 ]
564 )
566 ParseError modul ->
567 toParseErrorReport source modul
570toParseErrorReport :: Code.Source -> Module -> Report.Report
571toParseErrorReport source modul =
572 case modul of
573 ModuleSpace space row col ->
574 toSpaceReport source space row col
576 ModuleEndOfFile row col ->
577 case Code.whatIsNext source row col of
578 Code.Keyword keyword ->
579 let
580 region = toKeywordRegion row col keyword
581 in
582 Report.Report "RESERVED WORD" region [] $
583 Code.toSnippet source region Nothing
584 (
585 D.reflow $
586 "I got stuck on this reserved word:"
587 ,
588 D.reflow $
589 "The name `" ++ keyword ++ "` is reserved, so try using a different name?"
590 )
592 Code.Operator op ->
593 let
594 region = toKeywordRegion row col op
595 in
596 Report.Report "UNEXPECTED SYMBOL" region [] $
597 Code.toSnippet source region Nothing
598 (
599 D.reflow $
600 "I ran into an unexpected symbol:"
601 ,
602 D.reflow $
603 "I was not expecting to see a " ++ op ++ " here. Try deleting it? Maybe\
604 \ I can give a better hint from there?"
605 )
607 Code.Close term bracket ->
608 let
609 region = toRegion row col
610 in
611 Report.Report ("UNEXPECTED " ++ map Char.toUpper term) region [] $
612 Code.toSnippet source region Nothing
613 (
614 D.reflow $
615 "I ran into an unexpected " ++ term ++ ":"
616 ,
617 D.reflow $
618 "This " ++ bracket : " does not match up with an earlier open " ++ term ++ ". Try deleting it?"
619 )
621 Code.Other ->
622 let
623 region = toRegion row col
624 in
625 Report.Report "SYNTAX PROBLEM" region [] $
626 Code.toSnippet source region Nothing
627 (
628 D.reflow $
629 "I got stuck here:"
630 ,
631 D.reflow $
632 "Whatever I am running into is confusing me a lot! Normally I can give fairly\
633 \ specific hints, but something is really tripping me up this time."
634 )
636 ModuleProblem row col ->
637 let
638 region = toRegion row col
639 in
640 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
641 Code.toSnippet source region Nothing
642 (
643 D.reflow $
644 "I am parsing an `module` declaration, but I got stuck here:"
645 ,
646 D.stack
647 [ D.reflow $
648 "Here are some examples of valid `module` declarations:"
649 , D.indent 4 $ D.vcat $
650 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
651 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
652 ]
653 , D.reflow $
654 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
655 \ of files when the public interface of a module stays the same, so exposing fewer\
656 \ values can help improve compile times!"
657 ]
658 )
660 ModuleName row col ->
661 let
662 region = toRegion row col
663 in
664 Report.Report "EXPECTING MODULE NAME" region [] $
665 Code.toSnippet source region Nothing
666 (
667 D.reflow $
668 "I was parsing an `module` declaration until I got stuck here:"
669 ,
670 D.stack
671 [ D.reflow $
672 "I was expecting to see the module name next, like in these examples:"
673 , D.indent 4 $ D.vcat $
674 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
675 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
676 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
677 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
678 ]
679 , D.reflow $
680 "Notice that the module names all start with capital letters. That is required!"
681 ]
682 )
684 ModuleExposing exposing row col ->
685 toExposingReport source exposing row col
687 PortModuleProblem row col ->
688 let
689 region = toRegion row col
690 in
691 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
692 Code.toSnippet source region Nothing
693 (
694 D.reflow $
695 "I am parsing an `port module` declaration, but I got stuck here:"
696 ,
697 D.stack
698 [ D.reflow $
699 "Here are some examples of valid `port module` declarations:"
700 , D.indent 4 $ D.vcat $
701 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
702 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
703 ]
704 , D.link "Note" "Read" "ports" "for more help."
705 ]
706 )
708 PortModuleName row col ->
709 let
710 region = toRegion row col
711 in
712 Report.Report "EXPECTING MODULE NAME" region [] $
713 Code.toSnippet source region Nothing
714 (
715 D.reflow $
716 "I was parsing an `module` declaration until I got stuck here:"
717 ,
718 D.stack
719 [ D.reflow $
720 "I was expecting to see the module name next, like in these examples:"
721 , D.indent 4 $ D.vcat $
722 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
723 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
724 ]
725 , D.reflow $
726 "Notice that the module names start with capital letters. That is required!"
727 ]
728 )
730 PortModuleExposing exposing row col ->
731 toExposingReport source exposing row col
733 Effect row col ->
734 let
735 region = toRegion row col
736 in
737 Report.Report "BAD MODULE DECLARATION" region [] $
738 Code.toSnippet source region Nothing
739 (
740 D.reflow $
741 "I cannot parse this module declaration:"
742 ,
743 D.reflow $
744 "This type of module is reserved for the @elm organization. It is used to\
745 \ define certain effects, avoiding building them into the compiler."
746 )
748 FreshLine row col ->
749 let
750 region = toRegion row col
752 toBadFirstLineReport keyword =
753 Report.Report "TOO MUCH INDENTATION" region [] $
754 Code.toSnippet source region Nothing
755 (
756 D.reflow $
757 "This `" ++ keyword ++ "` should not have any spaces before it:"
758 ,
759 D.reflow $
760 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
761 )
763 in
764 case Code.whatIsNext source row col of
765 Code.Keyword "module" -> toBadFirstLineReport "module"
766 Code.Keyword "import" -> toBadFirstLineReport "import"
767 Code.Keyword "type" -> toBadFirstLineReport "type"
768 Code.Keyword "port" -> toBadFirstLineReport "port"
769 _ ->
770 Report.Report "SYNTAX PROBLEM" region [] $
771 Code.toSnippet source region Nothing
772 (
773 D.reflow $
774 "I got stuck here:"
775 ,
776 D.stack
777 [ D.reflow $
778 "I am not sure what is going on, but I recommend starting an Elm\
779 \ file with the following lines:"
780 , D.vcat
781 [ D.fillSep [D.cyan "import","Html"]
782 , ""
783 , D.fillSep [D.green "main","="]
784 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
785 ]
786 , D.reflow $
787 "You should be able to copy those lines directly into your file. Check out\
788 \ some of the examples on https://elm-lang.org for more help getting started!"
789 , D.toSimpleNote $
790 "This can also happen when something is indented too much!"
791 ]
792 )
794 ImportStart row col ->
795 toImportReport source row col
797 ImportName row col ->
798 let
799 region = toRegion row col
800 in
801 Report.Report "EXPECTING IMPORT NAME" region [] $
802 Code.toSnippet source region Nothing
803 (
804 D.reflow $
805 "I was parsing an `import` until I got stuck here:"
806 ,
807 D.stack
808 [ D.reflow $
809 "I was expecting to see a module name next, like in these examples:"
810 , D.indent 4 $ D.vcat $
811 [ D.fillSep [D.cyan "import","Dict"]
812 , D.fillSep [D.cyan "import","Maybe"]
813 , D.fillSep [D.cyan "import","Html.Attributes"]
814 , D.fillSep [D.cyan "import","Json.Decode"]
815 ]
816 , D.reflow $
817 "Notice that the module names all start with capital letters. That is required!"
818 ]
819 )
821 ImportAs row col ->
822 toImportReport source row col
824 ImportAlias row col ->
825 let
826 region = toRegion row col
827 in
828 Report.Report "EXECTING IMPORT ALIAS" region [] $
829 Code.toSnippet source region Nothing
830 (
831 D.reflow $
832 "I was parsing an `import` until I got stuck here:"
833 ,
834 D.stack
835 [ D.reflow $
836 "I was expecting to see an alias next, like in these examples:"
837 , D.indent 4 $ D.vcat $
838 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
839 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
840 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
841 ]
842 , D.reflow $
843 "Notice that the alias always starts with a capital letter. That is required!"
844 ]
845 )
847 ImportExposing row col ->
848 toImportReport source row col
850 ImportExposingList exposing row col ->
851 toExposingReport source exposing row col
853 ImportEnd row col ->
854 toImportReport source row col
856 ImportIndentName row col ->
857 toImportReport source row col
859 ImportIndentAlias row col ->
860 toImportReport source row col
862 ImportIndentExposingList row col ->
863 let
864 region = toRegion row col
865 in
866 Report.Report "UNFINISHED IMPORT" region [] $
867 Code.toSnippet source region Nothing
868 (
869 D.reflow $
870 "I was parsing an `import` until I got stuck here:"
871 ,
872 D.stack
873 [ D.reflow $
874 "I was expecting to see the list of exposed values next. For example, here\
875 \ are two ways to expose values from the `Html` module:"
876 , D.indent 4 $ D.vcat $
877 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
878 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
879 ]
880 , D.reflow $
881 "I generally recommend the second style. It is more explicit, making it\
882 \ much easier to figure out where values are coming from in large projects!"
883 ]
884 )
886 Infix row col ->
887 let
888 region = toRegion row col
889 in
890 Report.Report "BAD INFIX" region [] $
891 Code.toSnippet source region Nothing
892 (
893 D.reflow $
894 "Something went wrong in this infix operator declaration:"
895 ,
896 D.reflow $
897 "This feature is used by the @elm organization to define the\
898 \ languages built-in operators."
899 )
901 Declarations decl _ _ ->
902 toDeclarationsReport source decl
906-- IMPORTS
909toImportReport :: Code.Source -> Row -> Col -> Report.Report
910toImportReport source row col =
911 let
912 region = toRegion row col
913 in
914 Report.Report "UNFINISHED IMPORT" region [] $
915 Code.toSnippet source region Nothing
916 (
917 D.reflow $
918 "I am partway through parsing an import, but I got stuck here:"
919 ,
920 D.stack
921 [ D.reflow $
922 "Here are some examples of valid `import` declarations:"
923 , D.indent 4 $ D.vcat $
924 [ D.fillSep [D.cyan "import","Html"]
925 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
926 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
927 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
928 ]
929 , D.reflow $
930 "You are probably trying to import a different module, but try to make it look like one of these examples!"
931 ]
932 )
936-- EXPOSING
939toExposingReport :: Code.Source -> Exposing -> Row -> Col -> Report.Report
940toExposingReport source exposing startRow startCol =
941 case exposing of
942 ExposingSpace space row col ->
943 toSpaceReport source space row col
945 ExposingStart row col ->
946 let
947 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
948 region = toRegion row col
949 in
950 Report.Report "PROBLEM IN EXPOSING" region [] $
951 Code.toSnippet source surroundings (Just region)
952 (
953 D.reflow $
954 "I want to parse exposed values, but I am getting stuck here:"
955 ,
956 D.stack
957 [ D.fillSep $
958 ["Exposed","values","are","always","surrounded","by","parentheses."
959 ,"So","try","adding","a",D.green "(","here?"
960 ]
961 , D.toSimpleNote "Here are some valid examples of `exposing` for reference:"
962 , D.indent 4 $ D.vcat $
963 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
964 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
965 ]
966 , D.reflow $
967 "If you are getting tripped up, you can just expose everything for now. It should\
968 \ get easier to make an explicit exposing list as you see more examples in the wild."
969 ]
970 )
972 ExposingValue row col ->
973 case Code.whatIsNext source row col of
974 Code.Keyword keyword ->
975 let
976 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
977 region = toKeywordRegion row col keyword
978 in
979 Report.Report "RESERVED WORD" region [] $
980 Code.toSnippet source surroundings (Just region)
981 (
982 D.reflow $
983 "I got stuck on this reserved word:"
984 ,
985 D.reflow $
986 "It looks like you are trying to expose `" ++ keyword ++ "` but that is a reserved word. Is there a typo?"
987 )
989 Code.Operator op ->
990 let
991 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
992 region = toKeywordRegion row col op
993 in
994 Report.Report "UNEXPECTED SYMBOL" region [] $
995 Code.toSnippet source surroundings (Just region)
996 (
997 D.reflow $
998 "I got stuck on this symbol:"
999 ,
1000 D.stack
1001 [ D.reflow $
1002 "If you are trying to expose an operator, add parentheses around it like this:"
1003 , D.indent 4 $ D.dullyellow (D.fromChars op) <> " -> " <> D.green ("(" <> D.fromChars op <> ")")
1007 _ ->
1008 let
1009 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1010 region = toRegion row col
1011 in
1012 Report.Report "PROBLEM IN EXPOSING" region [] $
1013 Code.toSnippet source surroundings (Just region)
1015 D.reflow $
1016 "I got stuck while parsing these exposed values:"
1018 D.stack
1019 [ D.reflow $
1020 "I do not have an exact recommendation, so here are some valid examples\
1021 \ of `exposing` for reference:"
1022 , D.indent 4 $ D.vcat $
1023 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
1024 , D.fillSep [D.cyan "import","Basics",D.cyan "exposing","(Int, Float, Bool(..), (+), not, sqrt)"]
1026 , D.reflow $
1027 "These examples show how to expose types, variants, operators, and functions. Everything\
1028 \ should be some permutation of these examples, just with different names."
1032 ExposingOperator row col ->
1033 let
1034 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1035 region = toRegion row col
1036 in
1037 Report.Report "PROBLEM IN EXPOSING" region [] $
1038 Code.toSnippet source surroundings (Just region)
1040 D.reflow $
1041 "I just saw an open parenthesis, so I was expecting an operator next:"
1043 D.fillSep $
1044 ["It","is","possible","to","expose","operators,","so","I","was","expecting"
1045 ,"to","see","something","like",D.dullyellow "(+)","or",D.dullyellow "(|=)"
1046 ,"or",D.dullyellow "(||)","after","I","saw","that","open","parenthesis."
1050 ExposingOperatorReserved op row col ->
1051 let
1052 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1053 region = toRegion row col
1054 in
1055 Report.Report "RESERVED SYMBOL" region [] $
1056 Code.toSnippet source surroundings (Just region)
1058 D.reflow $
1059 "I cannot expose this as an operator:"
1061 case op of
1062 BadDot -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1063 BadPipe -> D.fillSep ["Maybe","you","want",D.dullyellow "(||)","instead?"]
1064 BadArrow -> D.reflow "Try getting rid of this entry? Maybe I can give you a better hint after that?"
1065 BadEquals -> D.fillSep ["Maybe","you","want",D.dullyellow "(==)","instead?"]
1066 BadHasType -> D.fillSep ["Maybe","you","want",D.dullyellow "(::)","instead?"]
1069 ExposingOperatorRightParen row col ->
1070 let
1071 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1072 region = toRegion row col
1073 in
1074 Report.Report "PROBLEM IN EXPOSING" region [] $
1075 Code.toSnippet source surroundings (Just region)
1077 D.reflow $
1078 "It looks like you are exposing an operator, but I got stuck here:"
1080 D.fillSep $
1081 ["I","was","expecting","to","see","the","closing","parenthesis","immediately"
1082 ,"after","the","operator.","Try","adding","a",D.green ")","right","here?"
1086 ExposingEnd row col ->
1087 let
1088 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1089 region = toRegion row col
1090 in
1091 Report.Report "UNFINISHED EXPOSING" region [] $
1092 Code.toSnippet source surroundings (Just region)
1094 D.reflow $
1095 "I was partway through parsing exposed values, but I got stuck here:"
1097 D.reflow $
1098 "Maybe there is a comma missing before this?"
1101 ExposingTypePrivacy row col ->
1102 let
1103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1104 region = toRegion row col
1105 in
1106 Report.Report "PROBLEM EXPOSING CUSTOM TYPE VARIANTS" region [] $
1107 Code.toSnippet source surroundings (Just region)
1109 D.reflow $
1110 "It looks like you are trying to expose the variants of a custom type:"
1112 D.stack
1113 [ D.fillSep $
1114 ["You","need","to","write","something","like"
1115 ,D.dullyellow "Status(..)","or",D.dullyellow "Entity(..)"
1116 ,"though.","It","is","all","or","nothing,","otherwise","`case`"
1117 ,"expressions","could","miss","a","variant","and","crash!"
1119 , D.toSimpleNote $
1120 "It is often best to keep the variants hidden! If someone pattern matches on\
1121 \ the variants, it is a MAJOR change if any new variants are added. Suddenly\
1122 \ their `case` expressions do not cover all variants! So if you do not need\
1123 \ people to pattern match, keep the variants hidden and expose functions to\
1124 \ construct values of this type. This way you can add new variants as a MINOR change!"
1128 ExposingIndentEnd row col ->
1129 let
1130 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1131 region = toRegion row col
1132 in
1133 Report.Report "UNFINISHED EXPOSING" region [] $
1134 Code.toSnippet source surroundings (Just region)
1136 D.reflow $
1137 "I was partway through parsing exposed values, but I got stuck here:"
1139 D.stack
1140 [ D.fillSep $
1141 ["I","was","expecting","a","closing","parenthesis."
1142 ,"Try","adding","a",D.green ")","right","here?"
1144 , D.toSimpleNote $
1145 "I can get confused when there is not enough indentation, so if you already\
1146 \ have a closing parenthesis, it probably just needs some spaces in front of it."
1150 ExposingIndentValue row col ->
1151 let
1152 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1153 region = toRegion row col
1154 in
1155 Report.Report "UNFINISHED EXPOSING" region [] $
1156 Code.toSnippet source surroundings (Just region)
1158 D.reflow $
1159 "I was partway through parsing exposed values, but I got stuck here:"
1161 D.reflow $
1162 "I was expecting another value to expose."
1167-- SPACES
1170toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
1171toSpaceReport source space row col =
1172 case space of
1173 HasTab ->
1174 let
1175 region = toRegion row col
1176 in
1177 Report.Report "NO TABS" region [] $
1178 Code.toSnippet source region Nothing
1180 D.reflow $
1181 "I ran into a tab, but tabs are not allowed in Elm files."
1183 D.reflow $
1184 "Replace the tab with spaces."
1187 EndlessMultiComment ->
1188 let
1189 region = toWiderRegion row col 2
1190 in
1191 Report.Report "ENDLESS COMMENT" region [] $
1192 Code.toSnippet source region Nothing
1194 D.reflow $
1195 "I cannot find the end of this multi-line comment:"
1197 D.stack -- "{-"
1198 [ D.reflow "Add a -} somewhere after this to end the comment."
1199 , D.toSimpleHint
1200 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
1201 \ that happens to contain another comment. Like parentheses and curly braces,\
1202 \ the start and end markers must always be balanced. Maybe that is the problem?"
1208-- DECLARATIONS
1211toRegion :: Row -> Col -> A.Region
1212toRegion row col =
1213 let
1214 pos = A.Position row col
1215 in
1216 A.Region pos pos
1219toWiderRegion :: Row -> Col -> Word16 -> A.Region
1220toWiderRegion row col extra =
1221 A.Region
1222 (A.Position row col)
1223 (A.Position row (col + extra))
1226toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
1227toKeywordRegion row col keyword =
1228 A.Region
1229 (A.Position row col)
1230 (A.Position row (col + fromIntegral (length keyword)))
1233toDeclarationsReport :: Code.Source -> Decl -> Report.Report
1234toDeclarationsReport source decl =
1235 case decl of
1236 DeclStart row col ->
1237 error "TODO DeclStart" row col
1239 DeclSpace space row col ->
1240 toSpaceReport source space row col
1242 Port port_ row col ->
1243 toPortReport source port_ row col
1245 DeclType declType row col ->
1246 toDeclTypeReport source declType row col
1248 DeclDef name declDef row col ->
1249 toDeclDefReport source name declDef row col
1251 DeclFreshLineStart row col ->
1252 error "TODO DeclFreshLineStart" row col
1254 DeclFreshLineAfterDocComment row col ->
1255 error "TODO DeclFreshLineAfterDocComment" row col
1259-- PORT
1262toPortReport :: Code.Source -> Port -> Row -> Col -> Report.Report
1263toPortReport source port_ startRow startCol =
1264 case port_ of
1265 PortSpace space row col ->
1266 toSpaceReport source space row col
1268 PortName row col ->
1269 case Code.whatIsNext source row col of
1270 Code.Keyword keyword ->
1271 let
1272 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1273 region = toKeywordRegion row col keyword
1274 in
1275 Report.Report "RESERVED WORD" region [] $
1276 Code.toSnippet source surroundings (Just region)
1278 D.reflow $
1279 "I cannot handle ports with names like this:"
1281 D.reflow $
1282 "You are trying to make a port named `" ++ keyword
1283 ++ "` but that is a reserved word. Try using some other name?"
1286 _ ->
1287 let
1288 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1289 region = toRegion row col
1290 in
1291 Report.Report "PORT PROBLEM" region [] $
1292 Code.toSnippet source surroundings (Just region)
1294 D.reflow $
1295 "I just saw the start of a `port` declaration, but then I got stuck here:"
1297 D.stack
1298 [ D.fillSep
1299 ["I","was","expecting","to","see","a","name","like"
1300 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1301 ,"Something","that","starts","with","a","lower-case","letter."
1303 , portNote
1307 PortColon row col ->
1308 let
1309 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1310 region = toRegion row col
1311 in
1312 Report.Report "PORT PROBLEM" region [] $
1313 Code.toSnippet source surroundings (Just region)
1315 D.reflow $
1316 "I just saw the start of a `port` declaration, but then I got stuck here:"
1318 D.stack
1319 [ D.reflow $
1320 "I was expecting to see a colon next. And then a type that tells me\
1321 \ what type of values are going to flow through."
1322 , portNote
1326 PortType tipe row col ->
1327 toTypeReport source tipe row col
1329 PortIndentName row col ->
1330 let
1331 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1332 region = toRegion row col
1333 in
1334 Report.Report "UNFINISHED PORT" region [] $
1335 Code.toSnippet source surroundings (Just region)
1337 D.reflow $
1338 "I just saw the start of a `port` declaration, but then I got stuck here:"
1340 D.stack
1341 [ D.fillSep
1342 ["I","was","expecting","to","see","a","name","like"
1343 ,D.dullyellow "send","or",D.dullyellow "receive","next."
1344 ,"Something","that","starts","with","a","lower-case","letter."
1346 , portNote
1350 PortIndentColon row col ->
1351 let
1352 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1353 region = toRegion row col
1354 in
1355 Report.Report "UNFINISHED PORT" region [] $
1356 Code.toSnippet source surroundings (Just region)
1358 D.reflow $
1359 "I just saw the start of a `port` declaration, but then I got stuck here:"
1361 D.stack
1362 [ D.reflow $
1363 "I was expecting to see a colon next. And then a type that tells me\
1364 \ what type of values are going to flow through."
1365 , portNote
1369 PortIndentType row col ->
1370 let
1371 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1372 region = toRegion row col
1373 in
1374 Report.Report "UNFINISHED PORT" region [] $
1375 Code.toSnippet source surroundings (Just region)
1377 D.reflow $
1378 "I just saw the start of a `port` declaration, but then I got stuck here:"
1380 D.stack
1381 [ D.reflow $
1382 "I was expecting to see a type next. Here are examples of outgoing and\
1383 \ incoming ports for reference:"
1384 , D.vcat
1385 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1386 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1388 , D.reflow $
1389 "The first line defines a `send` port so you can send strings out to JavaScript.\
1390 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1391 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1392 \ get receive messages when new WebSocket messages come in or when an entry in\
1393 \ IndexedDB changes for some external reason."
1398portNote :: D.Doc
1399portNote =
1400 D.stack
1401 [ D.toSimpleNote $
1402 "Here are some example `port` declarations for reference:"
1403 , D.vcat
1404 [ D.fillSep [D.cyan "port","send",":","String -> Cmd msg"]
1405 , D.fillSep [D.cyan "port","receive",":","(String -> msg) -> Sub msg"]
1407 , D.reflow $
1408 "The first line defines a `send` port so you can send strings out to JavaScript.\
1409 \ Maybe you send them on a WebSocket or put them into IndexedDB. The second line\
1410 \ defines a `receive` port so you can receive strings from JavaScript. Maybe you\
1411 \ get receive messages when new WebSocket messages come in or when the IndexedDB\
1412 \ is changed for some external reason."
1417-- DECL TYPE
1420toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
1421toDeclTypeReport source declType startRow startCol =
1422 case declType of
1423 DT_Space space row col ->
1424 toSpaceReport source space row col
1426 DT_Name row col ->
1427 let
1428 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1429 region = toRegion row col
1430 in
1431 Report.Report "EXPECTING TYPE NAME" region [] $
1432 Code.toSnippet source surroundings (Just region)
1434 D.reflow $
1435 "I think I am parsing a type declaration, but I got stuck here:"
1437 D.stack
1438 [ D.fillSep $
1439 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1440 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1442 , customTypeNote
1446 DT_Alias typeAlias row col ->
1447 toTypeAliasReport source typeAlias row col
1449 DT_Union customType row col ->
1450 toCustomTypeReport source customType row col
1452 DT_IndentName row col ->
1453 let
1454 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1455 region = toRegion row col
1456 in
1457 Report.Report "EXPECTING TYPE NAME" region [] $
1458 Code.toSnippet source surroundings (Just region)
1460 D.reflow $
1461 "I think I am parsing a type declaration, but I got stuck here:"
1463 D.stack
1464 [ D.fillSep $
1465 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1466 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1468 , customTypeNote
1473toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1474toTypeAliasReport source typeAlias startRow startCol =
1475 case typeAlias of
1476 AliasSpace space row col ->
1477 toSpaceReport source space row col
1479 AliasName row col ->
1480 let
1481 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1482 region = toRegion row col
1483 in
1484 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1485 Code.toSnippet source surroundings (Just region)
1487 D.reflow $
1488 "I am partway through parsing a type alias, but I got stuck here:"
1490 D.stack
1491 [ D.fillSep $
1492 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1493 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1495 , typeAliasNote
1499 AliasEquals row col ->
1500 case Code.whatIsNext source row col of
1501 Code.Keyword keyword ->
1502 let
1503 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1504 region = toKeywordRegion row col keyword
1505 in
1506 Report.Report "RESERVED WORD" region [] $
1507 Code.toSnippet source surroundings (Just region)
1509 D.reflow $
1510 "I ran into a reserved word unexpectedly while parsing this type alias:"
1512 D.stack
1513 [ D.reflow $
1514 "It looks like you are trying use `" ++ keyword
1515 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1516 , typeAliasNote
1520 _ ->
1521 let
1522 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1523 region = toRegion row col
1524 in
1525 Report.Report "PROBLEM IN TYPE ALIAS" region [] $
1526 Code.toSnippet source surroundings (Just region)
1528 D.reflow $
1529 "I am partway through parsing a type alias, but I got stuck here:"
1531 D.stack
1532 [ D.reflow $
1533 "I was expecting to see a type variable or an an equals sign next."
1534 , typeAliasNote
1538 AliasBody tipe row col ->
1539 toTypeReport source tipe row col
1541 AliasIndentEquals row col ->
1542 let
1543 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1544 region = toRegion row col
1545 in
1546 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1547 Code.toSnippet source surroundings (Just region)
1549 D.reflow $
1550 "I am partway through parsing a type alias, but I got stuck here:"
1552 D.stack
1553 [ D.reflow $
1554 "I was expecting to see a type variable or an an equals sign next."
1555 , typeAliasNote
1559 AliasIndentBody row col ->
1560 let
1561 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1562 region = toRegion row col
1563 in
1564 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1565 Code.toSnippet source surroundings (Just region)
1567 D.reflow $
1568 "I am partway through parsing a type alias, but I got stuck here:"
1570 D.stack
1571 [ D.fillSep $
1572 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1573 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1575 , typeAliasNote
1580typeAliasNote :: D.Doc
1581typeAliasNote =
1582 D.stack
1583 [ D.toSimpleNote $
1584 "Here is an example of a valid `type alias` for reference:"
1585 , D.vcat $
1586 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1587 , D.indent 2 $ D.vcat $
1588 ["{ name : String"
1589 ,", age : Int"
1590 ,", height : Float"
1591 ,"}"
1594 , D.reflow $
1595 "This would let us use `Person` as a shorthand for that record type. Using this\
1596 \ shorthand makes type annotations much easier to read, and makes changing code\
1597 \ easier if you decide later that there is more to a person than age and height!"
1601toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1602toCustomTypeReport source customType startRow startCol =
1603 case customType of
1604 CT_Space space row col ->
1605 toSpaceReport source space row col
1607 CT_Name row col ->
1608 let
1609 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1610 region = toRegion row col
1611 in
1612 Report.Report "EXPECTING TYPE NAME" region [] $
1613 Code.toSnippet source surroundings (Just region)
1615 D.reflow $
1616 "I think I am parsing a type declaration, but I got stuck here:"
1618 D.stack
1619 [ D.fillSep $
1620 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1621 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1623 , customTypeNote
1627 CT_Equals row col ->
1628 case Code.whatIsNext source row col of
1629 Code.Keyword keyword ->
1630 let
1631 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1632 region = toKeywordRegion row col keyword
1633 in
1634 Report.Report "RESERVED WORD" region [] $
1635 Code.toSnippet source surroundings (Just region)
1637 D.reflow $
1638 "I ran into a reserved word unexpectedly while parsing this custom type:"
1640 D.stack
1641 [ D.reflow $
1642 "It looks like you are trying use `" ++ keyword
1643 ++ "` as a type variable, but it is a reserved word. Try using a different name?"
1644 , customTypeNote
1648 _ ->
1649 let
1650 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1651 region = toRegion row col
1652 in
1653 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1654 Code.toSnippet source surroundings (Just region)
1656 D.reflow $
1657 "I am partway through parsing a custom type, but I got stuck here:"
1659 D.stack
1660 [ D.reflow $
1661 "I was expecting to see a type variable or an an equals sign next."
1662 , customTypeNote
1666 CT_Bar row col ->
1667 let
1668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1669 region = toRegion row col
1670 in
1671 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1672 Code.toSnippet source surroundings (Just region)
1674 D.reflow $
1675 "I am partway through parsing a custom type, but I got stuck here:"
1677 D.stack
1678 [ D.reflow $
1679 "I was expecting to see a vertical bar like | next."
1680 , customTypeNote
1684 CT_Variant row col ->
1685 let
1686 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1687 region = toRegion row col
1688 in
1689 Report.Report "PROBLEM IN CUSTOM TYPE" region [] $
1690 Code.toSnippet source surroundings (Just region)
1692 D.reflow $
1693 "I am partway through parsing a custom type, but I got stuck here:"
1695 D.stack
1696 [ D.fillSep $
1697 ["I","was","expecting","to","see","a","variant","name","next."
1698 ,"Something","like",D.dullyellow "Success","or",D.dullyellow "Sandwich" <> "."
1699 ,"Any","name","that","starts","with","a","capital","letter","really!"
1701 , customTypeNote
1705 CT_VariantArg tipe row col ->
1706 toTypeReport source tipe row col
1708 CT_IndentEquals row col ->
1709 let
1710 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1711 region = toRegion row col
1712 in
1713 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1714 Code.toSnippet source surroundings (Just region)
1716 D.reflow $
1717 "I am partway through parsing a custom type, but I got stuck here:"
1719 D.stack
1720 [ D.reflow $
1721 "I was expecting to see a type variable or an an equals sign next."
1722 , customTypeNote
1726 CT_IndentBar row col ->
1727 let
1728 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1729 region = toRegion row col
1730 in
1731 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1732 Code.toSnippet source surroundings (Just region)
1734 D.reflow $
1735 "I am partway through parsing a custom type, but I got stuck here:"
1737 D.stack
1738 [ D.reflow $
1739 "I was expecting to see a vertical bar like | next."
1740 , customTypeNote
1744 CT_IndentAfterBar row col ->
1745 let
1746 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1747 region = toRegion row col
1748 in
1749 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1750 Code.toSnippet source surroundings (Just region)
1752 D.reflow $
1753 "I am partway through parsing a custom type, but I got stuck here:"
1755 D.stack
1756 [ D.reflow $
1757 "I just saw a vertical bar, so I was expecting to see another variant defined next."
1758 , customTypeNote
1762 CT_IndentAfterEquals row col ->
1763 let
1764 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1765 region = toRegion row col
1766 in
1767 Report.Report "UNFINISHED CUSTOM TYPE" region [] $
1768 Code.toSnippet source surroundings (Just region)
1770 D.reflow $
1771 "I am partway through parsing a custom type, but I got stuck here:"
1773 D.stack
1774 [ D.reflow $
1775 "I just saw an equals sign, so I was expecting to see the first variant defined next."
1776 , customTypeNote
1781customTypeNote :: D.Doc
1782customTypeNote =
1783 D.stack
1784 [ D.toSimpleNote $
1785 "Here is an example of a valid `type` declaration for reference:"
1786 , D.vcat $
1787 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1788 , D.indent 2 $ D.fillSep ["=","Failure"]
1789 , D.indent 2 $ D.fillSep ["|","Waiting"]
1790 , D.indent 2 $ D.fillSep ["|","Success","String"]
1792 , D.reflow $
1793 "This defines a new `Status` type with three variants. This could be useful if\
1794 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1795 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1796 \ things go. Notice that the Success variant has some associated data, allowing\
1797 \ us to store a String if the request goes well!"
1802-- DECL DEF
1805toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
1806toDeclDefReport source name declDef startRow startCol =
1807 case declDef of
1808 DeclDefSpace space row col ->
1809 toSpaceReport source space row col
1811 DeclDefEquals row col ->
1812 case Code.whatIsNext source row col of
1813 Code.Keyword keyword ->
1814 let
1815 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1816 region = toKeywordRegion row col keyword
1817 in
1818 Report.Report "RESERVED WORD" region [] $
1819 Code.toSnippet source surroundings (Just region)
1821 D.reflow $
1822 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
1824 D.reflow $
1825 "This is a reserved word! Try using some other name?"
1828 Code.Operator op ->
1829 let
1830 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1831 region = toKeywordRegion row col op
1832 in
1833 Report.Report "UNEXPECTED SYMBOL" region [] $
1834 Code.toSnippet source surroundings (Just region)
1836 D.reflow $
1837 "I was not expecting to see this symbol here:"
1839 D.stack
1840 [ D.reflow $
1841 "I am not sure what is going wrong exactly, so here is a valid\
1842 \ definition (with an optional type annotation) for reference:"
1843 , D.vcat
1844 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1845 , D.fillSep [D.green "add","x","y","="]
1846 , D.fillSep [" ","x","+","y"]
1848 , D.reflow $
1849 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
1853 _ ->
1854 let
1855 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1856 region = toRegion row col
1857 in
1858 Report.Report "PROBLEM IN DEFINITION" region [] $
1859 Code.toSnippet source surroundings (Just region)
1861 D.reflow $
1862 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1864 D.stack
1865 [ D.reflow $
1866 "I am not sure what is going wrong exactly, so here is a valid\
1867 \ definition (with an optional type annotation) for reference:"
1868 , D.vcat
1869 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1870 , D.fillSep [D.green "add","x","y","="]
1871 , D.fillSep [" ","x","+","y"]
1873 , D.reflow $
1874 "Try to use that format!"
1878 DeclDefType tipe row col ->
1879 toTypeReport source tipe row col
1881 DeclDefArg pattern row col ->
1882 toPatternReport source PArg pattern row col
1884 DeclDefBody expr row col ->
1885 toExprReport source (InDef name startRow startCol) expr row col
1887 DeclDefNameRepeat row col ->
1888 let
1889 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1890 region = toRegion row col
1891 in
1892 Report.Report "EXPECTING DEFINITION" region [] $
1893 Code.toSnippet source surroundings (Just region)
1895 D.reflow $
1896 "I just saw the type annotation for `" ++ Name.toChars name
1897 ++ "` so I was expecting to see its definition here:"
1899 D.stack
1900 [ D.reflow $
1901 "Type annotations always appear directly above the relevant\
1902 \ definition, without anything else (even doc comments) in between."
1903 , declDefNote
1907 DeclDefNameMatch defName row col ->
1908 let
1909 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1910 region = toRegion row col
1911 in
1912 Report.Report "NAME MISMATCH" region [] $
1913 Code.toSnippet source surroundings (Just region)
1915 D.reflow $
1916 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
1918 D.stack
1919 [ D.reflow $
1920 "These names do not match! Is there a typo?"
1921 , D.indent 4 $ D.fillSep $
1922 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
1926 DeclDefIndentType row col ->
1927 let
1928 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1929 region = toRegion row col
1930 in
1931 Report.Report "UNFINISHED DEFINITION" region [] $
1932 Code.toSnippet source surroundings (Just region)
1934 D.reflow $
1935 "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
1937 D.stack
1938 [ D.reflow $
1939 "I just saw a colon, so I am expecting to see a type next."
1940 , declDefNote
1944 DeclDefIndentEquals row col ->
1945 let
1946 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1947 region = toRegion row col
1948 in
1949 Report.Report "UNFINISHED DEFINITION" region [] $
1950 Code.toSnippet source surroundings (Just region)
1952 D.reflow $
1953 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1955 D.stack
1956 [ D.reflow $
1957 "I was expecting to see an argument or an equals sign next."
1958 , declDefNote
1962 DeclDefIndentBody row col ->
1963 let
1964 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1965 region = toRegion row col
1966 in
1967 Report.Report "UNFINISHED DEFINITION" region [] $
1968 Code.toSnippet source surroundings (Just region)
1970 D.reflow $
1971 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1973 D.stack
1974 [ D.reflow $
1975 "I was expecting to see an expression next. What is it equal to?"
1976 , declDefNote
1981declDefNote :: D.Doc
1982declDefNote =
1983 D.stack
1984 [ D.reflow $
1985 "Here is a valid definition (with a type annotation) for reference:"
1986 , D.vcat
1987 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1988 , D.fillSep [D.green "add","x","y","="]
1989 , D.fillSep [" ","x","+","y"]
1991 , D.reflow $
1992 "The top line (called a \"type annotation\") is optional. You can leave it off\
1993 \ if you want. As you get more comfortable with Elm and as your project grows,\
1994 \ it becomes more and more valuable to add them though! They work great as\
1995 \ compiler-verified documentation, and they often improve error messages!"
2000-- CONTEXT
2003data Context
2004 = InNode Node Row Col Context
2005 | InDef Name.Name Row Col
2008data Node
2009 = NRecord
2010 | NParens
2011 | NList
2012 | NFunc
2013 | NCond
2014 | NThen
2015 | NElse
2016 | NCase
2017 | NBranch
2018 deriving (Eq)
2021getDefName :: Context -> Name.Name
2022getDefName context =
2023 case context of
2024 InDef name _ _ -> name
2025 InNode _ _ _ c -> getDefName c
2028isWithin :: Node -> Context -> Bool
2029isWithin desiredNode context =
2030 case context of
2031 InDef _ _ _ -> False
2032 InNode actualNode _ _ _ -> desiredNode == actualNode
2036-- EXPR REPORTS
2039toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
2040toExprReport source context expr startRow startCol =
2041 case expr of
2042 Let let_ row col ->
2043 toLetReport source context let_ row col
2045 Case case_ row col ->
2046 toCaseReport source context case_ row col
2048 If if_ row col ->
2049 toIfReport source context if_ row col
2051 List list row col ->
2052 toListReport source context list row col
2054 Record record row col ->
2055 toRecordReport source context record row col
2057 Tuple tuple row col ->
2058 toTupleReport source context tuple row col
2060 Func func row col ->
2061 toFuncReport source context func row col
2063 Dot row col ->
2064 let region = toRegion row col in
2065 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2066 Code.toSnippet source region Nothing
2068 D.reflow $
2069 "I was expecting to see a record accessor here:"
2071 D.fillSep
2072 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2073 ,"that","accesses","a","value","from","a","record."
2077 Access row col ->
2078 let region = toRegion row col in
2079 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
2080 Code.toSnippet source region Nothing
2082 D.reflow $
2083 "I am trying to parse a record accessor here:"
2085 D.stack
2087 D.fillSep
2088 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
2089 ,"that","accesses","a","value","from","a","record."
2092 D.toSimpleNote $
2093 "Record field names must start with a lower case letter!"
2097 OperatorRight op row col ->
2098 let region = toRegion row col in
2099 Report.Report "MISSING EXPRESSION" region [] $
2100 Code.toSnippet source region Nothing
2102 D.reflow $
2103 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2105 D.stack
2106 [ D.fillSep $
2107 ["You","can","just","put","anything","for","now,","like"
2108 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2109 ,"Once","there","is","something","there,","I","can","probably"
2110 ,"give","a","more","specific","hint!"
2112 , D.toSimpleNote $
2113 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2114 \ Or if I run into operators in unexpected spots. Point is, there are a\
2115 \ couple ways I can get confused and give sort of weird advice!"
2119 OperatorReserved operator row col ->
2120 toOperatorReport source context operator row col
2122 Start row col ->
2123 let
2124 (contextRow, contextCol, aThing) =
2125 case context of
2126 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
2127 InNode NRecord r c _ -> (r, c, "a record")
2128 InNode NParens r c _ -> (r, c, "some parentheses")
2129 InNode NList r c _ -> (r, c, "a list")
2130 InNode NFunc r c _ -> (r, c, "an anonymous function")
2131 InNode NCond r c _ -> (r, c, "an `if` expression")
2132 InNode NThen r c _ -> (r, c, "an `if` expression")
2133 InNode NElse r c _ -> (r, c, "an `if` expression")
2134 InNode NCase r c _ -> (r, c, "a `case` expression")
2135 InNode NBranch r c _ -> (r, c, "a `case` expression")
2136 -- TODO check if this is actually the best way to get error messages here
2138 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
2139 region = toRegion row col
2140 in
2141 Report.Report "MISSING EXPRESSION" region [] $
2142 Code.toSnippet source surroundings (Just region)
2144 D.reflow $
2145 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
2147 D.stack
2148 [ D.fillSep $
2149 ["I","was","expecting","to","see","an","expression","like"
2150 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2151 ,"Once","there","is","something","there,","I","can","probably"
2152 ,"give","a","more","specific","hint!"
2154 , D.toSimpleNote $
2155 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
2156 \ Or if I run into operators in unexpected spots. Point is, there are a\
2157 \ couple ways I can get confused and give sort of weird advice!"
2161 Char char row col ->
2162 toCharReport source char row col
2164 String string row col ->
2165 toStringReport source string row col
2167 Number number row col ->
2168 toNumberReport source number row col
2170 Space space row col ->
2171 toSpaceReport source space row col
2173 EndlessShader row col ->
2174 let
2175 region = toWiderRegion row col 6
2176 in
2177 Report.Report "ENDLESS SHADER" region [] $
2178 Code.toSnippet source region Nothing
2180 D.reflow "I cannot find the end of this shader:"
2182 D.reflow "Add a |] somewhere after this to end the shader."
2185 ShaderProblem problem row col ->
2186 let
2187 region = toRegion row col
2188 in
2189 Report.Report "SHADER PROBLEM" region [] $
2190 Code.toSnippet source region Nothing
2192 D.reflow $
2193 "I ran into a problem while parsing this GLSL block."
2195 D.stack
2196 [ D.reflow $
2197 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
2198 , D.indent 4 $ D.vcat $
2199 map D.fromChars (filter (/="") (lines problem))
2203 IndentOperatorRight op row col ->
2204 let
2205 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2206 region = toRegion row col
2207 in
2208 Report.Report "MISSING EXPRESSION" region [] $
2209 Code.toSnippet source surroundings (Just region)
2211 D.reflow $
2212 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
2214 D.stack
2216 D.fillSep $
2217 ["You","can","just","put","anything","for","now,","like"
2218 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
2219 ,"Once","there","is","something","there,","I","can","probably"
2220 ,"give","a","more","specific","hint!"
2223 D.toSimpleNote $
2224 "I may be getting confused by your indentation? The easiest way to make sure\
2225 \ this is not an indentation problem is to put the expression on the right of\
2226 \ the " ++ Name.toChars op ++ " operator on the same line."
2230 IndentMoreExpr _ _ ->
2231 error "TODO IndentMoreExpr"
2235-- CHAR
2238toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
2239toCharReport source char row col =
2240 case char of
2241 CharEndless ->
2242 let
2243 region = toRegion row col
2244 in
2245 Report.Report "MISSING SINGLE QUOTE" region [] $
2246 Code.toSnippet source region Nothing
2248 D.reflow $
2249 "I thought I was parsing a character, but I got to the end of\
2250 \ the line without seeing the closing single quote:"
2252 D.reflow $
2253 "Add a closing single quote here!"
2256 CharEscape escape ->
2257 toEscapeReport source escape row col
2259 CharNotString width ->
2260 let
2261 region = toWiderRegion row col width
2262 in
2263 Report.Report "NEEDS DOUBLE QUOTES" region [] $
2264 Code.toSnippet source region Nothing
2266 "The following string uses single quotes:"
2268 D.stack
2269 [ "Please switch to double quotes instead:"
2270 , D.indent 4 $
2271 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
2272 , D.toSimpleNote $
2273 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
2274 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
2275 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
2276 \ individual characters."
2282-- STRING
2285toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
2286toStringReport source string row col =
2287 case string of
2288 StringEndless_Single ->
2289 let
2290 region = toRegion row col
2291 in
2292 Report.Report "ENDLESS STRING" region [] $
2293 Code.toSnippet source region Nothing
2295 D.reflow $
2296 "I got to the end of the line without seeing the closing double quote:"
2298 D.stack
2299 [ D.fillSep $
2300 ["Strings","look","like",D.green "\"this\"","with","double"
2301 ,"quotes","on","each","end.","Is","the","closing","double"
2302 ,"quote","missing","in","your","code?"
2304 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
2308 StringEndless_Multi ->
2309 let
2310 region = toWiderRegion row col 3
2311 in
2312 Report.Report "ENDLESS STRING" region [] $
2313 Code.toSnippet source region Nothing
2315 D.reflow $
2316 "I cannot find the end of this multi-line string:"
2318 D.stack
2319 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
2320 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
2324 StringEscape escape ->
2325 toEscapeReport source escape row col
2329-- ESCAPES
2332toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
2333toEscapeReport source escape row col =
2334 case escape of
2335 EscapeUnknown ->
2336 let
2337 region = toWiderRegion row col 2
2338 in
2339 Report.Report "UNKNOWN ESCAPE" region [] $
2340 Code.toSnippet source region Nothing
2342 D.reflow $
2343 "Backslashes always start escaped characters, but I do not recognize this one:"
2345 D.stack
2346 [ D.reflow $
2347 "Valid escape characters include:"
2348 , D.dullyellow $ D.indent 4 $ D.vcat $
2349 [ "\\n"
2350 , "\\r"
2351 , "\\t"
2352 , "\\\""
2353 , "\\\'"
2354 , "\\\\"
2355 , "\\u{003D}"
2357 , D.reflow $
2358 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
2359 , D.toSimpleNote $
2360 "The last style lets encode ANY character by its Unicode code\
2361 \ point. That means \\u{0009} and \\t are the same. You can use\
2362 \ that style for anything not covered by the other six escapes!"
2366 BadUnicodeFormat width ->
2367 let
2368 region = toWiderRegion row col width
2369 in
2370 Report.Report "BAD UNICODE ESCAPE" region [] $
2371 Code.toSnippet source region Nothing
2373 D.reflow $
2374 "I ran into an invalid Unicode escape:"
2376 D.stack
2377 [ D.reflow $
2378 "Here are some examples of valid Unicode escapes:"
2379 , D.dullyellow $ D.indent 4 $ D.vcat $
2380 [ "\\u{0041}"
2381 , "\\u{03BB}"
2382 , "\\u{6728}"
2383 , "\\u{1F60A}"
2385 , D.reflow $
2386 "Notice that the code point is always surrounded by curly braces.\
2387 \ Maybe you are missing the opening or closing curly brace?"
2390 BadUnicodeCode width ->
2391 let
2392 region = toWiderRegion row col width
2393 in
2394 Report.Report "BAD UNICODE ESCAPE" region [] $
2395 Code.toSnippet source region Nothing
2397 D.reflow $
2398 "This is not a valid code point:"
2400 D.reflow $
2401 "The valid code points are between 0 and 10FFFF inclusive."
2404 BadUnicodeLength width numDigits badCode ->
2405 let
2406 region = toWiderRegion row col width
2407 in
2408 Report.Report "BAD UNICODE ESCAPE" region [] $
2409 Code.toSnippet source region Nothing $
2410 if numDigits < 4 then
2412 D.reflow $
2413 "Every code point needs at least four digits:"
2415 let
2416 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
2417 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
2418 in
2419 D.fillSep ["Try",D.green suggestion,"instead?"]
2422 else
2424 D.reflow $
2425 "This code point has too many digits:"
2427 D.fillSep $
2428 ["Valid","code","points","are","between"
2429 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
2430 ,"so","try","trimming","any","leading","zeros","until"
2431 ,"you","have","between","four","and","six","digits."
2437-- NUMBERS
2440toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
2441toNumberReport source number row col =
2442 let
2443 region = toRegion row col
2444 in
2445 case number of
2446 NumberEnd ->
2447 Report.Report "WEIRD NUMBER" region [] $
2448 Code.toSnippet source region Nothing
2450 D.reflow $
2451 "I thought I was reading a number, but I ran into some weird stuff here:"
2453 D.stack
2454 [ D.reflow $
2455 "I recognize numbers in the following formats:"
2456 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
2457 , D.reflow $
2458 "So is there a way to write it like one of those?"
2462 NumberDot int ->
2463 Report.Report "WEIRD NUMBER" region [] $
2464 Code.toSnippet source region Nothing
2466 D.reflow $
2467 "Numbers cannot end with a dot like this:"
2469 D.fillSep
2470 ["Switching","to",D.green (D.fromChars (show int))
2471 ,"or",D.green (D.fromChars (show int ++ ".0"))
2472 ,"will","work","though!"
2476 NumberHexDigit ->
2477 Report.Report "WEIRD HEXIDECIMAL" region [] $
2478 Code.toSnippet source region Nothing
2480 D.reflow $
2481 "I thought I was reading a hexidecimal number until I got here:"
2483 D.stack
2484 [ D.reflow $
2485 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
2486 \ only recognize things like this:"
2487 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
2491 NumberNoLeadingZero ->
2492 Report.Report "LEADING ZEROS" region [] $
2493 Code.toSnippet source region Nothing
2495 D.reflow $
2496 "I do not accept numbers with leading zeros:"
2498 D.stack
2499 [ D.reflow $
2500 "Just delete the leading zeros and it should work!"
2501 , D.toSimpleNote $
2502 "Some languages let you to specify octal numbers by adding a leading zero.\
2503 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
2504 \ that, but others probably want it to equal 111. Either path is going to\
2505 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
2506 \ situation."
2512-- OPERATORS
2515toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
2516toOperatorReport source context operator row col =
2517 case operator of
2518 BadDot ->
2519 let
2520 region = toRegion row col
2521 in
2522 Report.Report "UNEXPECTED SYMBOL" region [] $
2523 Code.toSnippet source region Nothing
2525 "I was not expecting this dot:"
2527 D.reflow $
2528 "Dots are for record access and decimal points, so\
2529 \ they cannot float around on their own. Maybe\
2530 \ there is some extra whitespace?"
2533 BadPipe ->
2534 let
2535 region = toRegion row col
2536 in
2537 Report.Report "UNEXPECTED SYMBOL" region [] $
2538 Code.toSnippet source region Nothing
2540 D.reflow $
2541 "I was not expecting this vertical bar:"
2543 D.reflow $
2544 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
2547 BadArrow ->
2548 let
2549 region = toWiderRegion row col 2
2550 in
2551 Report.Report "UNEXPECTED ARROW" region [] $
2552 Code.toSnippet source region Nothing $
2553 if isWithin NBranch context then
2555 D.reflow $
2556 "I was not expecting to see an arrow here:"
2558 D.stack
2560 D.reflow $
2561 "I think I am parsing a `case` expression right now, so it makes sense to\
2562 \ see arrows around here. This one is confusing me though!"
2564 D.toSimpleHint $
2565 "I may be getting confused by the indentation. Every pattern in a `case` must be\
2566 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
2567 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
2568 \ indented too far?"
2572 else
2574 D.reflow $
2575 "I was not expecting an arrow here:"
2577 D.reflow $
2578 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
2579 \ you want > or >= instead?"
2582 BadEquals ->
2583 let
2584 region = toRegion row col
2585 name = getDefName context
2586 in
2587 Report.Report "UNEXPECTED EQUALS" region [] $
2588 Code.toSnippet source region Nothing
2590 D.reflow $
2591 "I was not expecting to see this equals sign:"
2593 D.stack
2595 D.reflow "Maybe you want == instead? To check if two values are equal?"
2597 D.toSimpleNote $
2598 if isWithin NRecord context then
2599 "Records look like { x = 3, y = 4 } with the equals sign right\
2600 \ after the field name. So maybe you forgot a comma?"
2601 else
2602 "I may be getting confused by your indentation. Is this supposed to be part of\
2603 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2604 \ the problem may be a bit before the equals sign. I need all definitions to\
2605 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2606 \ this new definition is indented a bit too much."
2610 BadHasType ->
2611 let
2612 region = toRegion row col
2613 name = getDefName context
2614 in
2615 Report.Report "UNEXPECTED SYMBOL" region [] $
2616 Code.toSnippet source region Nothing $
2618 D.reflow $
2619 "I was not expecting to run into the \"has type\" symbol here:"
2621 D.stack
2623 D.fillSep
2624 ["Maybe","you","want",D.green "::","instead?"
2625 ,"To","put","something","on","the","front","of","a","list?"
2627 , D.toSimpleNote $
2628 "The single colon is reserved for type annotations and record types, but I think\
2629 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2631 D.toSimpleNote $
2632 "I may be getting confused by your indentation. Is this supposed to be part of\
2633 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2634 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2635 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2636 \ this new definition is indented a bit too much."
2642-- CASE
2645toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
2646toLetReport source context let_ startRow startCol =
2647 case let_ of
2648 LetSpace space row col ->
2649 toSpaceReport source space row col
2651 LetIn row col ->
2652 let
2653 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2654 region = toRegion row col
2655 in
2656 Report.Report "LET PROBLEM" region [] $
2657 Code.toSnippet source surroundings (Just region)
2659 D.reflow $
2660 "I was partway through parsing a `let` expression, but I got stuck here:"
2662 D.stack
2663 [ D.fillSep $
2664 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2665 ,"keyword","next.","Is","there","a","typo?"
2667 , D.toSimpleNote $
2668 "This can also happen if you are trying to define another value within the `let` but\
2669 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2670 \ spaces before it. They should line up exactly!"
2674 LetDefAlignment _ row col ->
2675 let
2676 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2677 region = toRegion row col
2678 in
2679 Report.Report "LET PROBLEM" region [] $
2680 Code.toSnippet source surroundings (Just region)
2682 D.reflow $
2683 "I was partway through parsing a `let` expression, but I got stuck here:"
2685 D.stack
2686 [ D.fillSep $
2687 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2688 ,"keyword","next.","Is","there","a","typo?"
2690 , D.toSimpleNote $
2691 "This can also happen if you are trying to define another value within the `let` but\
2692 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2693 \ spaces before it. The should line up exactly!"
2697 LetDefName row col ->
2698 case Code.whatIsNext source row col of
2699 Code.Keyword keyword ->
2700 let
2701 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2702 region = toKeywordRegion row col keyword
2703 in
2704 Report.Report "RESERVED WORD" region [] $
2705 Code.toSnippet source surroundings (Just region)
2707 D.reflow $
2708 "I was partway through parsing a `let` expression, but I got stuck here:"
2710 D.reflow $
2711 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
2712 \ it is a reserved word! Try using a different name instead."
2715 _ ->
2716 toUnfinishLetReport source row col startRow startCol $
2717 D.reflow $
2718 "I was expecting the name of a definition next."
2720 LetDef name def row col ->
2721 error "TODO LetDef" name def row col
2723 LetDestruct destruct row col ->
2724 error "TODO LetDestruct" destruct row col
2726 LetBody expr row col ->
2727 toExprReport source context expr row col
2729 LetIndentDef row col ->
2730 toUnfinishLetReport source row col startRow startCol $
2731 D.reflow $
2732 "I was expecting a value to be defined here."
2734 LetIndentIn row col ->
2735 toUnfinishLetReport source row col startRow startCol $
2736 D.fillSep $
2737 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
2738 ,"Or","maybe","more","of","that","expression?"
2741 LetIndentBody row col ->
2742 toUnfinishLetReport source row col startRow startCol $
2743 D.reflow $
2744 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
2747toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2748toUnfinishLetReport source row col startRow startCol message =
2749 let
2750 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2751 region = toRegion row col
2752 in
2753 Report.Report "UNFINISHED LET" region [] $
2754 Code.toSnippet source surroundings (Just region)
2756 D.reflow $
2757 "I was partway through parsing a `let` expression, but I got stuck here:"
2759 D.stack
2760 [ message
2761 , D.toSimpleNote $
2762 "Here is an example with a valid `let` expression for reference:"
2763 , D.vcat $
2764 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
2765 , D.indent 2 $ D.fillSep [D.cyan "let"]
2766 , D.indent 4 $ D.fillSep ["fullName","="]
2767 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
2768 , D.indent 2 $ D.fillSep [D.cyan "in"]
2769 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
2771 , D.reflow $
2772 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
2773 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
2774 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
2775 \ indented a bit more than that. That is important!"
2781-- CASE
2784toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
2785toCaseReport source context case_ startRow startCol =
2786 case case_ of
2787 CaseSpace space row col ->
2788 toSpaceReport source space row col
2790 CaseOf row col ->
2791 toUnfinishCaseReport source row col startRow startCol $
2792 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2794 CasePattern pattern row col ->
2795 toPatternReport source PCase pattern row col
2797 CaseArrow row col ->
2798 case Code.whatIsNext source row col of
2799 Code.Keyword keyword ->
2800 let
2801 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2802 region = toKeywordRegion row col keyword
2803 in
2804 Report.Report "RESERVED WORD" region [] $
2805 Code.toSnippet source surroundings (Just region)
2807 D.reflow $
2808 "I am partway through parsing a `case` expression, but I got stuck here:"
2810 D.reflow $
2811 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
2812 \ patterns, but it is a reserved word. Try using a different name?"
2815 Code.Operator ":" ->
2816 let
2817 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2818 region = toRegion row col
2819 in
2820 Report.Report "UNEXPECTED OPERATOR" region [] $
2821 Code.toSnippet source surroundings (Just region)
2823 D.reflow $
2824 "I am partway through parsing a `case` expression, but I got stuck here:"
2826 D.fillSep $
2827 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
2828 ,"For","pattern","matching","on","lists?"
2832 Code.Operator "=" ->
2833 let
2834 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2835 region = toRegion row col
2836 in
2837 Report.Report "UNEXPECTED OPERATOR" region [] $
2838 Code.toSnippet source surroundings (Just region)
2840 D.reflow $
2841 "I am partway through parsing a `case` expression, but I got stuck here:"
2843 D.fillSep $
2844 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
2848 _ ->
2849 let
2850 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2851 region = toRegion row col
2852 in
2853 Report.Report "MISSING ARROW" region [] $
2854 Code.toSnippet source surroundings (Just region)
2856 D.reflow $
2857 "I am partway through parsing a `case` expression, but I got stuck here:"
2859 addNoteForCaseIndentError $
2860 D.reflow $
2861 "I was expecting to see an arrow next."
2864 CaseExpr expr row col ->
2865 toExprReport source (InNode NCase startRow startCol context) expr row col
2867 CaseBranch expr row col ->
2868 toExprReport source (InNode NBranch startRow startCol context) expr row col
2870 CaseIndentOf row col ->
2871 toUnfinishCaseReport source row col startRow startCol $
2872 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2874 CaseIndentExpr row col ->
2875 toUnfinishCaseReport source row col startRow startCol $
2876 D.reflow "I was expecting to see a expression next."
2878 CaseIndentPattern row col ->
2879 toUnfinishCaseReport source row col startRow startCol $
2880 D.reflow "I was expecting to see a pattern next."
2882 CaseIndentArrow row col ->
2883 toUnfinishCaseReport source row col startRow startCol $
2884 D.fillSep
2885 ["I","just","saw","a","pattern,","so","I","was","expecting"
2886 ,"to","see","a",D.dullyellow "->","next."
2889 CaseIndentBranch row col ->
2890 toUnfinishCaseReport source row col startRow startCol $
2891 D.reflow $
2892 "I was expecting to see an expression next. What should I do when\
2893 \ I run into this particular pattern?"
2895 CasePatternAlignment indent row col ->
2896 toUnfinishCaseReport source row col startRow startCol $
2897 D.reflow $
2898 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
2901toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2902toUnfinishCaseReport source row col startRow startCol message =
2903 let
2904 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2905 region = toRegion row col
2906 in
2907 Report.Report "UNFINISHED CASE" region [] $
2908 Code.toSnippet source surroundings (Just region)
2910 D.reflow $
2911 "I was partway through parsing a `case` expression, but I got stuck here:"
2913 D.stack
2914 [ message
2915 , D.toSimpleNote $
2916 "Here is an example of a valid `case` expression for reference."
2917 , D.vcat $
2918 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2919 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2920 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2921 , ""
2922 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2923 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2925 , D.reflow $
2926 "Notice the indentation. Each pattern is aligned, and each branch is indented\
2927 \ a bit more than the corresponding pattern. That is important!"
2932addNoteForCaseIndentError :: D.Doc -> D.Doc
2933addNoteForCaseIndentError message =
2934 D.stack $
2935 message
2937 [ D.toSimpleNote $
2938 "Sometimes I get confused by indentation, so try to make your `case` look\
2939 \ something like this:"
2940 , D.vcat $
2941 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2942 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2943 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2944 , ""
2945 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2946 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2948 , D.reflow $
2949 "Notice the indentation! Each pattern is aligned, and each branch is indented\
2950 \ a bit more than the corresponding pattern. That is important!"
2955-- IF
2958toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
2959toIfReport source context if_ startRow startCol =
2960 case if_ of
2961 IfSpace space row col ->
2962 toSpaceReport source space row col
2964 IfThen 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 "UNFINISHED IF" region [] $
2970 Code.toSnippet source surroundings (Just region)
2972 D.reflow $
2973 "I was expecting to see more of this `if` expression, but I got stuck here:"
2975 D.fillSep $
2976 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2980 IfElse row col ->
2981 let
2982 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2983 region = toRegion row col
2984 in
2985 Report.Report "UNFINISHED IF" region [] $
2986 Code.toSnippet source surroundings (Just region)
2988 D.reflow $
2989 "I was expecting to see more of this `if` expression, but I got stuck here:"
2991 D.fillSep $
2992 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
2996 IfElseBranchStart row col ->
2997 let
2998 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2999 region = toRegion row col
3000 in
3001 Report.Report "UNFINISHED IF" region [] $
3002 Code.toSnippet source surroundings (Just region)
3004 D.reflow $
3005 "I just saw the start of an `else` branch, but then I got stuck here:"
3007 D.reflow $
3008 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3011 IfCondition expr row col ->
3012 toExprReport source (InNode NCond startRow startCol context) expr row col
3014 IfThenBranch expr row col ->
3015 toExprReport source (InNode NThen startRow startCol context) expr row col
3017 IfElseBranch expr row col ->
3018 toExprReport source (InNode NElse startRow startCol context) expr row col
3020 IfIndentCondition row col ->
3021 let
3022 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3023 region = toRegion row col
3024 in
3025 Report.Report "UNFINISHED IF" region [] $
3026 Code.toSnippet source surroundings (Just region)
3028 D.reflow $
3029 "I was expecting to see more of this `if` expression, but I got stuck here:"
3031 D.stack
3032 [ D.fillSep $
3033 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
3034 ,"that","evaluates","to","True","or","False."
3036 , D.toSimpleNote $
3037 "I can be confused by indentation. Maybe something is not indented enough?"
3041 IfIndentThen row col ->
3042 let
3043 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3044 region = toRegion row col
3045 in
3046 Report.Report "UNFINISHED IF" region [] $
3047 Code.toSnippet source surroundings (Just region)
3049 D.reflow $
3050 "I was expecting to see more of this `if` expression, but I got stuck here:"
3052 D.stack
3053 [ D.fillSep $
3054 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
3056 , D.toSimpleNote $
3057 "I can be confused by indentation. Maybe something is not indented enough?"
3061 IfIndentThenBranch row col ->
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 IF" region [] $
3067 Code.toSnippet source surroundings (Just region)
3069 D.reflow $
3070 "I got stuck after the start of this `then` branch:"
3072 D.stack
3073 [ D.reflow $
3074 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3075 , D.toSimpleNote $
3076 "I can be confused by indentation, so if the `then` branch is already\
3077 \ present, it may not be indented enough for me to recognize it."
3081 IfIndentElseBranch row col ->
3082 let
3083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3084 region = toRegion row col
3085 in
3086 Report.Report "UNFINISHED IF" region [] $
3087 Code.toSnippet source surroundings (Just region)
3089 D.reflow $
3090 "I got stuck after the start of this `else` branch:"
3092 D.stack
3093 [ D.reflow $
3094 "I was expecting to see an expression next. Maybe it is not filled in yet?"
3095 , D.toSimpleNote $
3096 "I can be confused by indentation, so if the `else` branch is already\
3097 \ present, it may not be indented enough for me to recognize it."
3101 IfIndentElse row col ->
3102 let
3103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3104 region = toRegion row col
3105 in
3106 Report.Report "UNFINISHED IF" region [] $
3107 Code.toSnippet source surroundings (Just region)
3109 D.reflow $
3110 "I was expecting to see an `else` branch after this:"
3112 D.stack
3113 [ D.reflow $
3114 "I know what to do when the condition is `True`, but not when it is `False`."
3115 , D.fillSep
3116 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
3122-- RECORD
3125toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
3126toRecordReport source context record startRow startCol =
3127 case record of
3128 RecordOpen row col ->
3129 case Code.whatIsNext source row col of
3130 Code.Keyword keyword ->
3131 let
3132 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3133 region = toKeywordRegion row col keyword
3134 in
3135 Report.Report "RESERVED WORD" region [] $
3136 Code.toSnippet source surroundings (Just region)
3138 D.reflow $
3139 "I just started parsing a record, but I got stuck on this field name:"
3141 D.reflow $
3142 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3143 \ that is a reserved word. Try using a different name!"
3146 _ ->
3147 let
3148 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3149 region = toRegion row col
3150 in
3151 Report.Report "UNFINISHED RECORD" region [] $
3152 Code.toSnippet source surroundings (Just region)
3154 D.reflow $
3155 "I just started parsing a record, but I got stuck here:"
3157 D.fillSep
3158 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
3159 ,"so","I","was","expecting","to","see","a","field","name","next."
3163 RecordEnd row col ->
3164 let
3165 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3166 region = toRegion row col
3167 in
3168 Report.Report "UNFINISHED RECORD" region [] $
3169 Code.toSnippet source surroundings (Just region)
3171 D.reflow $
3172 "I am partway through parsing a record, but I got stuck here:"
3174 D.stack
3175 [ D.fillSep
3176 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3177 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3179 , D.toSimpleNote $
3180 "When I get stuck like this, it usually means that there is a missing parenthesis\
3181 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3185 RecordField row col ->
3186 case Code.whatIsNext source row col of
3187 Code.Keyword keyword ->
3188 let
3189 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3190 region = toKeywordRegion row col keyword
3191 in
3192 Report.Report "RESERVED WORD" region [] $
3193 Code.toSnippet source surroundings (Just region)
3195 D.reflow $
3196 "I am partway through parsing a record, but I got stuck on this field name:"
3198 D.reflow $
3199 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3200 \ that is a reserved word. Try using a different name!"
3203 _ ->
3204 let
3205 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3206 region = toRegion row col
3207 in
3208 Report.Report "UNFINISHED RECORD" region [] $
3209 Code.toSnippet source surroundings (Just region)
3211 D.reflow $
3212 "I am partway through parsing a record, but I got stuck after that last comma:"
3214 addNoteForRecordError $
3215 D.reflow $
3216 "Trailing commas are not allowed in records, so I was expecting to see another\
3217 \ record field defined next. If you are done defining the record, the fix may\
3218 \ be to delete that last comma?"
3221 RecordEquals row col ->
3222 let
3223 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3224 region = toRegion row col
3225 in
3226 Report.Report "UNFINISHED RECORD" region [] $
3227 Code.toSnippet source surroundings (Just region)
3229 D.reflow $
3230 "I am partway through parsing a record, but I got stuck here:"
3232 addNoteForRecordError $
3233 D.fillSep $
3234 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3235 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
3239 RecordExpr expr row col ->
3240 toExprReport source (InNode NRecord startRow startCol context) expr row col
3242 RecordSpace space row col ->
3243 toSpaceReport source space row col
3245 RecordIndentOpen row col ->
3246 let
3247 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3248 region = toRegion row col
3249 in
3250 Report.Report "UNFINISHED RECORD" region [] $
3251 Code.toSnippet source surroundings (Just region)
3253 D.reflow $
3254 "I just saw the opening curly brace of a record, but then I got stuck here:"
3256 addNoteForRecordIndentError $
3257 D.fillSep $
3258 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
3259 ,"Try","defining","some","fields","of","your","own?"
3263 RecordIndentEnd row col ->
3264 let
3265 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3266 region = toRegion row col
3267 in
3268 Report.Report "UNFINISHED RECORD" region [] $
3269 Code.toSnippet source surroundings (Just region)
3271 D.reflow $
3272 "I was expecting to see a closing curly brace next:"
3274 addNoteForRecordIndentError $
3275 D.fillSep $
3276 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3280 RecordIndentField row col ->
3281 let
3282 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3283 region = toRegion row col
3284 in
3285 Report.Report "UNFINISHED RECORD" region [] $
3286 Code.toSnippet source surroundings (Just region)
3288 D.reflow $
3289 "I am partway through parsing a record, but I got stuck after that last comma:"
3291 addNoteForRecordError $
3292 D.reflow $
3293 "Trailing commas are not allowed in records, so the fix may be to\
3294 \ delete that last comma? Or maybe you were in the middle of defining\
3295 \ an additional field?"
3298 RecordIndentEquals row col ->
3299 let
3300 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3301 region = toRegion row col
3302 in
3303 Report.Report "UNFINISHED RECORD" region [] $
3304 Code.toSnippet source surroundings (Just region)
3306 D.reflow $
3307 "I am partway through parsing a record. I just saw a record\
3308 \ field, so I was expecting to see an equals sign next:"
3310 addNoteForRecordIndentError $
3311 D.fillSep $
3312 ["Try","putting","an",D.green "=","followed","by","an","expression?"
3316 RecordIndentExpr row col ->
3317 let
3318 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3319 region = toRegion row col
3320 in
3321 Report.Report "UNFINISHED RECORD" region [] $
3322 Code.toSnippet source surroundings (Just region)
3324 D.reflow $
3325 "I am partway through parsing a record, and I was expecting to run into an expression next:"
3327 addNoteForRecordIndentError $
3328 D.fillSep $
3329 ["Try","putting","something,","like"
3330 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
3335addNoteForRecordError :: D.Doc -> D.Doc
3336addNoteForRecordError normalRecommendation =
3337 D.stack $
3338 normalRecommendation
3340 [ D.toSimpleNote
3341 "If you are trying to define a record across multiple lines, I recommend using this format:"
3342 , D.indent 4 $ D.vcat $
3343 [ "{ name = \"Alice\""
3344 , ", age = 42"
3345 , ", height = 1.75"
3346 , "}"
3348 , D.reflow $
3349 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3350 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3351 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3355addNoteForRecordIndentError :: D.Doc -> D.Doc
3356addNoteForRecordIndentError normalRecommendation =
3357 D.stack $
3358 normalRecommendation
3360 [ D.toSimpleNote
3361 "I may be confused by indentation. For example, if you are trying to define\
3362 \ a record across multiple lines, I recommend using this format:"
3363 , D.indent 4 $ D.vcat $
3364 [ "{ name = \"Alice\""
3365 , ", age = 42"
3366 , ", height = 1.75"
3367 , "}"
3369 , D.reflow $
3370 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3371 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3372 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3377-- TUPLE
3380toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
3381toTupleReport source context tuple startRow startCol =
3382 case tuple of
3383 TupleExpr expr row col ->
3384 toExprReport source (InNode NParens startRow startCol context) expr row col
3386 TupleSpace space row col ->
3387 toSpaceReport source space row col
3389 TupleEnd row col ->
3390 let
3391 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3392 region = toRegion row col
3393 in
3394 Report.Report "UNFINISHED PARENTHESES" region [] $
3395 Code.toSnippet source surroundings (Just region)
3397 D.reflow $
3398 "I was expecting to see a closing parentheses next, but I got stuck here:"
3400 D.stack
3401 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3402 , D.toSimpleNote $
3403 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
3404 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
3405 \ or missing brackets) that is confusing me."
3409 TupleOperatorClose 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 OPERATOR FUNCTION" region [] $
3415 Code.toSnippet source surroundings (Just region)
3417 D.reflow "I was expecting a closing parenthesis here:"
3419 D.stack
3420 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3421 , D.toSimpleNote $
3422 "I think I am parsing an operator function right now, so I am expecting to see\
3423 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
3424 \ no extra spaces."
3428 TupleOperatorReserved operator row col ->
3429 let
3430 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3431 region = toRegion row col
3432 in
3433 Report.Report "UNEXPECTED SYMBOL" region [] $
3434 Code.toSnippet source surroundings (Just region)
3436 D.reflow $
3437 "I ran into an unexpected symbol here:"
3439 D.fillSep $
3440 case operator of
3441 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
3442 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
3443 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
3444 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
3445 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
3448 TupleIndentExpr1 row col ->
3449 let
3450 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3451 region = toRegion row col
3452 in
3453 Report.Report "UNFINISHED PARENTHESES" region [] $
3454 Code.toSnippet source surroundings (Just region)
3456 D.reflow $
3457 "I just saw an open parenthesis, so I was expecting to see an expression next."
3459 D.stack
3460 [ D.fillSep $
3461 ["Something","like",D.dullyellow "(4 + 5)","or"
3462 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
3463 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
3465 , D.toSimpleNote $
3466 "I can get confused by indentation in cases like this, so\
3467 \ maybe you have an expression but it is not indented enough?"
3471 TupleIndentExprN row col ->
3472 let
3473 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3474 region = toRegion row col
3475 in
3476 Report.Report "UNFINISHED TUPLE" region [] $
3477 Code.toSnippet source surroundings (Just region)
3479 D.reflow $
3480 "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."
3482 D.stack
3483 [ D.fillSep $
3484 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
3485 ,D.dullyellow "(\"Tom\",42)" <> ","
3486 ,"so","I","think","there","is","an","expression","missing","here?"
3488 , D.toSimpleNote $
3489 "I can get confused by indentation in cases like this, so\
3490 \ maybe you have an expression but it is not indented enough?"
3494 TupleIndentEnd row col ->
3495 let
3496 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3497 region = toRegion row col
3498 in
3499 Report.Report "UNFINISHED PARENTHESES" region [] $
3500 Code.toSnippet source surroundings (Just region)
3502 D.reflow $
3503 "I was expecting to see a closing parenthesis next:"
3505 D.stack
3506 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
3507 , D.toSimpleNote $
3508 "I can get confused by indentation in cases like this, so\
3509 \ maybe you have a closing parenthesis but it is not indented enough?"
3514toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
3515toListReport source context list startRow startCol =
3516 case list of
3517 ListSpace space row col ->
3518 toSpaceReport source space row col
3520 ListOpen row col ->
3521 let
3522 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3523 region = toRegion row col
3524 in
3525 Report.Report "UNFINISHED LIST" region [] $
3526 Code.toSnippet source surroundings (Just region)
3528 D.reflow $
3529 "I am partway through parsing a list, but I got stuck here:"
3531 D.stack
3532 [ D.fillSep
3533 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3534 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3536 , D.toSimpleNote $
3537 "When I get stuck like this, it usually means that there is a missing parenthesis\
3538 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3542 ListExpr expr row col ->
3543 case expr of
3544 Start r c ->
3545 let
3546 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
3547 region = toRegion r c
3548 in
3549 Report.Report "UNFINISHED LIST" region [] $
3550 Code.toSnippet source surroundings (Just region)
3552 D.reflow $
3553 "I was expecting to see another list entry after that last comma:"
3555 D.stack
3556 [ D.reflow $
3557 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3558 , D.toSimpleNote
3559 "I recommend using the following format for lists that span multiple lines:"
3560 , D.indent 4 $ D.vcat $
3561 [ "[ \"Alice\""
3562 , ", \"Bob\""
3563 , ", \"Chuck\""
3564 , "]"
3566 , D.reflow $
3567 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3568 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3569 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3573 _ ->
3574 toExprReport source (InNode NList startRow startCol context) expr row col
3576 ListEnd row col ->
3577 let
3578 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3579 region = toRegion row col
3580 in
3581 Report.Report "UNFINISHED LIST" region [] $
3582 Code.toSnippet source surroundings (Just region)
3584 D.reflow $
3585 "I am partway through parsing a list, but I got stuck here:"
3587 D.stack
3588 [ D.fillSep
3589 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
3590 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
3592 , D.toSimpleNote $
3593 "When I get stuck like this, it usually means that there is a missing parenthesis\
3594 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3598 ListIndentOpen row col ->
3599 let
3600 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3601 region = toRegion row col
3602 in
3603 Report.Report "UNFINISHED LIST" region [] $
3604 Code.toSnippet source surroundings (Just region)
3606 D.reflow $
3607 "I cannot find the end of this list:"
3609 D.stack
3610 [ D.fillSep $
3611 ["You","could","change","it","to","something","like"
3612 ,D.dullyellow "[3,4,5]"
3613 ,"or","even","just"
3614 ,D.dullyellow "[]" <> "."
3615 ,"Anything","where","there","is","an","open","and","close","square","brace,"
3616 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
3618 , D.toSimpleNote
3619 "I may be confused by indentation. For example, if you are trying to define\
3620 \ a list across multiple lines, I recommend using this format:"
3621 , D.indent 4 $ D.vcat $
3622 [ "[ \"Alice\""
3623 , ", \"Bob\""
3624 , ", \"Chuck\""
3625 , "]"
3627 , D.reflow $
3628 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3629 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3630 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3634 ListIndentEnd row col ->
3635 let
3636 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3637 region = toRegion row col
3638 in
3639 Report.Report "UNFINISHED LIST" region [] $
3640 Code.toSnippet source surroundings (Just region)
3642 D.reflow $
3643 "I cannot find the end of this list:"
3645 D.stack
3646 [ D.fillSep $
3647 ["You","can","just","add","a","closing",D.dullyellow "]"
3648 ,"right","here,","and","I","will","be","all","set!"
3650 , D.toSimpleNote
3651 "I may be confused by indentation. For example, if you are trying to define\
3652 \ a list across multiple lines, I recommend using this format:"
3653 , D.indent 4 $ D.vcat $
3654 [ "[ \"Alice\""
3655 , ", \"Bob\""
3656 , ", \"Chuck\""
3657 , "]"
3659 , D.reflow $
3660 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3661 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3662 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3666 ListIndentExpr row col ->
3667 let
3668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3669 region = toRegion row col
3670 in
3671 Report.Report "UNFINISHED LIST" region [] $
3672 Code.toSnippet source surroundings (Just region)
3674 D.reflow $
3675 "I was expecting to see another list entry after this comma:"
3677 D.stack
3678 [ D.reflow $
3679 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3680 , D.toSimpleNote
3681 "I recommend using the following format for lists that span multiple lines:"
3682 , D.indent 4 $ D.vcat $
3683 [ "[ \"Alice\""
3684 , ", \"Bob\""
3685 , ", \"Chuck\""
3686 , "]"
3688 , D.reflow $
3689 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3690 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3691 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3696toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
3697toFuncReport source context func startRow startCol =
3698 case func of
3699 FuncSpace space row col ->
3700 toSpaceReport source space row col
3702 FuncArg pattern row col ->
3703 toPatternReport source PArg pattern row col
3705 FuncBody expr row col ->
3706 toExprReport source (InNode NFunc startRow startCol context) expr row col
3708 FuncArrow row col ->
3709 case Code.whatIsNext source row col of
3710 Code.Keyword keyword ->
3711 let
3712 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3713 region = toKeywordRegion row col keyword
3714 in
3715 Report.Report "RESERVED WORD" region [] $
3716 Code.toSnippet source surroundings (Just region)
3718 D.reflow $
3719 "I was parsing an anonymous function, but I got stuck here:"
3721 D.reflow $
3722 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
3723 \ it is a reserved word in this language. Try using a different argument name!"
3726 _ ->
3727 let
3728 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3729 region = toRegion row col
3730 in
3731 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3732 Code.toSnippet source surroundings (Just region)
3734 D.reflow $
3735 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3737 D.fillSep $
3738 ["The","syntax","for","anonymous","functions","is"
3739 ,D.dullyellow "(\\x -> x + 1)"
3740 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3744 FuncIndentArg row col ->
3745 let
3746 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3747 region = toRegion row col
3748 in
3749 Report.Report "MISSING ARGUMENT" region [] $
3750 Code.toSnippet source surroundings (Just region)
3752 D.reflow $
3753 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
3755 D.stack
3756 [ D.fillSep
3757 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
3758 ,"Anything","that","starts","with","a","lower","case","letter!"
3760 , D.toSimpleNote $
3761 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
3762 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
3763 \ like a better idea at the time!"
3767 FuncIndentArrow row col ->
3768 let
3769 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3770 region = toRegion row col
3771 in
3772 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3773 Code.toSnippet source surroundings (Just region)
3775 D.reflow $
3776 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3778 D.stack
3779 [ D.fillSep $
3780 ["The","syntax","for","anonymous","functions","is"
3781 ,D.dullyellow "(\\x -> x + 1)"
3782 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3784 , D.toSimpleNote $
3785 "It is possible that I am confused about indetation! I generally recommend\
3786 \ switching to named functions if the definition cannot fit inline nicely, so\
3787 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3788 \ the whole thing out into a named function. Things tend to be clearer that way!"
3792 FuncIndentBody row col ->
3793 let
3794 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3795 region = toRegion row col
3796 in
3797 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3798 Code.toSnippet source surroundings (Just region)
3800 D.reflow $
3801 "I was expecting to see the body of your anonymous function next:"
3803 D.stack
3804 [ D.fillSep $
3805 ["The","syntax","for","anonymous","functions","is"
3806 ,D.dullyellow "(\\x -> x + 1)"
3807 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
3809 , D.toSimpleNote $
3810 "It is possible that I am confused about indetation! I generally recommend\
3811 \ switching to named functions if the definition cannot fit inline nicely, so\
3812 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3813 \ the whole thing out into a named function. Things tend to be clearer that way!"
3819-- PATTERN
3822data PContext
3823 = PCase
3824 | PArg
3827toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
3828toPatternReport source context pattern startRow startCol =
3829 case pattern of
3830 PRecord record row col ->
3831 toPRecordReport source record row col
3833 PTuple tuple row col ->
3834 toPTupleReport source context tuple row col
3836 PList list row col ->
3837 toPListReport source context list row col
3839 PStart row col ->
3840 case Code.whatIsNext source row col of
3841 Code.Keyword keyword ->
3842 let
3843 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3844 region = toKeywordRegion row col keyword
3845 aThing =
3846 case context of
3847 PArg -> "an argument"
3848 PCase -> "a pattern"
3849 in
3850 Report.Report "RESERVED WORD" region [] $
3851 Code.toSnippet source surroundings (Just region)
3853 D.reflow $
3854 "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
3856 D.reflow $
3857 "This is a reserved word! Try using some other name?"
3860 _ ->
3861 error "TODO PStart"
3863 PChar char row col ->
3864 toCharReport source char row col
3866 PString string row col ->
3867 toStringReport source string row col
3869 PNumber number row col ->
3870 toNumberReport source number row col
3872 PFloat width row col ->
3873 let
3874 region = toWiderRegion row col width
3875 in
3876 Report.Report "UNEXPECTED PATTERN" region [] $
3877 Code.toSnippet source region Nothing
3879 D.reflow $
3880 "I cannot pattern match with floating point numbers:"
3882 D.fillSep $
3883 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
3884 ,"to","check","that","they","are","nearby","with","some","sort","of"
3885 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
3889 PAlias row col ->
3890 let
3891 region = toRegion row col
3892 in
3893 Report.Report "UNFINISHED PATTERN" region [] $
3894 Code.toSnippet source region Nothing $
3896 D.reflow $
3897 "I was expecting to see a variable name after the `as` keyword:"
3899 D.stack
3900 [ D.fillSep $
3901 ["The","`as`","keyword","lets","you","write","patterns","like"
3902 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3903 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3904 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3905 ,"thing","with",D.dullyellow "point."
3907 , D.reflow $
3908 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3909 \ people just want to use `as` as a variable name though. Try using a different name\
3910 \ in that case!"
3914 PWildcardNotVar name width row col ->
3915 let
3916 region = toWiderRegion row col (fromIntegral width)
3917 examples =
3918 case dropWhile (=='_') (Name.toChars name) of
3919 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
3920 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
3921 in
3922 Report.Report "UNEXPECTED NAME" region [] $
3923 Code.toSnippet source region Nothing $
3925 D.reflow $
3926 "Variable names cannot start with underscores like this:"
3928 D.fillSep $
3929 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
3930 ,"ignore","the","value,","or","you","can","have","a","name","like"
3931 ] ++ examples ++ ["to","use","the","matched","value." ]
3934 PSpace space row col ->
3935 toSpaceReport source space row col
3937 PIndentStart row col ->
3938 error "TODO PIndentStart" row col
3940 PIndentAlias row col ->
3941 let
3942 region = toRegion row col
3943 in
3944 Report.Report "UNFINISHED PATTERN" region [] $
3945 Code.toSnippet source region Nothing $
3947 D.reflow $
3948 "I was expecting to see a variable name after the `as` keyword:"
3950 D.stack
3951 [ D.fillSep $
3952 ["The","`as`","keyword","lets","you","write","patterns","like"
3953 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3954 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3955 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3956 ,"thing","with",D.dullyellow "point."
3958 , D.reflow $
3959 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3960 \ people just want to use `as` as a variable name though. Try using a different name\
3961 \ in that case!"
3966toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
3967toPRecordReport source record startRow startCol =
3968 case record of
3969 PRecordOpen row col ->
3970 toUnfinishRecordPatternReport source row col startRow startCol $
3971 D.reflow "I was expecting to see a field name next."
3973 PRecordEnd row col ->
3974 toUnfinishRecordPatternReport source row col startRow startCol $
3975 D.fillSep
3976 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3977 ,"Try","adding","a",D.dullyellow "}","here?"
3980 PRecordField row col ->
3981 case Code.whatIsNext source row col of
3982 Code.Keyword keyword ->
3983 let
3984 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3985 region = toKeywordRegion row col keyword
3986 in
3987 Report.Report "RESERVED WORD" region [] $
3988 Code.toSnippet source surroundings (Just region)
3990 D.reflow $
3991 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
3993 D.reflow $
3994 "This is a reserved word, not available for variable names. Try another name!"
3997 _ ->
3998 toUnfinishRecordPatternReport source row col startRow startCol $
3999 D.reflow "I was expecting to see a field name next."
4001 PRecordSpace space row col ->
4002 toSpaceReport source space row col
4004 PRecordIndentOpen row col ->
4005 toUnfinishRecordPatternReport source row col startRow startCol $
4006 D.reflow "I was expecting to see a field name next."
4008 PRecordIndentEnd row col ->
4009 toUnfinishRecordPatternReport source row col startRow startCol $
4010 D.fillSep
4011 ["I","was","expecting","to","see","a","closing","curly","brace","next."
4012 ,"Try","adding","a",D.dullyellow "}","here?"
4015 PRecordIndentField row col ->
4016 toUnfinishRecordPatternReport source row col startRow startCol $
4017 D.reflow "I was expecting to see a field name next."
4020toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
4021toUnfinishRecordPatternReport source row col startRow startCol message =
4022 let
4023 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4024 region = toRegion row col
4025 in
4026 Report.Report "UNFINISHED RECORD PATTERN" region [] $
4027 Code.toSnippet source surroundings (Just region)
4029 D.reflow $
4030 "I was partway through parsing a record pattern, but I got stuck here:"
4032 D.stack
4033 [ message
4034 , D.toFancyHint $
4035 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
4036 ,"where","you","list","the","field","names","you","want","to","access."
4043toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
4044toPTupleReport source context tuple startRow startCol =
4045 case tuple of
4046 PTupleOpen row col ->
4047 case Code.whatIsNext source row col of
4048 Code.Keyword keyword ->
4049 let
4050 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4051 region = toKeywordRegion row col keyword
4052 in
4053 Report.Report "RESERVED WORD" region [] $
4054 Code.toSnippet source surroundings (Just region)
4056 D.reflow $
4057 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
4059 D.reflow $
4060 "This is a reserved word! Try using some other name?"
4063 _ ->
4064 let
4065 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4066 region = toRegion row col
4067 in
4068 Report.Report "UNFINISHED PARENTHESES" region [] $
4069 Code.toSnippet source surroundings (Just region)
4071 D.reflow $
4072 "I just saw an open parenthesis, but I got stuck here:"
4074 D.fillSep
4075 ["I","was","expecting","so","see","a","pattern","next."
4076 ,"Maybe","it","will","end","up","being","something"
4077 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4081 PTupleEnd row col ->
4082 let
4083 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4084 region = toRegion row col
4085 in
4086 Report.Report "UNFINISHED PARENTHESES" region [] $
4087 Code.toSnippet source surroundings (Just region) $
4089 D.reflow $
4090 "I was expecting a closing parenthesis next:"
4092 D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4095 PTupleExpr pattern row col ->
4096 toPatternReport source context pattern row col
4098 PTupleSpace space row col ->
4099 toSpaceReport source space row col
4101 PTupleIndentEnd row col ->
4102 let
4103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4104 region = toRegion row col
4105 in
4106 Report.Report "UNFINISHED PARENTHESES" region [] $
4107 Code.toSnippet source surroundings (Just region) $
4109 D.reflow $
4110 "I was expecting a closing parenthesis next:"
4112 D.stack
4113 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4114 , D.toSimpleNote $
4115 "I can get confused by indentation in cases like this, so\
4116 \ maybe you have a closing parenthesis but it is not indented enough?"
4120 PTupleIndentExpr1 row col ->
4121 let
4122 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4123 region = toRegion row col
4124 in
4125 Report.Report "UNFINISHED PARENTHESES" region [] $
4126 Code.toSnippet source surroundings (Just region) $
4128 D.reflow $
4129 "I just saw an open parenthesis, but then I got stuck here:"
4131 D.fillSep
4132 ["I","was","expecting","so","see","a","pattern","next."
4133 ,"Maybe","it","will","end","up","being","something"
4134 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
4138 PTupleIndentExprN row col ->
4139 let
4140 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4141 region = toRegion row col
4142 in
4143 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
4144 Code.toSnippet source surroundings (Just region) $
4146 D.reflow $
4147 "I am partway through parsing a tuple pattern, but I got stuck here:"
4149 D.stack
4150 [ D.fillSep
4151 ["I","was","expecting","so","see","a","pattern","next."
4152 ,"I","am","expecting","the","final","result","to","be","something"
4153 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
4155 , D.toSimpleNote $
4156 "I can get confused by indentation in cases like this, so the problem\
4157 \ may be that the next part is not indented enough?"
4162toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
4163toPListReport source context list startRow startCol =
4164 case list of
4165 PListOpen row col ->
4166 case Code.whatIsNext source row col of
4167 Code.Keyword keyword ->
4168 let
4169 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4170 region = toKeywordRegion row col keyword
4171 in
4172 Report.Report "RESERVED WORD" region [] $
4173 Code.toSnippet source surroundings (Just region)
4175 D.reflow $
4176 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
4178 D.reflow $
4179 "This is a reserved word though! Try using some other name?"
4182 _ ->
4183 let
4184 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4185 region = toRegion row col
4186 in
4187 Report.Report "UNFINISHED LIST PATTERN" region [] $
4188 Code.toSnippet source surroundings (Just region) $
4190 D.reflow $
4191 "I just saw an open square bracket, but then I got stuck here:"
4193 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4196 PListEnd row col ->
4197 let
4198 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4199 region = toRegion row col
4200 in
4201 Report.Report "UNFINISHED LIST PATTERN" region [] $
4202 Code.toSnippet source surroundings (Just region) $
4204 D.reflow $
4205 "I was expecting a closing square bracket to end this list pattern:"
4207 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4210 PListExpr pattern row col ->
4211 toPatternReport source context pattern row col
4213 PListSpace space row col ->
4214 toSpaceReport source space row col
4216 PListIndentOpen row col ->
4217 let
4218 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4219 region = toRegion row col
4220 in
4221 Report.Report "UNFINISHED LIST PATTERN" region [] $
4222 Code.toSnippet source surroundings (Just region) $
4224 D.reflow $
4225 "I just saw an open square bracket, but then I got stuck here:"
4227 D.stack
4228 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4229 , D.toSimpleNote $
4230 "I can get confused by indentation in cases like this, so\
4231 \ maybe there is something next, but it is not indented enough?"
4235 PListIndentEnd row col ->
4236 let
4237 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4238 region = toRegion row col
4239 in
4240 Report.Report "UNFINISHED LIST PATTERN" region [] $
4241 Code.toSnippet source surroundings (Just region) $
4243 D.reflow $
4244 "I was expecting a closing square bracket to end this list pattern:"
4246 D.stack
4247 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
4248 , D.toSimpleNote $
4249 "I can get confused by indentation in cases like this, so\
4250 \ maybe you have a closing square bracket but it is not indented enough?"
4254 PListIndentExpr row col ->
4255 let
4256 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4257 region = toRegion row col
4258 in
4259 Report.Report "UNFINISHED LIST PATTERN" region [] $
4260 Code.toSnippet source surroundings (Just region) $
4262 D.reflow $
4263 "I am partway through parsing a list pattern, but I got stuck here:"
4265 D.stack
4266 [ D.reflow $
4267 "I was expecting to see another pattern next. Maybe a variable name."
4268 , D.toSimpleNote $
4269 "I can get confused by indentation in cases like this, so\
4270 \ maybe there is more to this pattern but it is not indented enough?"
4276-- TYPES
4279-- TODO add context? say something special if you are in type annotation vs custom type vs type alias?
4281toTypeReport :: Code.Source -> Type -> Row -> Col -> Report.Report
4282toTypeReport source tipe startRow startCol =
4283 case tipe of
4284 TRecord record row col ->
4285 toTRecordReport source record row col
4287 TTuple tuple row col ->
4288 toTTupleReport source tuple row col
4290 TArrow row col ->
4291 error "TODO TArrow" row col
4293 TStart row col ->
4294 error "TODO TStart" row col startRow startCol
4296 TSpace space row col ->
4297 toSpaceReport source space row col
4299 TIndentStart row col ->
4300 error "TODO TIndentStart" row col
4304toTRecordReport :: Code.Source -> TRecord -> Row -> Col -> Report.Report
4305toTRecordReport source record startRow startCol =
4306 case record of
4307 TRecordOpen row col ->
4308 case Code.whatIsNext source row col of
4309 Code.Keyword keyword ->
4310 let
4311 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4312 region = toKeywordRegion row col keyword
4313 in
4314 Report.Report "RESERVED WORD" region [] $
4315 Code.toSnippet source surroundings (Just region)
4317 D.reflow $
4318 "I just started parsing a record type, but I got stuck on this field name:"
4320 D.reflow $
4321 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4322 \ that is a reserved word. Try using a different name!"
4325 _ ->
4326 let
4327 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4328 region = toRegion row col
4329 in
4330 Report.Report "UNFINISHED RECORD TYPE" region [] $
4331 Code.toSnippet source surroundings (Just region)
4333 D.reflow $
4334 "I just started parsing a record type, but I got stuck here:"
4336 D.fillSep
4337 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
4338 ,"so","I","was","expecting","to","see","a","field","name","next."
4342 TRecordEnd row col ->
4343 let
4344 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4345 region = toRegion row col
4346 in
4347 Report.Report "UNFINISHED RECORD TYPE" region [] $
4348 Code.toSnippet source surroundings (Just region)
4350 D.reflow $
4351 "I am partway through parsing a record type, but I got stuck here:"
4353 D.stack
4354 [ D.fillSep
4355 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
4356 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
4358 , D.toSimpleNote $
4359 "When I get stuck like this, it usually means that there is a missing parenthesis\
4360 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
4364 TRecordField row col ->
4365 case Code.whatIsNext source row col of
4366 Code.Keyword keyword ->
4367 let
4368 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4369 region = toKeywordRegion row col keyword
4370 in
4371 Report.Report "RESERVED WORD" region [] $
4372 Code.toSnippet source surroundings (Just region)
4374 D.reflow $
4375 "I am partway through parsing a record type, but I got stuck on this field name:"
4377 D.reflow $
4378 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
4379 \ that is a reserved word. Try using a different name!"
4382 _ ->
4383 let
4384 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4385 region = toRegion row col
4386 in
4387 Report.Report "UNFINISHED RECORD TYPE" region [] $
4388 Code.toSnippet source surroundings (Just region)
4390 D.reflow $
4391 "I am partway through parsing a record type, but I got stuck after that last comma:"
4393 addNoteForRecordTypeError $
4394 D.reflow $
4395 "Trailing commas are not allowed in records, so I was expecting to see another\
4396 \ record field defined next. If you are done defining the record, the fix may\
4397 \ be to delete that last comma?"
4400 TRecordColon row col ->
4401 let
4402 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4403 region = toRegion row col
4404 in
4405 Report.Report "UNFINISHED RECORD TYPE" region [] $
4406 Code.toSnippet source surroundings (Just region)
4408 D.reflow $
4409 "I am partway through parsing a record type, but I got stuck here:"
4411 addNoteForRecordTypeError $
4412 D.fillSep $
4413 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
4414 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
4418 TRecordType tipe row col ->
4419 toTypeReport source tipe row col
4421 TRecordSpace space row col ->
4422 toSpaceReport source space row col
4424 TRecordIndentOpen row col ->
4425 let
4426 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4427 region = toRegion row col
4428 in
4429 Report.Report "UNFINISHED RECORD TYPE" region [] $
4430 Code.toSnippet source surroundings (Just region)
4432 D.reflow $
4433 "I just saw the opening curly brace of a record type, but then I got stuck here:"
4435 addNoteForRecordTypeIndentError $
4436 D.fillSep $
4437 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
4438 ,"Try","defining","some","fields","of","your","own?"
4442 TRecordIndentEnd row col ->
4443 let
4444 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4445 region = toRegion row col
4446 in
4447 Report.Report "UNFINISHED RECORD TYPE" region [] $
4448 Code.toSnippet source surroundings (Just region)
4450 D.reflow $
4451 "I was expecting to see a closing curly brace next:"
4453 addNoteForRecordTypeIndentError $
4454 D.fillSep $
4455 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
4459 TRecordIndentField row col ->
4460 let
4461 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4462 region = toRegion row col
4463 in
4464 Report.Report "UNFINISHED RECORD TYPE" region [] $
4465 Code.toSnippet source surroundings (Just region)
4467 D.reflow $
4468 "I am partway through parsing a record type, but I got stuck after that last comma:"
4470 addNoteForRecordTypeIndentError $
4471 D.reflow $
4472 "Trailing commas are not allowed in record types, so the fix may be to\
4473 \ delete that last comma? Or maybe you were in the middle of defining\
4474 \ an additional field?"
4477 TRecordIndentColon row col ->
4478 let
4479 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4480 region = toRegion row col
4481 in
4482 Report.Report "UNFINISHED RECORD TYPE" region [] $
4483 Code.toSnippet source surroundings (Just region)
4485 D.reflow $
4486 "I am partway through parsing a record type. I just saw a record\
4487 \ field, so I was expecting to see a colon next:"
4489 addNoteForRecordTypeIndentError $
4490 D.fillSep $
4491 ["Try","putting","an",D.green ":","followed","by","a","type?"
4495 TRecordIndentType row col ->
4496 let
4497 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4498 region = toRegion row col
4499 in
4500 Report.Report "UNFINISHED RECORD TYPE" region [] $
4501 Code.toSnippet source surroundings (Just region)
4503 D.reflow $
4504 "I am partway through parsing a record type, and I was expecting to run into a type next:"
4506 addNoteForRecordTypeIndentError $
4507 D.fillSep $
4508 ["Try","putting","something,","like"
4509 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
4514addNoteForRecordTypeError :: D.Doc -> D.Doc
4515addNoteForRecordTypeError normalRecommendation =
4516 D.stack $
4517 normalRecommendation
4519 [ D.toSimpleNote
4520 "If you are trying to define a record type across multiple lines, I recommend using this format:"
4521 , D.indent 4 $ D.vcat $
4522 [ "{ name : String"
4523 , ", age : Int"
4524 , ", height : Float"
4525 , "}"
4527 , D.reflow $
4528 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4529 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4530 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4534addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
4535addNoteForRecordTypeIndentError normalRecommendation =
4536 D.stack $
4537 normalRecommendation
4539 [ D.toSimpleNote
4540 "I may be confused by indentation. For example, if you are trying to define\
4541 \ a record type across multiple lines, I recommend using this format:"
4542 , D.indent 4 $ D.vcat $
4543 [ "{ name : String"
4544 , ", age : Int"
4545 , ", height : Float"
4546 , "}"
4548 , D.reflow $
4549 "Notice that each line starts with some indentation. Usually two or four spaces. I\
4550 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
4551 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
4555toTTupleReport :: Code.Source -> TTuple -> Row -> Col -> Report.Report
4556toTTupleReport source tuple startRow startCol =
4557 case tuple of
4558 TTupleOpen row col ->
4559 case Code.whatIsNext source row col of
4560 Code.Keyword keyword ->
4561 let
4562 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4563 region = toKeywordRegion row col keyword
4564 in
4565 Report.Report "RESERVED WORD" region [] $
4566 Code.toSnippet source surroundings (Just region)
4568 D.reflow $
4569 "I ran into a reserved word unexpectedly:"
4571 D.reflow $
4572 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
4573 \ it is a reserved word. Try using a different name!"
4576 _ ->
4577 let
4578 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4579 region = toRegion row col
4580 in
4581 Report.Report "UNFINISHED PARENTHESES" region [] $
4582 Code.toSnippet source surroundings (Just region)
4584 D.reflow $
4585 "I just saw an open parenthesis, so I was expecting to see a type next."
4587 D.fillSep $
4588 ["Something","like",D.dullyellow "(Maybe Int)","or"
4589 ,D.dullyellow "(List Person)" <> "."
4590 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4594 TTupleEnd row col ->
4595 let
4596 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4597 region = toRegion row col
4598 in
4599 Report.Report "UNFINISHED PARENTHESES" region [] $
4600 Code.toSnippet source surroundings (Just region)
4602 D.reflow $
4603 "I was expecting to see a closing parentheses next, but I got stuck here:"
4605 D.stack
4606 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
4607 , D.toSimpleNote $
4608 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
4609 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
4610 \ or missing brackets) that is confusing me."
4614 TTupleType tipe row col ->
4615 toTypeReport source tipe row col
4617 TTupleSpace space row col ->
4618 toSpaceReport source space row col
4620 TTupleIndentType1 row col ->
4621 let
4622 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4623 region = toRegion row col
4624 in
4625 Report.Report "UNFINISHED PARENTHESES" region [] $
4626 Code.toSnippet source surroundings (Just region)
4628 D.reflow $
4629 "I just saw an open parenthesis, so I was expecting to see a type next."
4631 D.stack
4632 [ D.fillSep $
4633 ["Something","like",D.dullyellow "(Maybe Int)","or"
4634 ,D.dullyellow "(List Person)" <> "."
4635 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
4637 , D.toSimpleNote $
4638 "I can get confused by indentation in cases like this, so\
4639 \ maybe you have a type but it is not indented enough?"
4643 TTupleIndentTypeN row col ->
4644 let
4645 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4646 region = toRegion row col
4647 in
4648 Report.Report "UNFINISHED TUPLE TYPE" region [] $
4649 Code.toSnippet source surroundings (Just region)
4651 D.reflow $
4652 "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."
4654 D.stack
4655 [ D.fillSep $
4656 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
4657 ,D.dullyellow "(String,Int)" <> ","
4658 ,"so","I","think","there","is","a","type","missing","here?"
4660 , D.toSimpleNote $
4661 "I can get confused by indentation in cases like this, so\
4662 \ maybe you have an expression but it is not indented enough?"
4666 TTupleIndentEnd row col ->
4667 let
4668 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4669 region = toRegion row col
4670 in
4671 Report.Report "UNFINISHED PARENTHESES" region [] $
4672 Code.toSnippet source surroundings (Just region)
4674 D.reflow $
4675 "I was expecting to see a closing parenthesis next:"
4677 D.stack
4678 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4679 , D.toSimpleNote $
4680 "I can get confused by indentation in cases like this, so\
4681 \ maybe you have a closing parenthesis but it is not indented enough?"