on fbbc543 help sign in
3458 lines 118 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 | ExposingEnd Row Col
119 --
120 | ExposingTypePrivacy Row Col
121 | ExposingTypePrivacyDots Row Col
122 | ExposingTypePrivacyEnd Row Col
123 --
124 | ExposingIndentEnd Row Col
125 | ExposingIndentValue Row Col
126 | ExposingIndentValueEnd Row Col
127 | ExposingIndentTypePrivacy Row Col
128 | ExposingIndentTypePrivacyDots Row Col
129 | ExposingIndentTypePrivacyEnd Row Col
133-- DECLARATIONS
136data Decl
137 = DeclStart Row Col
138 | DeclSpace Space Row Col
139 --
140 | Port Port Row Col
141 | DeclType DeclType Row Col
142 | DeclDef Name.Name DeclDef Row Col
143 --
144 | DeclFreshLineStart Row Col
145 | DeclFreshLineAfterDocComment Row Col
148data DeclDef
149 = DeclDefSpace Space Row Col
150 | DeclDefEquals Row Col
151 | DeclDefType Type Row Col
152 | DeclDefArg Pattern Row Col
153 | DeclDefBody Expr Row Col
154 | DeclDefNameRepeat Row Col
155 | DeclDefNameMatch Name.Name Row Col
156 --
157 | DeclDefIndentType Row Col
158 | DeclDefIndentEquals Row Col
159 | DeclDefIndentBody Row Col
160 --
161 | DeclDefFreshLineAfterType Row Col
164data Port
165 = PortSpace Space Row Col
166 | PortName Row Col
167 | PortColon Row Col
168 | PortType Type Row Col
169 | PortIndentName Row Col
170 | PortIndentColon Row Col
171 | PortIndentType Row Col
175-- TYPE DECLARATIONS
178data DeclType
179 = DT_Space Space Row Col
180 | DT_Name Row Col
181 | DT_Alias TypeAlias Row Col
182 | DT_Union CustomType Row Col
183 --
184 | DT_IndentName Row Col
187data TypeAlias
188 = AliasSpace Space Row Col
189 | AliasName Row Col
190 | AliasEquals Row Col
191 | AliasBody Type Row Col
192 --
193 | AliasIndentEquals Row Col
194 | AliasIndentBody Row Col
197data CustomType
198 = CT_Space Space Row Col
199 | CT_Name Row Col
200 | CT_Equals Row Col
201 | CT_Bar Row Col
202 | CT_Variant Row Col
203 | CT_VariantArg Type Row Col
204 --
205 | CT_IndentEquals Row Col
206 | CT_IndentBar Row Col
207 | CT_IndentAfterBar Row Col
208 | CT_IndentAfterEquals Row Col
212-- EXPRESSIONS
215data Expr
216 = Let Let Row Col
217 | Case Case Row Col
218 | If If Row Col
219 | List List Row Col
220 | Record Record Row Col
221 | Tuple Tuple Row Col
222 | Func Func Row Col
223 --
224 | Dot Row Col
225 | Access Row Col
226 | OperatorRight Name.Name Row Col
227 | OperatorReserved BadOperator Row Col
228 --
229 | Start Row Col
230 | Char Char Row Col
231 | String String Row Col
232 | Number Number Row Col
233 | Space Space Row Col
234 | EndlessShader Row Col
235 | ShaderProblem [Char.Char] Row Col
236 | IndentOperatorRight Name.Name Row Col
237 | IndentMoreExpr Row Col
240data Record
241 = RecordOpen Row Col
242 | RecordEnd Row Col
243 | RecordField Row Col
244 | RecordEquals Row Col
245 | RecordExpr Expr Row Col
246 | RecordSpace Space Row Col
247 --
248 | RecordIndentOpen Row Col
249 | RecordIndentEnd Row Col
250 | RecordIndentField Row Col
251 | RecordIndentEquals Row Col
252 | RecordIndentExpr Row Col
255data Tuple
256 = TupleExpr Expr Row Col
257 | TupleSpace Space Row Col
258 | TupleEnd Row Col
259 | TupleOperatorClose Row Col
260 | TupleOperatorReserved BadOperator Row Col
261 --
262 | TupleIndentExpr1 Row Col
263 | TupleIndentExprN Row Col
264 | TupleIndentEnd Row Col
267data List
268 = ListSpace Space Row Col
269 | ListOpen Row Col
270 | ListExpr Expr Row Col
271 | ListEnd Row Col
272 --
273 | ListIndentOpen Row Col
274 | ListIndentEnd Row Col
275 | ListIndentExpr Row Col
278data Func
279 = FuncSpace Space Row Col
280 | FuncArg Pattern Row Col
281 | FuncBody Expr Row Col
282 | FuncArrow Row Col
283 --
284 | FuncIndentArg Row Col
285 | FuncIndentArrow Row Col
286 | FuncIndentBody Row Col
289data Case
290 = CaseSpace Space Row Col
291 | CaseOf Row Col
292 | CasePattern Pattern Row Col
293 | CaseArrow Row Col
294 | CaseExpr Expr Row Col
295 | CaseBranch Expr Row Col
296 --
297 | CaseIndentOf Row Col
298 | CaseIndentExpr Row Col
299 | CaseIndentPattern Row Col
300 | CaseIndentArrow Row Col
301 | CaseIndentBranch Row Col
302 | CasePatternAlignment Word16 Row Col
305data If
306 = IfSpace Space Row Col
307 | IfThen Row Col
308 | IfElse Row Col
309 | IfElseBranchStart Row Col
310 --
311 | IfCondition Expr Row Col
312 | IfThenBranch Expr Row Col
313 | IfElseBranch Expr Row Col
314 --
315 | IfIndentCondition Row Col
316 | IfIndentThen Row Col
317 | IfIndentThenBranch Row Col
318 | IfIndentElseBranch Row Col
319 | IfIndentElse Row Col
322data Let
323 = LetSpace Space Row Col
324 | LetIn Row Col
325 | LetDefAlignment Word16 Row Col
326 | LetDefName Row Col
327 | LetDef Name.Name Def Row Col
328 | LetDestruct Destruct Row Col
329 | LetBody Expr Row Col
330 | LetIndentDef Row Col
331 | LetIndentIn Row Col
332 | LetIndentBody Row Col
335data Def
336 = DefSpace Space Row Col
337 | DefType Type Row Col
338 | DefNameRepeat Name.Name Row Col
339 | DefNameMatch Name.Name Name.Name Row Col
340 | DefArg Pattern Row Col
341 | DefEquals Row Col
342 | DefBody Expr Row Col
343 | DefIndentEquals Row Col
344 | DefIndentType Row Col
345 | DefIndentBody Row Col
346 | DefAlignment Word16 Row Col
349data Destruct
350 = DestructSpace Space Row Col
351 | DestructPattern Pattern Row Col
352 | DestructEquals Row Col
353 | DestructBody Expr Row Col
354 | DestructIndentEquals Row Col
355 | DestructIndentBody Row Col
359-- PATTERNS
362data Pattern
363 = PRecord PRecord Row Col
364 | PTuple PTuple Row Col
365 | PList PList Row Col
366 --
367 | PStart Row Col
368 | PChar Char Row Col
369 | PString String Row Col
370 | PNumber Number Row Col
371 | PFloat Word16 Row Col
372 | PAlias Row Col
373 | PWildcardNotVar Name.Name Int Row Col
374 | PSpace Space Row Col
375 --
376 | PIndentStart Row Col
377 | PIndentAlias Row Col
380data PRecord
381 = PRecordOpen Row Col
382 | PRecordEnd Row Col
383 | PRecordField Row Col
384 | PRecordSpace Space Row Col
385 --
386 | PRecordIndentOpen Row Col
387 | PRecordIndentEnd Row Col
388 | PRecordIndentField Row Col
391data PTuple
392 = PTupleOpen Row Col
393 | PTupleEnd Row Col
394 | PTupleExpr Pattern Row Col
395 | PTupleSpace Space Row Col
396 --
397 | PTupleIndentEnd Row Col
398 | PTupleIndentExpr1 Row Col
399 | PTupleIndentExprN Row Col
402data PList
403 = PListOpen Row Col
404 | PListEnd Row Col
405 | PListExpr Pattern Row Col
406 | PListSpace Space Row Col
407 --
408 | PListIndentOpen Row Col
409 | PListIndentEnd Row Col
410 | PListIndentExpr Row Col
414-- TYPES
417data Type
418 = TRecord TRecord Row Col
419 | TTuple TTuple Row Col
420 | TVariant Row Col
421 | TArrow Row Col
422 --
423 | TStart Row Col
424 | TSpace Space Row Col
425 --
426 | TIndentStart Row Col
429data TRecord
430 = TRecordOpen Row Col
431 | TRecordEnd Row Col
432 --
433 | TRecordField Row Col
434 | TRecordColon Row Col
435 | TRecordType Type Row Col
436 --
437 | TRecordSpace Space Row Col
438 --
439 | TRecordIndentOpen Row Col
440 | TRecordIndentField Row Col
441 | TRecordIndentColon Row Col
442 | TRecordIndentType Row Col
443 | TRecordIndentEnd Row Col
446data TTuple
447 = TTupleOpen Row Col
448 | TTupleEnd Row Col
449 | TTupleType Type Row Col
450 | TTupleSpace Space Row Col
451 --
452 | TTupleIndentOpen Row Col
453 | TTupleIndentType Row Col
454 | TTupleIndentEnd Row Col
458-- LITERALS
461data Char
462 = CharEndless
463 | CharEscape Escape
464 | CharNotString Word16
467data String
468 = StringEndless_Single
469 | StringEndless_Multi
470 | StringEscape Escape
473data Escape
474 = EscapeUnknown
475 | BadUnicodeFormat Word16
476 | BadUnicodeCode Word16
477 | BadUnicodeLength Word16 Int Int
480data Number
481 = NumberEnd
482 | NumberDot Int
483 | NumberHexDigit
484 | NumberNoLeadingZero
488-- MISC
491data Space
492 = HasTab
493 | EndlessMultiComment
497-- TO REPORT
500toReport :: Code.Source -> Error -> Report.Report
501toReport source err =
502 case err of
503 ModuleNameUnspecified name ->
504 let
505 region = toRegion 1 1
506 in
507 Report.Report "MODULE NAME MISSING" region [] $
508 D.stack
509 [ D.reflow $
510 "I need the module name to be declared at the top of this file, like this:"
511 , D.indent 4 $ D.fillSep $
512 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
513 , D.reflow $
514 "Try adding that as the first line of your file!"
515 , D.toSimpleNote $
516 "It is best to replace (..) with an explicit list of types and\
517 \ functions you want to expose. When you know a value is only used\
518 \ within this module, you can refactor without worrying about uses\
519 \ elsewhere. Limiting exposed values can also speed up compilation\
520 \ because I can skip a bunch of work if I see that the exposed API\
521 \ has not changed."
522 ]
524 ModuleNameMismatch expectedName (A.At region actualName) ->
525 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
526 Code.toSnippet source region Nothing
527 (
528 "It looks like this module name is out of sync:"
529 ,
530 D.stack
531 [ D.reflow $
532 "I need it to match the file path, so I was expecting it to see `"
533 ++ ModuleName.toChars expectedName
534 ++ "` here. Make the following change, and you should be all set!"
535 , D.indent 4 $
536 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
537 , D.toSimpleNote $
538 "I require that module names correspond to file paths. This makes it much\
539 \ easier to explore unfamiliar codebases! So if you want to keep the current\
540 \ module name, try renaming the file instead."
541 ]
542 )
544 UnexpectedPort region ->
545 Report.Report "UNEXPECTED PORTS" region [] $
546 Code.toSnippet source region Nothing
547 (
548 D.reflow $
549 "You are declaring ports in a normal module."
550 ,
551 D.stack
552 [ D.fillSep
553 ["Switch","this","to","say",D.cyan "port module","instead,"
554 ,"marking","that","this","module","contains","port","declarations."
555 ]
556 , D.link "Note"
557 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
558 "ports"
559 "to learn the syntax and how to use it effectively."
560 ]
561 )
563 NoPorts region ->
564 Report.Report "NO PORTS" region [] $
565 Code.toSnippet source region Nothing
566 (
567 D.reflow $
568 "This module does not declare any ports, but it says it will:"
569 ,
570 D.fillSep
571 ["Switch","this","to",D.cyan "module"
572 ,"and","you","should","be","all","set!"
573 ]
574 )
576 ParseError modul ->
577 toParseErrorReport source modul
580toParseErrorReport :: Code.Source -> Module -> Report.Report
581toParseErrorReport source modul =
582 case modul of
583 ModuleSpace space row col ->
584 toSpaceReport source space row col
586 ModuleEndOfFile row col ->
587 let
588 region = toRegion row col
589 in
590 Report.Report "EXPECTING END OF FILE" region [] $
591 Code.toSnippet source region Nothing
592 (
593 D.reflow $
594 "I was not expecting to see anything more here:"
595 ,
596 D.reflow $
597 "I think I have read all the declarations in the file and that there is nothing\
598 \ left to see, so whatever I am running into is confusing me a lot!"
599 )
601 ModuleProblem row col ->
602 let
603 region = toRegion row col
604 in
605 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
606 Code.toSnippet source region Nothing
607 (
608 D.reflow $
609 "I am parsing an `module` declaration, but I got stuck here:"
610 ,
611 D.stack
612 [ D.reflow $
613 "Here are some examples of valid `module` declarations:"
614 , D.indent 4 $ D.vcat $
615 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
616 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
617 ]
618 , D.reflow $
619 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
620 \ of files when the public interface of a module stays the same, so exposing fewer\
621 \ values can help improve compile times!"
622 ]
623 )
625 ModuleName row col ->
626 let
627 region = toRegion row col
628 in
629 Report.Report "EXPECTING MODULE NAME" region [] $
630 Code.toSnippet source region Nothing
631 (
632 D.reflow $
633 "I was parsing an `module` declaration until I got stuck here:"
634 ,
635 D.stack
636 [ D.reflow $
637 "I was expecting to see the module name next, like in these examples:"
638 , D.indent 4 $ D.vcat $
639 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
640 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
641 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
642 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
643 ]
644 , D.reflow $
645 "Notice that the module names all start with capital letters. That is required!"
646 ]
647 )
649 ModuleExposing exposing row col ->
650 error "TODO ModuleExposing" exposing row col
652 PortModuleProblem row col ->
653 let
654 region = toRegion row col
655 in
656 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
657 Code.toSnippet source region Nothing
658 (
659 D.reflow $
660 "I am parsing an `port module` declaration, but I got stuck here:"
661 ,
662 D.stack
663 [ D.reflow $
664 "Here are some examples of valid `port module` declarations:"
665 , D.indent 4 $ D.vcat $
666 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
667 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
668 ]
669 , D.link "Note" "Read" "ports" "for more help."
670 ]
671 )
673 PortModuleName row col ->
674 let
675 region = toRegion row col
676 in
677 Report.Report "EXPECTING MODULE NAME" region [] $
678 Code.toSnippet source region Nothing
679 (
680 D.reflow $
681 "I was parsing an `module` declaration until I got stuck here:"
682 ,
683 D.stack
684 [ D.reflow $
685 "I was expecting to see the module name next, like in these examples:"
686 , D.indent 4 $ D.vcat $
687 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
688 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
689 ]
690 , D.reflow $
691 "Notice that the module names start with capital letters. That is required!"
692 ]
693 )
695 PortModuleExposing exposing row col ->
696 error "TODO PortModuleExposing" exposing row col
698 Effect row col ->
699 let
700 region = toRegion row col
701 in
702 Report.Report "BAD MODULE DECLARATION" region [] $
703 Code.toSnippet source region Nothing
704 (
705 D.reflow $
706 "I cannot parse this module declaration:"
707 ,
708 D.reflow $
709 "This type of module is reserved for the @elm organization. It is used to\
710 \ define certain effects, avoiding building them into the compiler."
711 )
713 FreshLine row col ->
714 let
715 region = toRegion row col
717 toBadFirstLineReport keyword =
718 Report.Report "TOO MUCH INDENTATION" region [] $
719 Code.toSnippet source region Nothing
720 (
721 D.reflow $
722 "This `" ++ keyword ++ "` should not have any spaces before it:"
723 ,
724 D.reflow $
725 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
726 )
728 in
729 case Code.whatIsNext source row col of
730 Code.Keyword "module" -> toBadFirstLineReport "module"
731 Code.Keyword "import" -> toBadFirstLineReport "import"
732 Code.Keyword "type" -> toBadFirstLineReport "type"
733 Code.Keyword "port" -> toBadFirstLineReport "port"
734 _ ->
735 Report.Report "SYNTAX PROBLEM" region [] $
736 Code.toSnippet source region Nothing
737 (
738 D.reflow $
739 "I got stuck here:"
740 ,
741 D.stack
742 [ D.reflow $
743 "I am not sure what is going on, but I recommend starting an Elm\
744 \ file with the following lines:"
745 , D.vcat
746 [ D.fillSep [D.cyan "import","Html"]
747 , ""
748 , D.fillSep [D.green "main","="]
749 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
750 ]
751 , D.reflow $
752 "You should be able to copy those lines directly into your file. Check out\
753 \ some of the examples on https://elm-lang.org for more help getting started!"
754 , D.toSimpleNote $
755 "This can also happen when something is indented too much!"
756 ]
757 )
759 ImportStart row col ->
760 toImportReport source row col
762 ImportName row col ->
763 let
764 region = toRegion row col
765 in
766 Report.Report "EXPECTING IMPORT NAME" region [] $
767 Code.toSnippet source region Nothing
768 (
769 D.reflow $
770 "I was parsing an `import` until I got stuck here:"
771 ,
772 D.stack
773 [ D.reflow $
774 "I was expecting to see a module name next, like in these examples:"
775 , D.indent 4 $ D.vcat $
776 [ D.fillSep [D.cyan "import","Dict"]
777 , D.fillSep [D.cyan "import","Maybe"]
778 , D.fillSep [D.cyan "import","Html.Attributes"]
779 , D.fillSep [D.cyan "import","Json.Decode"]
780 ]
781 , D.reflow $
782 "Notice that the module names all start with capital letters. That is required!"
783 ]
784 )
786 ImportAs row col ->
787 toImportReport source row col
789 ImportAlias row col ->
790 let
791 region = toRegion row col
792 in
793 Report.Report "EXECTING IMPORT ALIAS" region [] $
794 Code.toSnippet source region Nothing
795 (
796 D.reflow $
797 "I was parsing an `import` until I got stuck here:"
798 ,
799 D.stack
800 [ D.reflow $
801 "I was expecting to see an alias next, like in these examples:"
802 , D.indent 4 $ D.vcat $
803 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
804 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
805 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
806 ]
807 , D.reflow $
808 "Notice that the alias always starts with a capital letter. That is required!"
809 ]
810 )
812 ImportExposing row col ->
813 toImportReport source row col
815 ImportExposingList exposing row col ->
816 error "TODO ImportExposingList" exposing row col
818 ImportEnd row col ->
819 toImportReport source row col
821 ImportIndentName row col ->
822 toImportReport source row col
824 ImportIndentAlias row col ->
825 toImportReport source row col
827 ImportIndentExposingList row col ->
828 let
829 region = toRegion row col
830 in
831 Report.Report "UNFINISHED IMPORT" region [] $
832 Code.toSnippet source region Nothing
833 (
834 D.reflow $
835 "I was parsing an `import` until I got stuck here:"
836 ,
837 D.stack
838 [ D.reflow $
839 "I was expecting to see the list of exposed values next. For example, here\
840 \ are two ways to expose values from the `Html` module:"
841 , D.indent 4 $ D.vcat $
842 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
843 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
844 ]
845 , D.reflow $
846 "I generally recommend the second style. It is more explicit, making it\
847 \ much easier to figure out where values are coming from in large projects!"
848 ]
849 )
851 Infix row col ->
852 let
853 region = toRegion row col
854 in
855 Report.Report "BAD INFIX" region [] $
856 Code.toSnippet source region Nothing
857 (
858 D.reflow $
859 "Something went wrong in this infix operator declaration:"
860 ,
861 D.reflow $
862 "This feature is used by the @elm organization to define the\
863 \ languages built-in operators."
864 )
866 Declarations decl _ _ ->
867 toDeclarationsReport source decl
871-- IMPORTS
874toImportReport :: Code.Source -> Row -> Col -> Report.Report
875toImportReport source row col =
876 let
877 region = toRegion row col
878 in
879 Report.Report "UNFINISHED IMPORT" region [] $
880 Code.toSnippet source region Nothing
881 (
882 D.reflow $
883 "I am partway through parsing an import, but I got stuck here:"
884 ,
885 D.stack
886 [ D.reflow $
887 "Here are some examples of valid `import` declarations:"
888 , D.indent 4 $ D.vcat $
889 [ D.fillSep [D.cyan "import","Html"]
890 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
891 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
892 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
893 ]
894 , D.reflow $
895 "You are probably trying to import a different module, but try to make it look like one of these examples!"
896 ]
897 )
901-- SPACES
904toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
905toSpaceReport source space row col =
906 case space of
907 HasTab ->
908 let
909 region = toRegion row col
910 in
911 Report.Report "NO TABS" region [] $
912 Code.toSnippet source region Nothing
913 (
914 D.reflow $
915 "I ran into a tab, but tabs are not allowed in Elm files."
916 ,
917 D.reflow $
918 "Replace the tab with spaces."
919 )
921 EndlessMultiComment ->
922 let
923 region = toWiderRegion row col 2
924 in
925 Report.Report "ENDLESS COMMENT" region [] $
926 Code.toSnippet source region Nothing
927 (
928 D.reflow $
929 "I cannot find the end of this multi-line comment:"
930 ,
931 D.stack -- "{-"
932 [ D.reflow "Add a -} somewhere after this to end the comment."
933 , D.toSimpleHint
934 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
935 \ that happens to contain another comment. Like parentheses and curly braces,\
936 \ the start and end markers must always be balanced. Maybe that is the problem?"
937 ]
938 )
942-- DECLARATIONS
945toRegion :: Row -> Col -> A.Region
946toRegion row col =
947 let
948 pos = A.Position row col
949 in
950 A.Region pos pos
953toWiderRegion :: Row -> Col -> Word16 -> A.Region
954toWiderRegion row col extra =
955 A.Region
956 (A.Position row col)
957 (A.Position row (col + extra))
960toDeclarationsReport :: Code.Source -> Decl -> Report.Report
961toDeclarationsReport source decl =
962 case decl of
963 DeclStart row col ->
964 error "TODO DeclStart" row col
966 DeclSpace space row col ->
967 toSpaceReport source space row col
969 Port port row col ->
970 error "TODO Port" port row col
972 DeclType declType row col ->
973 error "TODO DeclType" declType row col
975 DeclDef name declDef row col ->
976 toDeclDefReport source name declDef row col
978 DeclFreshLineStart row col ->
979 error "TODO DeclFreshLineStart" row col
981 DeclFreshLineAfterDocComment row col ->
982 error "TODO DeclFreshLineAfterDocComment" row col
985toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
986toDeclDefReport source name declDef startRow startCol =
987 case declDef of
988 DeclDefSpace space row col ->
989 toSpaceReport source space row col
991 DeclDefEquals row col ->
992 case Code.whatIsNext source row col of
993 Code.Keyword keyword ->
994 let
995 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
996 region = toWiderRegion row col (fromIntegral (length keyword))
997 in
998 Report.Report "RESERVED WORD" region [] $
999 Code.toSnippet source surroundings (Just region)
1001 D.reflow $
1002 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
1004 D.reflow $
1005 "This is a reserved word! Try using some other name?"
1008 Code.Operator op ->
1009 let
1010 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1011 region = toWiderRegion row col (fromIntegral (length op))
1012 in
1013 Report.Report "UNEXPECTED SYMBOL" region [] $
1014 Code.toSnippet source surroundings (Just region)
1016 D.reflow $
1017 "I was not expecting to see this symbol here:"
1019 D.stack
1020 [ D.reflow $
1021 "I am not sure what is going wrong exactly, so here is a valid\
1022 \ definition (with an optional type annotation) for reference:"
1023 , D.vcat
1024 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1025 , D.fillSep [D.green "add","x","y","="]
1026 , D.fillSep [" ","x","+","y"]
1028 , D.reflow $
1029 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
1033 _ ->
1034 let
1035 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1036 region = toRegion row col
1037 in
1038 Report.Report "PROBLEM IN DEFINITION" region [] $
1039 Code.toSnippet source surroundings (Just region)
1041 D.reflow $
1042 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1044 D.stack
1045 [ D.reflow $
1046 "I am not sure what is going wrong exactly, so here is a valid\
1047 \ definition (with an optional type annotation) for reference:"
1048 , D.vcat
1049 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1050 , D.fillSep [D.green "add","x","y","="]
1051 , D.fillSep [" ","x","+","y"]
1053 , D.reflow $
1054 "Try to use that format!"
1058 DeclDefType tipe row col ->
1059 error "TODO DeclDefType" toTypeReport tipe row col
1061 DeclDefArg pattern row col ->
1062 toPatternReport source PArg pattern row col
1064 DeclDefBody expr row col ->
1065 toExprReport source (InDef name startRow startCol) expr row col
1067 DeclDefNameRepeat row col ->
1068 let
1069 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1070 region = toRegion row col
1071 in
1072 Report.Report "EXPECTING DEFINITION" region [] $
1073 Code.toSnippet source surroundings (Just region)
1075 D.reflow $
1076 "I just saw the type annotation for `" ++ Name.toChars name
1077 ++ "` so I was expecting to see its definition here:"
1079 D.reflow $
1080 "Type annotations always appear directly above the relevant\
1081 \ definition, without anything else (even doc comments) in between."
1084 DeclDefNameMatch defName row col ->
1085 let
1086 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1087 region = toRegion row col
1088 in
1089 Report.Report "NAME MISMATCH" region [] $
1090 Code.toSnippet source surroundings (Just region)
1092 D.reflow $
1093 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
1095 D.stack
1096 [ D.reflow $
1097 "These names do not match! Is there a typo?"
1098 , D.indent 4 $ D.fillSep $
1099 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
1103 DeclDefIndentType row col ->
1104 error "TODO DeclDefIndentType" row col
1106 DeclDefIndentEquals row col ->
1107 error "TODO DeclDefIndentEquals" row col
1109 DeclDefIndentBody row col ->
1110 error "TODO DeclDefIndentBody" row col
1112 DeclDefFreshLineAfterType row col ->
1113 error "TODO DeclDefFreshLineAfterType" row col
1117-- CONTEXT
1120data Context
1121 = InNode Node Row Col Context
1122 | InDef Name.Name Row Col
1125data Node
1126 = NRecord
1127 | NParens
1128 | NList
1129 | NFunc
1130 | NCond
1131 | NThen
1132 | NElse
1133 | NCase
1134 | NBranch
1135 deriving (Eq)
1138getDefName :: Context -> Name.Name
1139getDefName context =
1140 case context of
1141 InDef name _ _ -> name
1142 InNode _ _ _ c -> getDefName c
1145isWithin :: Node -> Context -> Bool
1146isWithin desiredNode context =
1147 case context of
1148 InDef _ _ _ -> False
1149 InNode actualNode _ _ _ -> desiredNode == actualNode
1153-- EXPR REPORTS
1156toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
1157toExprReport source context expr startRow startCol =
1158 case expr of
1159 Let let_ row col ->
1160 toLetReport source context let_ row col
1162 Case case_ row col ->
1163 toCaseReport source context case_ row col
1165 If if_ row col ->
1166 toIfReport source context if_ row col
1168 List list row col ->
1169 toListReport source context list row col
1171 Record record row col ->
1172 toRecordReport source context record row col
1174 Tuple tuple row col ->
1175 toTupleReport source context tuple row col
1177 Func func row col ->
1178 toFuncReport source context func row col
1180 Dot row col ->
1181 let region = toRegion row col in
1182 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1183 Code.toSnippet source region Nothing
1185 D.reflow $
1186 "I was expecting to see a record accessor here:"
1188 D.fillSep
1189 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1190 ,"that","accesses","a","value","from","a","record."
1194 Access row col ->
1195 let region = toRegion row col in
1196 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1197 Code.toSnippet source region Nothing
1199 D.reflow $
1200 "I am trying to parse a record accessor here:"
1202 D.stack
1204 D.fillSep
1205 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1206 ,"that","accesses","a","value","from","a","record."
1209 D.toSimpleNote $
1210 "Record field names must start with a lower case letter!"
1214 OperatorRight op row col ->
1215 let region = toRegion row col in
1216 Report.Report "MISSING EXPRESSION" region [] $
1217 Code.toSnippet source region Nothing
1219 D.reflow $
1220 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1222 D.stack
1223 [ D.fillSep $
1224 ["You","can","just","put","anything","for","now,","like"
1225 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1226 ,"Once","there","is","something","there,","I","can","probably"
1227 ,"give","a","more","specific","hint!"
1229 , D.toSimpleNote $
1230 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1231 \ Or if I run into operators in unexpected spots. Point is, there are a\
1232 \ couple ways I can get confused and give sort of weird advice!"
1236 OperatorReserved operator row col ->
1237 toOperatorReport source context operator row col
1239 Start row col ->
1240 let
1241 (contextRow, contextCol, aThing) =
1242 case context of
1243 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
1244 InNode NRecord r c _ -> (r, c, "a record")
1245 InNode NParens r c _ -> (r, c, "some parentheses")
1246 InNode NList r c _ -> (r, c, "a list")
1247 InNode NFunc r c _ -> (r, c, "an anonymous function")
1248 InNode NCond r c _ -> (r, c, "an `if` expression")
1249 InNode NThen r c _ -> (r, c, "an `if` expression")
1250 InNode NElse r c _ -> (r, c, "an `if` expression")
1251 InNode NCase r c _ -> (r, c, "a `case` expression")
1252 InNode NBranch r c _ -> (r, c, "a `case` expression")
1253 -- TODO check if this is actually the best way to get error messages here
1255 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
1256 region = toRegion row col
1257 in
1258 Report.Report "MISSING EXPRESSION" region [] $
1259 Code.toSnippet source surroundings (Just region)
1261 D.reflow $
1262 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
1264 D.stack
1265 [ D.fillSep $
1266 ["I","was","expecting","to","see","an","expression","like"
1267 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1268 ,"Once","there","is","something","there,","I","can","probably"
1269 ,"give","a","more","specific","hint!"
1271 , D.toSimpleNote $
1272 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1273 \ Or if I run into operators in unexpected spots. Point is, there are a\
1274 \ couple ways I can get confused and give sort of weird advice!"
1278 Char char row col ->
1279 toCharReport source char row col
1281 String string row col ->
1282 toStringReport source string row col
1284 Number number row col ->
1285 toNumberReport source number row col
1287 Space space row col ->
1288 toSpaceReport source space row col
1290 EndlessShader row col ->
1291 let
1292 region = toWiderRegion row col 6
1293 in
1294 Report.Report "ENDLESS SHADER" region [] $
1295 Code.toSnippet source region Nothing
1297 D.reflow "I cannot find the end of this shader:"
1299 D.reflow "Add a |] somewhere after this to end the shader."
1302 ShaderProblem problem row col ->
1303 let
1304 region = toRegion row col
1305 in
1306 Report.Report "SHADER PROBLEM" region [] $
1307 Code.toSnippet source region Nothing
1309 D.reflow $
1310 "I ran into a problem while parsing this GLSL block."
1312 D.stack
1313 [ D.reflow $
1314 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
1315 , D.indent 4 $ D.vcat $
1316 map D.fromChars (filter (/="") (lines problem))
1320 IndentOperatorRight op row col ->
1321 let
1322 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1323 region = toRegion row col
1324 in
1325 Report.Report "MISSING EXPRESSION" region [] $
1326 Code.toSnippet source surroundings (Just region)
1328 D.reflow $
1329 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1331 D.stack
1333 D.fillSep $
1334 ["You","can","just","put","anything","for","now,","like"
1335 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1336 ,"Once","there","is","something","there,","I","can","probably"
1337 ,"give","a","more","specific","hint!"
1340 D.toSimpleNote $
1341 "I may be getting confused by your indentation? The easiest way to make sure\
1342 \ this is not an indentation problem is to put the expression on the right of\
1343 \ the " ++ Name.toChars op ++ " operator on the same line."
1347 IndentMoreExpr _ _ ->
1348 error "TODO IndentMoreExpr"
1352-- CHAR
1355toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
1356toCharReport source char row col =
1357 case char of
1358 CharEndless ->
1359 let
1360 region = toRegion row col
1361 in
1362 Report.Report "MISSING SINGLE QUOTE" region [] $
1363 Code.toSnippet source region Nothing
1365 D.reflow $
1366 "I thought I was parsing a character, but I got to the end of\
1367 \ the line without seeing the closing single quote:"
1369 D.reflow $
1370 "Add a closing single quote here!"
1373 CharEscape escape ->
1374 toEscapeReport source escape row col
1376 CharNotString width ->
1377 let
1378 region = toWiderRegion row col width
1379 in
1380 Report.Report "NEEDS DOUBLE QUOTES" region [] $
1381 Code.toSnippet source region Nothing
1383 "The following string uses single quotes:"
1385 D.stack
1386 [ "Please switch to double quotes instead:"
1387 , D.indent 4 $
1388 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
1389 , D.toSimpleNote $
1390 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
1391 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
1392 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
1393 \ individual characters."
1399-- STRING
1402toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
1403toStringReport source string row col =
1404 case string of
1405 StringEndless_Single ->
1406 let
1407 region = toRegion row col
1408 in
1409 Report.Report "ENDLESS STRING" region [] $
1410 Code.toSnippet source region Nothing
1412 D.reflow $
1413 "I got to the end of the line without seeing the closing double quote:"
1415 D.stack
1416 [ D.fillSep $
1417 ["Strings","look","like",D.green "\"this\"","with","double"
1418 ,"quotes","on","each","end.","Is","the","closing","double"
1419 ,"quote","missing","in","your","code?"
1421 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1425 StringEndless_Multi ->
1426 let
1427 region = toWiderRegion row col 3
1428 in
1429 Report.Report "ENDLESS STRING" region [] $
1430 Code.toSnippet source region Nothing
1432 D.reflow $
1433 "I cannot find the end of this multi-line string:"
1435 D.stack
1436 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1437 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1441 StringEscape escape ->
1442 toEscapeReport source escape row col
1446-- ESCAPES
1449toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1450toEscapeReport source escape row col =
1451 case escape of
1452 EscapeUnknown ->
1453 let
1454 region = toWiderRegion row col 2
1455 in
1456 Report.Report "UNKNOWN ESCAPE" region [] $
1457 Code.toSnippet source region Nothing
1459 D.reflow $
1460 "Backslashes always start escaped characters, but I do not recognize this one:"
1462 D.stack
1463 [ D.reflow $
1464 "Valid escape characters include:"
1465 , D.dullyellow $ D.indent 4 $ D.vcat $
1466 [ "\\n"
1467 , "\\r"
1468 , "\\t"
1469 , "\\\""
1470 , "\\\'"
1471 , "\\\\"
1472 , "\\u{003D}"
1474 , D.reflow $
1475 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1476 , D.toSimpleNote $
1477 "The last style lets encode ANY character by its Unicode code\
1478 \ point. That means \\u{0009} and \\t are the same. You can use\
1479 \ that style for anything not covered by the other six escapes!"
1483 BadUnicodeFormat width ->
1484 let
1485 region = toWiderRegion row col width
1486 in
1487 Report.Report "BAD UNICODE ESCAPE" region [] $
1488 Code.toSnippet source region Nothing
1490 D.reflow $
1491 "I ran into an invalid Unicode escape:"
1493 D.stack
1494 [ D.reflow $
1495 "Here are some examples of valid Unicode escapes:"
1496 , D.dullyellow $ D.indent 4 $ D.vcat $
1497 [ "\\u{0041}"
1498 , "\\u{03BB}"
1499 , "\\u{6728}"
1500 , "\\u{1F60A}"
1502 , D.reflow $
1503 "Notice that the code point is always surrounded by curly braces.\
1504 \ Maybe you are missing the opening or closing curly brace?"
1507 BadUnicodeCode width ->
1508 let
1509 region = toWiderRegion row col width
1510 in
1511 Report.Report "BAD UNICODE ESCAPE" region [] $
1512 Code.toSnippet source region Nothing
1514 D.reflow $
1515 "This is not a valid code point:"
1517 D.reflow $
1518 "The valid code points are between 0 and 10FFFF inclusive."
1521 BadUnicodeLength width numDigits badCode ->
1522 let
1523 region = toWiderRegion row col width
1524 in
1525 Report.Report "BAD UNICODE ESCAPE" region [] $
1526 Code.toSnippet source region Nothing $
1527 if numDigits < 4 then
1529 D.reflow $
1530 "Every code point needs at least four digits:"
1532 let
1533 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1534 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1535 in
1536 D.fillSep ["Try",D.green suggestion,"instead?"]
1539 else
1541 D.reflow $
1542 "This code point has too many digits:"
1544 D.fillSep $
1545 ["Valid","code","points","are","between"
1546 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1547 ,"so","try","trimming","any","leading","zeros","until"
1548 ,"you","have","between","four","and","six","digits."
1554-- NUMBERS
1557toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1558toNumberReport source number row col =
1559 let
1560 region = toRegion row col
1561 in
1562 case number of
1563 NumberEnd ->
1564 Report.Report "WEIRD NUMBER" region [] $
1565 Code.toSnippet source region Nothing
1567 D.reflow $
1568 "I thought I was reading a number, but I ran into some weird stuff here:"
1570 D.stack
1571 [ D.reflow $
1572 "I recognize numbers in the following formats:"
1573 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1574 , D.reflow $
1575 "So is there a way to write it like one of those?"
1579 NumberDot int ->
1580 Report.Report "WEIRD NUMBER" region [] $
1581 Code.toSnippet source region Nothing
1583 D.reflow $
1584 "Numbers cannot end with a dot like this:"
1586 D.fillSep
1587 ["Switching","to",D.green (D.fromChars (show int))
1588 ,"or",D.green (D.fromChars (show int ++ ".0"))
1589 ,"will","work","though!"
1593 NumberHexDigit ->
1594 Report.Report "WEIRD HEXIDECIMAL" region [] $
1595 Code.toSnippet source region Nothing
1597 D.reflow $
1598 "I thought I was reading a hexidecimal number until I got here:"
1600 D.stack
1601 [ D.reflow $
1602 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1603 \ only recognize things like this:"
1604 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1608 NumberNoLeadingZero ->
1609 Report.Report "LEADING ZEROS" region [] $
1610 Code.toSnippet source region Nothing
1612 D.reflow $
1613 "I do not accept numbers with leading zeros:"
1615 D.stack
1616 [ D.reflow $
1617 "Just delete the leading zeros and it should work!"
1618 , D.toSimpleNote $
1619 "Some languages let you to specify octal numbers by adding a leading zero.\
1620 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1621 \ that, but others probably want it to equal 111. Either path is going to\
1622 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1623 \ situation."
1629-- OPERATORS
1632toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
1633toOperatorReport source context operator row col =
1634 case operator of
1635 BadDot ->
1636 let
1637 region = toRegion row col
1638 in
1639 Report.Report "UNEXPECTED SYMBOL" region [] $
1640 Code.toSnippet source region Nothing
1642 "I was not expecting this dot:"
1644 D.reflow $
1645 "Dots are for record access and decimal points, so\
1646 \ they cannot float around on their own. Maybe\
1647 \ there is some extra whitespace?"
1650 BadPipe ->
1651 let
1652 region = toRegion row col
1653 in
1654 Report.Report "UNEXPECTED SYMBOL" region [] $
1655 Code.toSnippet source region Nothing
1657 D.reflow $
1658 "I was not expecting this vertical bar:"
1660 D.reflow $
1661 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1664 BadArrow ->
1665 let
1666 region = toWiderRegion row col 2
1667 in
1668 Report.Report "UNEXPECTED ARROW" region [] $
1669 Code.toSnippet source region Nothing $
1670 if isWithin NBranch context then
1672 D.reflow $
1673 "I was not expecting to see an arrow here:"
1675 D.stack
1677 D.reflow $
1678 "I think I am parsing a `case` expression right now, so it makes sense to\
1679 \ see arrows around here. This one is confusing me though!"
1681 D.toSimpleHint $
1682 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1683 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1684 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1685 \ indented too far?"
1689 else
1691 D.reflow $
1692 "I was not expecting an arrow here:"
1694 D.reflow $
1695 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1696 \ you want > or >= instead?"
1699 BadEquals ->
1700 let
1701 region = toRegion row col
1702 name = getDefName context
1703 in
1704 Report.Report "UNEXPECTED EQUALS" region [] $
1705 Code.toSnippet source region Nothing
1707 D.reflow $
1708 "I was not expecting to see this equals sign:"
1710 D.stack
1712 D.reflow "Maybe you want == instead? To check if two values are equal?"
1714 D.toSimpleNote $
1715 if isWithin NRecord context then
1716 "Records look like { x = 3, y = 4 } with the equals sign right\
1717 \ after the field name. So maybe you forgot a comma?"
1718 else
1719 "I may be getting confused by your indentation. Is this supposed to be part of\
1720 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1721 \ the problem may be a bit before the equals sign. I need all definitions to\
1722 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1723 \ this new definition is indented a bit too much."
1727 BadHasType ->
1728 let
1729 region = toRegion row col
1730 name = getDefName context
1731 in
1732 Report.Report "UNEXPECTED SYMBOL" region [] $
1733 Code.toSnippet source region Nothing $
1735 D.reflow $
1736 "I was not expecting to run into the \"has type\" symbol here:"
1738 D.stack
1740 D.fillSep
1741 ["Maybe","you","want",D.green "::","instead?"
1742 ,"To","put","something","on","the","front","of","a","list?"
1744 , D.toSimpleNote $
1745 "The single colon is reserved for type annotations and record types, but I think\
1746 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1748 D.toSimpleNote $
1749 "I may be getting confused by your indentation. Is this supposed to be part of\
1750 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1751 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1752 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1753 \ this new definition is indented a bit too much."
1759-- CASE
1762toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
1763toLetReport source context let_ startRow startCol =
1764 case let_ of
1765 LetSpace space row col ->
1766 toSpaceReport source space row col
1768 LetIn row col ->
1769 let
1770 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1771 region = toRegion row col
1772 in
1773 Report.Report "LET PROBLEM" region [] $
1774 Code.toSnippet source surroundings (Just region)
1776 D.reflow $
1777 "I was partway through parsing a `let` expression, but I got stuck here:"
1779 D.stack
1780 [ D.fillSep $
1781 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
1782 ,"keyword","next.","Is","there","a","typo?"
1784 , D.toSimpleNote $
1785 "This can also happen if you are trying to define another value within the `let` but\
1786 \ it is not indented enough. Make sure each definition has exactly the same amount of\
1787 \ spaces before it. They should line up exactly!"
1791 LetDefAlignment _ row col ->
1792 let
1793 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1794 region = toRegion row col
1795 in
1796 Report.Report "LET PROBLEM" region [] $
1797 Code.toSnippet source surroundings (Just region)
1799 D.reflow $
1800 "I was partway through parsing a `let` expression, but I got stuck here:"
1802 D.stack
1803 [ D.fillSep $
1804 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
1805 ,"keyword","next.","Is","there","a","typo?"
1807 , D.toSimpleNote $
1808 "This can also happen if you are trying to define another value within the `let` but\
1809 \ it is not indented enough. Make sure each definition has exactly the same amount of\
1810 \ spaces before it. The should line up exactly!"
1814 LetDefName row col ->
1815 case Code.whatIsNext source row col of
1816 Code.Keyword keyword ->
1817 let
1818 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1819 region = toWiderRegion row col (fromIntegral (length keyword))
1820 in
1821 Report.Report "RESERVED WORD" region [] $
1822 Code.toSnippet source surroundings (Just region)
1824 D.reflow $
1825 "I was partway through parsing a `let` expression, but I got stuck here:"
1827 D.reflow $
1828 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
1829 \ it is a reserved word! Try using a different name instead."
1832 _ ->
1833 toUnfinishLetReport source row col startRow startCol $
1834 D.reflow $
1835 "I was expecting the name of a definition next."
1837 LetDef name def row col ->
1838 error "TODO LetDef" name def row col
1840 LetDestruct destruct row col ->
1841 error "TODO LetDestruct" destruct row col
1843 LetBody expr row col ->
1844 toExprReport source context expr row col
1846 LetIndentDef row col ->
1847 toUnfinishLetReport source row col startRow startCol $
1848 D.reflow $
1849 "I was expecting a value to be defined here."
1851 LetIndentIn row col ->
1852 toUnfinishLetReport source row col startRow startCol $
1853 D.fillSep $
1854 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
1855 ,"Or","maybe","more","of","that","expression?"
1858 LetIndentBody row col ->
1859 toUnfinishLetReport source row col startRow startCol $
1860 D.reflow $
1861 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
1864toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
1865toUnfinishLetReport source row col startRow startCol message =
1866 let
1867 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1868 region = toRegion row col
1869 in
1870 Report.Report "UNFINISHED LET" region [] $
1871 Code.toSnippet source surroundings (Just region)
1873 D.reflow $
1874 "I was partway through parsing a `let` expression, but I got stuck here:"
1876 D.stack
1877 [ message
1878 , D.toSimpleNote $
1879 "Here is an example with a valid `let` expression for reference:"
1880 , D.vcat $
1881 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
1882 , D.indent 2 $ D.fillSep [D.cyan "let"]
1883 , D.indent 4 $ D.fillSep ["fullName","="]
1884 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
1885 , D.indent 2 $ D.fillSep [D.cyan "in"]
1886 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
1888 , D.reflow $
1889 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
1890 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
1891 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
1892 \ indented a bit more than that. That is important!"
1898-- CASE
1901toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
1902toCaseReport source context case_ startRow startCol =
1903 case case_ of
1904 CaseSpace space row col ->
1905 toSpaceReport source space row col
1907 CaseOf row col ->
1908 toUnfinishCaseReport source row col startRow startCol $
1909 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
1911 CasePattern pattern row col ->
1912 toPatternReport source PCase pattern row col
1914 CaseArrow row col ->
1915 let
1916 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1917 region = toRegion row col
1918 in
1919 case Code.whatIsNext source row col of
1920 Code.Keyword keyword ->
1921 Report.Report "RESERVED WORD" region [] $
1922 Code.toSnippet source surroundings (Just region)
1924 D.reflow $
1925 "I am partway through parsing a `case` expression, but I got stuck here:"
1927 D.reflow $
1928 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
1929 \ patterns, but it is a reserved word. Try using a different name?"
1932 Code.Operator ":" ->
1933 Report.Report "UNEXPECTED OPERATOR" region [] $
1934 Code.toSnippet source surroundings (Just region)
1936 D.reflow $
1937 "I am partway through parsing a `case` expression, but I got stuck here:"
1939 D.fillSep $
1940 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
1941 ,"For","pattern","matching","on","lists?"
1945 Code.Operator "=" ->
1946 Report.Report "UNEXPECTED OPERATOR" region [] $
1947 Code.toSnippet source surroundings (Just region)
1949 D.reflow $
1950 "I am partway through parsing a `case` expression, but I got stuck here:"
1952 D.fillSep $
1953 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
1957 _ ->
1958 Report.Report "MISSING ARROW" region [] $
1959 Code.toSnippet source surroundings (Just region)
1961 D.reflow $
1962 "I am partway through parsing a `case` expression, but I got stuck here:"
1964 addNoteForCaseIndentError $
1965 D.reflow $
1966 "I was expecting to see an arrow next."
1969 CaseExpr expr row col ->
1970 toExprReport source (InNode NCase startRow startCol context) expr row col
1972 CaseBranch expr row col ->
1973 toExprReport source (InNode NBranch startRow startCol context) expr row col
1975 CaseIndentOf row col ->
1976 toUnfinishCaseReport source row col startRow startCol $
1977 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
1979 CaseIndentExpr row col ->
1980 toUnfinishCaseReport source row col startRow startCol $
1981 D.reflow "I was expecting to see a expression next."
1983 CaseIndentPattern row col ->
1984 toUnfinishCaseReport source row col startRow startCol $
1985 D.reflow "I was expecting to see a pattern next."
1987 CaseIndentArrow row col ->
1988 toUnfinishCaseReport source row col startRow startCol $
1989 D.fillSep
1990 ["I","just","saw","a","pattern,","so","I","was","expecting"
1991 ,"to","see","a",D.dullyellow "->","next."
1994 CaseIndentBranch row col ->
1995 toUnfinishCaseReport source row col startRow startCol $
1996 D.reflow $
1997 "I was expecting to see an expression next. What should I do when\
1998 \ I run into this particular pattern?"
2000 CasePatternAlignment indent row col ->
2001 toUnfinishCaseReport source row col startRow startCol $
2002 D.reflow $
2003 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
2006toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2007toUnfinishCaseReport source row col startRow startCol message =
2008 let
2009 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2010 region = toRegion row col
2011 in
2012 Report.Report "UNFINISHED CASE" region [] $
2013 Code.toSnippet source surroundings (Just region)
2015 D.reflow $
2016 "I was partway through parsing a `case` expression, but I got stuck here:"
2018 D.stack
2019 [ message
2020 , D.toSimpleNote $
2021 "Here is an example of a valid `case` expression for reference."
2022 , D.vcat $
2023 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2024 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2025 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2026 , ""
2027 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2028 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2030 , D.reflow $
2031 "Notice the indentation. Each pattern is aligned, and each branch is indented\
2032 \ a bit more than the corresponding pattern. That is important!"
2037addNoteForCaseIndentError :: D.Doc -> D.Doc
2038addNoteForCaseIndentError message =
2039 D.stack $
2040 message
2042 [ D.toSimpleNote $
2043 "Sometimes I get confused by indentation, so try to make your `case` look\
2044 \ something like this:"
2045 , D.vcat $
2046 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2047 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2048 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2049 , ""
2050 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2051 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2053 , D.reflow $
2054 "Notice the indentation! Each pattern is aligned, and each branch is indented\
2055 \ a bit more than the corresponding pattern. That is important!"
2060-- IF
2063toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
2064toIfReport source context if_ startRow startCol =
2065 case if_ of
2066 IfSpace space row col ->
2067 toSpaceReport source space row col
2069 IfThen row col ->
2070 let
2071 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2072 region = toRegion row col
2073 in
2074 Report.Report "UNFINISHED IF" region [] $
2075 Code.toSnippet source surroundings (Just region)
2077 D.reflow $
2078 "I was expecting to see more of this `if` expression, but I got stuck here:"
2080 D.fillSep $
2081 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2085 IfElse row col ->
2086 let
2087 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2088 region = toRegion row col
2089 in
2090 Report.Report "UNFINISHED IF" region [] $
2091 Code.toSnippet source surroundings (Just region)
2093 D.reflow $
2094 "I was expecting to see more of this `if` expression, but I got stuck here:"
2096 D.fillSep $
2097 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
2101 IfElseBranchStart row col ->
2102 let
2103 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2104 region = toRegion row col
2105 in
2106 Report.Report "UNFINISHED IF" region [] $
2107 Code.toSnippet source surroundings (Just region)
2109 D.reflow $
2110 "I just saw the start of an `else` branch, but then I got stuck here:"
2112 D.reflow $
2113 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2116 IfCondition expr row col ->
2117 toExprReport source (InNode NCond startRow startCol context) expr row col
2119 IfThenBranch expr row col ->
2120 toExprReport source (InNode NThen startRow startCol context) expr row col
2122 IfElseBranch expr row col ->
2123 toExprReport source (InNode NElse startRow startCol context) expr row col
2125 IfIndentCondition row col ->
2126 let
2127 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2128 region = toRegion row col
2129 in
2130 Report.Report "UNFINISHED IF" region [] $
2131 Code.toSnippet source surroundings (Just region)
2133 D.reflow $
2134 "I was expecting to see more of this `if` expression, but I got stuck here:"
2136 D.stack
2137 [ D.fillSep $
2138 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
2139 ,"that","evaluates","to","True","or","False."
2141 , D.toSimpleNote $
2142 "I can be confused by indentation. Maybe something is not indented enough?"
2146 IfIndentThen row col ->
2147 let
2148 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2149 region = toRegion row col
2150 in
2151 Report.Report "UNFINISHED IF" region [] $
2152 Code.toSnippet source surroundings (Just region)
2154 D.reflow $
2155 "I was expecting to see more of this `if` expression, but I got stuck here:"
2157 D.stack
2158 [ D.fillSep $
2159 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2161 , D.toSimpleNote $
2162 "I can be confused by indentation. Maybe something is not indented enough?"
2166 IfIndentThenBranch row col ->
2167 let
2168 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2169 region = toRegion row col
2170 in
2171 Report.Report "UNFINISHED IF" region [] $
2172 Code.toSnippet source surroundings (Just region)
2174 D.reflow $
2175 "I got stuck after the start of this `then` branch:"
2177 D.stack
2178 [ D.reflow $
2179 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2180 , D.toSimpleNote $
2181 "I can be confused by indentation, so if the `then` branch is already\
2182 \ present, it may not be indented enough for me to recognize it."
2186 IfIndentElseBranch row col ->
2187 let
2188 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2189 region = toRegion row col
2190 in
2191 Report.Report "UNFINISHED IF" region [] $
2192 Code.toSnippet source surroundings (Just region)
2194 D.reflow $
2195 "I got stuck after the start of this `else` branch:"
2197 D.stack
2198 [ D.reflow $
2199 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2200 , D.toSimpleNote $
2201 "I can be confused by indentation, so if the `else` branch is already\
2202 \ present, it may not be indented enough for me to recognize it."
2206 IfIndentElse row col ->
2207 let
2208 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2209 region = toRegion row col
2210 in
2211 Report.Report "UNFINISHED IF" region [] $
2212 Code.toSnippet source surroundings (Just region)
2214 D.reflow $
2215 "I was expecting to see an `else` branch after this:"
2217 D.stack
2218 [ D.reflow $
2219 "I know what to do when the condition is `True`, but not when it is `False`."
2220 , D.fillSep
2221 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
2227-- RECORD
2230toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
2231toRecordReport source context record startRow startCol =
2232 case record of
2233 RecordOpen row col ->
2234 let
2235 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2236 region = toRegion row col
2237 in
2238 case Code.whatIsNext source row col of
2239 Code.Keyword keyword ->
2240 Report.Report "RESERVED WORD" region [] $
2241 Code.toSnippet source surroundings (Just region)
2243 D.reflow $
2244 "I just started parsing a record, but I got stuck on this field name:"
2246 D.reflow $
2247 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
2248 \ that is a reserved word. Try using a different name!"
2251 _ ->
2252 Report.Report "UNFINISHED RECORD" region [] $
2253 Code.toSnippet source surroundings (Just region)
2255 D.reflow $
2256 "I just started parsing a record, but I got stuck here:"
2258 D.fillSep
2259 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
2260 ,"so","I","was","expecting","to","see","a","field","name","next."
2264 RecordEnd row col ->
2265 let
2266 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2267 region = toRegion row col
2268 in
2269 Report.Report "UNFINISHED RECORD" region [] $
2270 Code.toSnippet source surroundings (Just region)
2272 D.reflow $
2273 "I am partway through parsing a record, but I got stuck here:"
2275 D.stack
2276 [ D.fillSep
2277 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
2278 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
2280 , D.toSimpleNote $
2281 "When I get stuck like this, it usually means that there is a missing parenthesis\
2282 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2286 RecordField row col ->
2287 let
2288 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2289 region = toRegion row col
2290 in
2291 case Code.whatIsNext source row col of
2292 Code.Keyword keyword ->
2293 Report.Report "RESERVED WORD" region [] $
2294 Code.toSnippet source surroundings (Just region)
2296 D.reflow $
2297 "I am partway through parsing a record, but I got stuck on this field name:"
2299 D.reflow $
2300 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
2301 \ that is a reserved word. Try using a different name!"
2304 _ ->
2305 Report.Report "UNFINISHED RECORD" region [] $
2306 Code.toSnippet source surroundings (Just region)
2308 D.reflow $
2309 "I am partway through parsing a record, but I got stuck after that last comma:"
2311 addNoteForRecordError $
2312 D.reflow $
2313 "Trailing commas are not allowed in records, so I was expecting to see another\
2314 \ record field defined next. If you are done defining the record, the fix may\
2315 \ be to delete that last comma?"
2318 RecordEquals row col ->
2319 let
2320 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2321 region = toRegion row col
2322 in
2323 Report.Report "UNFINISHED RECORD" region [] $
2324 Code.toSnippet source surroundings (Just region)
2326 D.reflow $
2327 "I am partway through parsing a record, but I got stuck here:"
2329 addNoteForRecordError $
2330 D.fillSep $
2331 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
2332 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
2336 RecordExpr expr row col ->
2337 toExprReport source (InNode NRecord startRow startCol context) expr row col
2339 RecordSpace space row col ->
2340 toSpaceReport source space row col
2342 RecordIndentOpen row col ->
2343 let
2344 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2345 region = toRegion row col
2346 in
2347 Report.Report "UNFINISHED RECORD" region [] $
2348 Code.toSnippet source surroundings (Just region)
2350 D.reflow $
2351 "I just saw the opening curly brace of a record, but then I got stuck here:"
2353 addNoteForRecordIndentError $
2354 D.fillSep $
2355 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
2356 ,"Try","defining","some","fields","of","your","own?"
2360 RecordIndentEnd row col ->
2361 let
2362 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2363 region = toRegion row col
2364 in
2365 Report.Report "UNFINISHED RECORD" region [] $
2366 Code.toSnippet source surroundings (Just region)
2368 D.reflow $
2369 "I was expecting to see a closing curly brace next:"
2371 addNoteForRecordIndentError $
2372 D.fillSep $
2373 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
2377 RecordIndentField row col ->
2378 let
2379 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2380 region = toRegion row col
2381 in
2382 Report.Report "UNFINISHED RECORD" region [] $
2383 Code.toSnippet source surroundings (Just region)
2385 D.reflow $
2386 "I am partway through parsing a record, but I got stuck after that last comma:"
2388 addNoteForRecordError $
2389 D.reflow $
2390 "Trailing commas are not allowed in records, so the fix may be to\
2391 \ delete that last comma? Or maybe you were in the middle of defining\
2392 \ an additional field?"
2395 RecordIndentEquals row col ->
2396 let
2397 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2398 region = toRegion row col
2399 in
2400 Report.Report "UNFINISHED RECORD" region [] $
2401 Code.toSnippet source surroundings (Just region)
2403 D.reflow $
2404 "I am partway through parsing a record. I just saw a record\
2405 \ field, so I was expecting to see an equals sign next:"
2407 addNoteForRecordIndentError $
2408 D.fillSep $
2409 ["Try","putting","an",D.green "=","followed","by","an","expression?"
2413 RecordIndentExpr row col ->
2414 let
2415 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2416 region = toRegion row col
2417 in
2418 Report.Report "UNFINISHED RECORD" region [] $
2419 Code.toSnippet source surroundings (Just region)
2421 D.reflow $
2422 "I am partway through parsing a record, and I was expecting to run into an expression next:"
2424 addNoteForRecordIndentError $
2425 D.fillSep $
2426 ["Try","putting","something,","like"
2427 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
2432addNoteForRecordError :: D.Doc -> D.Doc
2433addNoteForRecordError normalRecommendation =
2434 D.stack $
2435 normalRecommendation
2437 [ D.toSimpleNote
2438 "If you are trying to define a record across multiple lines, I recommend using this format:"
2439 , D.indent 4 $ D.vcat $
2440 [ "{ name = \"Alice\""
2441 , ", age = 42"
2442 , ", height = 1.75"
2443 , "}"
2445 , D.reflow $
2446 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
2447 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2448 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2452addNoteForRecordIndentError :: D.Doc -> D.Doc
2453addNoteForRecordIndentError normalRecommendation =
2454 D.stack $
2455 normalRecommendation
2457 [ D.toSimpleNote
2458 "I may be confused by indentation. For example, if you are trying to define\
2459 \ a record across multiple lines, I recommend using this format:"
2460 , D.indent 4 $ D.vcat $
2461 [ "[ \"Alice\""
2462 , ", \"Bob\""
2463 , ", \"Chuck\""
2464 , "]"
2466 , D.reflow $
2467 "Notice that nothing comes directly after a newline. Each line starts with some spaces. I\
2468 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2469 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2474-- TUPLE
2477toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
2478toTupleReport source context tuple startRow startCol =
2479 case tuple of
2480 TupleExpr expr row col ->
2481 toExprReport source (InNode NParens startRow startCol context) expr row col
2483 TupleSpace space row col ->
2484 toSpaceReport source space row col
2486 TupleEnd row col ->
2487 let
2488 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2489 region = toRegion row col
2490 in
2491 Report.Report "UNFINISHED PARENTHESES" region [] $
2492 Code.toSnippet source surroundings (Just region)
2494 D.reflow $
2495 "I was expecting to see a closing parentheses next, but I got stuck here:"
2497 D.stack
2498 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
2499 , D.toSimpleNote $
2500 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
2501 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
2502 \ or missing brackets) that is confusing me."
2506 TupleOperatorClose row col ->
2507 let
2508 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2509 region = toRegion row col
2510 in
2511 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
2512 Code.toSnippet source surroundings (Just region)
2514 D.reflow "I was expecting a closing parenthesis here:"
2516 D.stack
2517 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2518 , D.toSimpleNote $
2519 "I think I am parsing an operator function right now, so I am expecting to see\
2520 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
2521 \ no extra spaces."
2525 TupleOperatorReserved operator row col ->
2526 let
2527 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2528 region = toRegion row col
2529 in
2530 Report.Report "UNEXPECTED SYMBOL" region [] $
2531 Code.toSnippet source surroundings (Just region)
2533 D.reflow $
2534 "I ran into an unexpected symbol here:"
2536 D.fillSep $
2537 case operator of
2538 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
2539 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
2540 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
2541 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
2542 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
2545 TupleIndentExpr1 row col ->
2546 let
2547 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2548 region = toRegion row col
2549 in
2550 Report.Report "UNFINISHED PARENTHESES" region [] $
2551 Code.toSnippet source surroundings (Just region)
2553 D.reflow $
2554 "I just saw an open parenthesis, so I was expecting to see an expression next."
2556 D.stack
2557 [ D.fillSep $
2558 ["Something","like",D.dullyellow "(4 + 5)","or"
2559 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
2560 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
2562 , D.toSimpleNote $
2563 "I can get confused by indentation in cases like this, so\
2564 \ maybe you have an expression but it is not indented enough?"
2568 TupleIndentExprN row col ->
2569 let
2570 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2571 region = toRegion row col
2572 in
2573 Report.Report "UNFINISHED TUPLE" region [] $
2574 Code.toSnippet source surroundings (Just region)
2576 D.reflow $
2577 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see expression next."
2579 D.stack
2580 [ D.fillSep $
2581 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
2582 ,D.dullyellow "(\"Tom\",42)" <> ","
2583 ,"so","I","think","there","is","an","expression","missing","here?"
2585 , D.toSimpleNote $
2586 "I can get confused by indentation in cases like this, so\
2587 \ maybe you have an expression but it is not indented enough?"
2591 TupleIndentEnd row col ->
2592 let
2593 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2594 region = toRegion row col
2595 in
2596 Report.Report "UNFINISHED PARENTHESES" region [] $
2597 Code.toSnippet source surroundings (Just region)
2599 D.reflow $
2600 "I was expecting to see a closing parenthesis next:"
2602 D.stack
2603 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2604 , D.toSimpleNote $
2605 "I can get confused by indentation in cases like this, so\
2606 \ maybe you have a closing parenthesis but it is not indented enough?"
2611toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
2612toListReport source context list startRow startCol =
2613 case list of
2614 ListSpace space row col ->
2615 toSpaceReport source space row col
2617 ListOpen row col ->
2618 let
2619 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2620 region = toRegion row col
2621 in
2622 Report.Report "UNFINISHED LIST" region [] $
2623 Code.toSnippet source surroundings (Just region)
2625 D.reflow $
2626 "I am partway through parsing a list, but I got stuck here:"
2628 D.stack
2629 [ D.fillSep
2630 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2631 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2633 , D.toSimpleNote $
2634 "When I get stuck like this, it usually means that there is a missing parenthesis\
2635 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2639 ListExpr expr row col ->
2640 case expr of
2641 Start r c ->
2642 let
2643 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
2644 region = toRegion r c
2645 in
2646 Report.Report "UNFINISHED LIST" region [] $
2647 Code.toSnippet source surroundings (Just region)
2649 D.reflow $
2650 "I was expecting to see another list entry after that last comma:"
2652 D.stack
2653 [ D.reflow $
2654 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2655 , D.toSimpleNote
2656 "I recommend using the following format for lists that span multiple lines:"
2657 , D.indent 4 $ D.vcat $
2658 [ "[ \"Alice\""
2659 , ", \"Bob\""
2660 , ", \"Chuck\""
2661 , "]"
2663 , D.reflow $
2664 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2665 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2666 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2670 _ ->
2671 toExprReport source (InNode NList startRow startCol context) expr row col
2673 ListEnd row col ->
2674 let
2675 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2676 region = toRegion row col
2677 in
2678 Report.Report "UNFINISHED LIST" region [] $
2679 Code.toSnippet source surroundings (Just region)
2681 D.reflow $
2682 "I am partway through parsing a list, but I got stuck here:"
2684 D.stack
2685 [ D.fillSep
2686 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2687 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2689 , D.toSimpleNote $
2690 "When I get stuck like this, it usually means that there is a missing parenthesis\
2691 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2695 ListIndentOpen row col ->
2696 let
2697 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2698 region = toRegion row col
2699 in
2700 Report.Report "UNFINISHED LIST" region [] $
2701 Code.toSnippet source surroundings (Just region)
2703 D.reflow $
2704 "I cannot find the end of this list:"
2706 D.stack
2707 [ D.fillSep $
2708 ["You","could","change","it","to","something","like"
2709 ,D.dullyellow "[3,4,5]"
2710 ,"or","even","just"
2711 ,D.dullyellow "[]" <> "."
2712 ,"Anything","where","there","is","an","open","and","close","square","brace,"
2713 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
2715 , D.toSimpleNote
2716 "I may be confused by indentation. For example, if you are trying to define\
2717 \ a list across multiple lines, I recommend using this format:"
2718 , D.indent 4 $ D.vcat $
2719 [ "[ \"Alice\""
2720 , ", \"Bob\""
2721 , ", \"Chuck\""
2722 , "]"
2724 , D.reflow $
2725 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2726 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2727 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2731 ListIndentEnd row col ->
2732 let
2733 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2734 region = toRegion row col
2735 in
2736 Report.Report "UNFINISHED LIST" region [] $
2737 Code.toSnippet source surroundings (Just region)
2739 D.reflow $
2740 "I cannot find the end of this list:"
2742 D.stack
2743 [ D.fillSep $
2744 ["You","can","just","add","a","closing",D.dullyellow "]"
2745 ,"right","here,","and","I","will","be","all","set!"
2747 , D.toSimpleNote
2748 "I may be confused by indentation. For example, if you are trying to define\
2749 \ a list across multiple lines, I recommend using this format:"
2750 , D.indent 4 $ D.vcat $
2751 [ "[ \"Alice\""
2752 , ", \"Bob\""
2753 , ", \"Chuck\""
2754 , "]"
2756 , D.reflow $
2757 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2758 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2759 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2763 ListIndentExpr row col ->
2764 let
2765 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2766 region = toRegion row col
2767 in
2768 Report.Report "UNFINISHED LIST" region [] $
2769 Code.toSnippet source surroundings (Just region)
2771 D.reflow $
2772 "I was expecting to see another list entry after this comma:"
2774 D.stack
2775 [ D.reflow $
2776 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2777 , D.toSimpleNote
2778 "I recommend using the following format for lists that span multiple lines:"
2779 , D.indent 4 $ D.vcat $
2780 [ "[ \"Alice\""
2781 , ", \"Bob\""
2782 , ", \"Chuck\""
2783 , "]"
2785 , D.reflow $
2786 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2787 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2788 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2793toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
2794toFuncReport source context func startRow startCol =
2795 case func of
2796 FuncSpace space row col ->
2797 toSpaceReport source space row col
2799 FuncArg pattern row col ->
2800 toPatternReport source PArg pattern row col
2802 FuncBody expr row col ->
2803 toExprReport source (InNode NFunc startRow startCol context) expr row col
2805 FuncArrow row col ->
2806 let
2807 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2808 region = toRegion row col
2809 in
2810 case Code.whatIsNext source row col of
2811 Code.Keyword keyword ->
2812 Report.Report "RESERVED WORD" region [] $
2813 Code.toSnippet source surroundings (Just region)
2815 D.reflow $
2816 "I was parsing an anonymous function, but I got stuck here:"
2818 D.reflow $
2819 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
2820 \ it is a reserved word in this language. Try using a different argument name!"
2823 _ ->
2824 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2825 Code.toSnippet source surroundings (Just region)
2827 D.reflow $
2828 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2830 D.fillSep $
2831 ["The","syntax","for","anonymous","functions","is"
2832 ,D.dullyellow "(\\x -> x + 1)"
2833 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2837 FuncIndentArg row col ->
2838 let
2839 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2840 region = toRegion row col
2841 in
2842 Report.Report "MISSING ARGUMENT" region [] $
2843 Code.toSnippet source surroundings (Just region)
2845 D.reflow $
2846 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
2848 D.stack
2849 [ D.fillSep
2850 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
2851 ,"Anything","that","starts","with","a","lower","case","letter!"
2853 , D.toSimpleNote $
2854 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
2855 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
2856 \ like a better idea at the time!"
2860 FuncIndentArrow row col ->
2861 let
2862 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2863 region = toRegion row col
2864 in
2865 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2866 Code.toSnippet source surroundings (Just region)
2868 D.reflow $
2869 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
2871 D.stack
2872 [ D.fillSep $
2873 ["The","syntax","for","anonymous","functions","is"
2874 ,D.dullyellow "(\\x -> x + 1)"
2875 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
2877 , D.toSimpleNote $
2878 "It is possible that I am confused about indetation! I generally recommend\
2879 \ switching to named functions if the definition cannot fit inline nicely, so\
2880 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2881 \ the whole thing out into a named function. Things tend to be clearer that way!"
2885 FuncIndentBody row col ->
2886 let
2887 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2888 region = toRegion row col
2889 in
2890 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
2891 Code.toSnippet source surroundings (Just region)
2893 D.reflow $
2894 "I was expecting to see the body of your anonymous function next:"
2896 D.stack
2897 [ D.fillSep $
2898 ["The","syntax","for","anonymous","functions","is"
2899 ,D.dullyellow "(\\x -> x + 1)"
2900 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
2902 , D.toSimpleNote $
2903 "It is possible that I am confused about indetation! I generally recommend\
2904 \ switching to named functions if the definition cannot fit inline nicely, so\
2905 \ either (1) try to fit the whole anonymous function on one line or (2) break\
2906 \ the whole thing out into a named function. Things tend to be clearer that way!"
2912-- PATTERN
2915data PContext
2916 = PCase
2917 | PArg
2920toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
2921toPatternReport source context pattern startRow startCol =
2922 case pattern of
2923 PRecord record row col ->
2924 toPRecordReport source record row col
2926 PTuple tuple row col ->
2927 toPTupleReport source context tuple row col
2929 PList list row col ->
2930 toPListReport source context list row col
2932 PStart row col ->
2933 case Code.whatIsNext source row col of
2934 Code.Keyword keyword ->
2935 let
2936 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2937 region = toWiderRegion row col (fromIntegral (length keyword))
2938 aThing =
2939 case context of
2940 PArg -> "an argument"
2941 PCase -> "a pattern"
2942 in
2943 Report.Report "RESERVED WORD" region [] $
2944 Code.toSnippet source surroundings (Just region)
2946 D.reflow $
2947 "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
2949 D.reflow $
2950 "This is a reserved word! Try using some other name?"
2953 _ ->
2954 error "TODO PStart"
2956 PChar char row col ->
2957 toCharReport source char row col
2959 PString string row col ->
2960 toStringReport source string row col
2962 PNumber number row col ->
2963 toNumberReport source number row col
2965 PFloat width row col ->
2966 let
2967 region = toWiderRegion row col width
2968 in
2969 Report.Report "UNEXPECTED PATTERN" region [] $
2970 Code.toSnippet source region Nothing
2972 D.reflow $
2973 "I cannot pattern match with floating point numbers:"
2975 D.fillSep $
2976 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
2977 ,"to","check","that","they","are","nearby","with","some","sort","of"
2978 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
2982 PAlias row col ->
2983 let
2984 region = toRegion row col
2985 in
2986 Report.Report "UNFINISHED PATTERN" region [] $
2987 Code.toSnippet source region Nothing $
2989 D.reflow $
2990 "I was expecting to see a variable name after the `as` keyword:"
2992 D.stack
2993 [ D.fillSep $
2994 ["The","`as`","keyword","lets","you","write","patterns","like"
2995 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
2996 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
2997 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
2998 ,"thing","with",D.dullyellow "point."
3000 , D.reflow $
3001 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3002 \ people just want to use `as` as a variable name though. Try using a different name\
3003 \ in that case!"
3007 PWildcardNotVar name width row col ->
3008 let
3009 region = toWiderRegion row col (fromIntegral width)
3010 examples =
3011 case dropWhile (=='_') (Name.toChars name) of
3012 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
3013 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
3014 in
3015 Report.Report "UNEXPECTED NAME" region [] $
3016 Code.toSnippet source region Nothing $
3018 D.reflow $
3019 "Variable names cannot start with underscores like this:"
3021 D.fillSep $
3022 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
3023 ,"ignore","the","value,","or","you","can","have","a","name","like"
3024 ] ++ examples ++ ["to","use","the","matched","value." ]
3027 PSpace space row col ->
3028 toSpaceReport source space row col
3030 PIndentStart row col ->
3031 error "TODO PIndentStart" row col
3033 PIndentAlias row col ->
3034 let
3035 region = toRegion row col
3036 in
3037 Report.Report "UNFINISHED PATTERN" region [] $
3038 Code.toSnippet source region Nothing $
3040 D.reflow $
3041 "I was expecting to see a variable name after the `as` keyword:"
3043 D.stack
3044 [ D.fillSep $
3045 ["The","`as`","keyword","lets","you","write","patterns","like"
3046 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3047 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3048 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3049 ,"thing","with",D.dullyellow "point."
3051 , D.reflow $
3052 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3053 \ people just want to use `as` as a variable name though. Try using a different name\
3054 \ in that case!"
3059toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
3060toPRecordReport source record startRow startCol =
3061 case record of
3062 PRecordOpen row col ->
3063 toUnfinishRecordPatternReport source row col startRow startCol $
3064 D.reflow "I was expecting to see a field name next."
3066 PRecordEnd row col ->
3067 toUnfinishRecordPatternReport source row col startRow startCol $
3068 D.fillSep
3069 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3070 ,"Try","adding","a",D.dullyellow "}","here?"
3073 PRecordField row col ->
3074 case Code.whatIsNext source row col of
3075 Code.Keyword keyword ->
3076 let
3077 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3078 region = toWiderRegion row col (fromIntegral (length keyword))
3079 in
3080 Report.Report "RESERVED WORD" region [] $
3081 Code.toSnippet source surroundings (Just region)
3083 D.reflow $
3084 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
3086 D.reflow $
3087 "This is a reserved word, not available for variable names. Try another name!"
3090 _ ->
3091 toUnfinishRecordPatternReport source row col startRow startCol $
3092 D.reflow "I was expecting to see a field name next."
3094 PRecordSpace space row col ->
3095 toSpaceReport source space row col
3097 PRecordIndentOpen row col ->
3098 toUnfinishRecordPatternReport source row col startRow startCol $
3099 D.reflow "I was expecting to see a field name next."
3101 PRecordIndentEnd row col ->
3102 toUnfinishRecordPatternReport source row col startRow startCol $
3103 D.fillSep
3104 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3105 ,"Try","adding","a",D.dullyellow "}","here?"
3108 PRecordIndentField row col ->
3109 toUnfinishRecordPatternReport source row col startRow startCol $
3110 D.reflow "I was expecting to see a field name next."
3113toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3114toUnfinishRecordPatternReport source row col startRow startCol message =
3115 let
3116 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3117 region = toRegion row col
3118 in
3119 Report.Report "UNFINISHED RECORD PATTERN" region [] $
3120 Code.toSnippet source surroundings (Just region)
3122 D.reflow $
3123 "I was partway through parsing a record pattern, but I got stuck here:"
3125 D.stack
3126 [ message
3127 , D.toFancyHint $
3128 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
3129 ,"where","you","list","the","field","names","you","want","to","access."
3136toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
3137toPTupleReport source context tuple startRow startCol =
3138 case tuple of
3139 PTupleOpen row col ->
3140 case Code.whatIsNext source row col of
3141 Code.Keyword keyword ->
3142 let
3143 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3144 region = toWiderRegion row col (fromIntegral (length keyword))
3145 in
3146 Report.Report "RESERVED WORD" region [] $
3147 Code.toSnippet source surroundings (Just region)
3149 D.reflow $
3150 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
3152 D.reflow $
3153 "This is a reserved word! Try using some other name?"
3156 _ ->
3157 let
3158 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3159 region = toRegion row col
3160 in
3161 Report.Report "UNFINISHED PARENTHESES" region [] $
3162 Code.toSnippet source surroundings (Just region)
3164 D.reflow $
3165 "I just saw an open parenthesis, but I got stuck here:"
3167 D.fillSep
3168 ["I","was","expecting","so","see","a","pattern","next."
3169 ,"Maybe","it","will","end","up","being","something"
3170 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
3174 PTupleEnd row col ->
3175 let
3176 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3177 region = toRegion row col
3178 in
3179 Report.Report "UNFINISHED PARENTHESES" region [] $
3180 Code.toSnippet source surroundings (Just region) $
3182 D.reflow $
3183 "I was expecting a closing parenthesis next:"
3185 D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3188 PTupleExpr pattern row col ->
3189 toPatternReport source context pattern row col
3191 PTupleSpace space row col ->
3192 toSpaceReport source space row col
3194 PTupleIndentEnd row col ->
3195 let
3196 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3197 region = toRegion row col
3198 in
3199 Report.Report "UNFINISHED PARENTHESES" region [] $
3200 Code.toSnippet source surroundings (Just region) $
3202 D.reflow $
3203 "I was expecting a closing parenthesis next:"
3205 D.stack
3206 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3207 , D.toSimpleNote $
3208 "I can get confused by indentation in cases like this, so\
3209 \ maybe you have a closing parenthesis but it is not indented enough?"
3213 PTupleIndentExpr1 row col ->
3214 let
3215 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3216 region = toRegion row col
3217 in
3218 Report.Report "UNFINISHED PARENTHESES" region [] $
3219 Code.toSnippet source surroundings (Just region) $
3221 D.reflow $
3222 "I just saw an open parenthesis, but then I got stuck here:"
3224 D.fillSep
3225 ["I","was","expecting","so","see","a","pattern","next."
3226 ,"Maybe","it","will","end","up","being","something"
3227 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
3231 PTupleIndentExprN row col ->
3232 let
3233 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3234 region = toRegion row col
3235 in
3236 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
3237 Code.toSnippet source surroundings (Just region) $
3239 D.reflow $
3240 "I am partway through parsing a tuple pattern, but I got stuck here:"
3242 D.stack
3243 [ D.fillSep
3244 ["I","was","expecting","so","see","a","pattern","next."
3245 ,"I","am","expecting","the","final","result","to","be","something"
3246 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
3248 , D.toSimpleNote $
3249 "I can get confused by indentation in cases like this, so the problem\
3250 \ may be that the next part is not indented enough?"
3255toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
3256toPListReport source context list startRow startCol =
3257 case list of
3258 PListOpen row col ->
3259 case Code.whatIsNext source row col of
3260 Code.Keyword keyword ->
3261 let
3262 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3263 region = toWiderRegion row col (fromIntegral (length keyword))
3264 in
3265 Report.Report "RESERVED WORD" region [] $
3266 Code.toSnippet source surroundings (Just region)
3268 D.reflow $
3269 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
3271 D.reflow $
3272 "This is a reserved word though! Try using some other name?"
3275 _ ->
3276 let
3277 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3278 region = toRegion row col
3279 in
3280 Report.Report "UNFINISHED LIST PATTERN" region [] $
3281 Code.toSnippet source surroundings (Just region) $
3283 D.reflow $
3284 "I just saw an open square bracket, but then I got stuck here:"
3286 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3289 PListEnd row col ->
3290 let
3291 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3292 region = toRegion row col
3293 in
3294 Report.Report "UNFINISHED LIST PATTERN" region [] $
3295 Code.toSnippet source surroundings (Just region) $
3297 D.reflow $
3298 "I was expecting a closing square bracket to end this list pattern:"
3300 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3303 PListExpr pattern row col ->
3304 toPatternReport source context pattern row col
3306 PListSpace space row col ->
3307 toSpaceReport source space row col
3309 PListIndentOpen row col ->
3310 let
3311 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3312 region = toRegion row col
3313 in
3314 Report.Report "UNFINISHED LIST PATTERN" region [] $
3315 Code.toSnippet source surroundings (Just region) $
3317 D.reflow $
3318 "I just saw an open square bracket, but then I got stuck here:"
3320 D.stack
3321 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3322 , D.toSimpleNote $
3323 "I can get confused by indentation in cases like this, so\
3324 \ maybe there is something next, but it is not indented enough?"
3328 PListIndentEnd row col ->
3329 let
3330 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3331 region = toRegion row col
3332 in
3333 Report.Report "UNFINISHED LIST PATTERN" region [] $
3334 Code.toSnippet source surroundings (Just region) $
3336 D.reflow $
3337 "I was expecting a closing square bracket to end this list pattern:"
3339 D.stack
3340 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3341 , D.toSimpleNote $
3342 "I can get confused by indentation in cases like this, so\
3343 \ maybe you have a closing square bracket but it is not indented enough?"
3347 PListIndentExpr row col ->
3348 let
3349 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3350 region = toRegion row col
3351 in
3352 Report.Report "UNFINISHED LIST PATTERN" region [] $
3353 Code.toSnippet source surroundings (Just region) $
3355 D.reflow $
3356 "I am partway through parsing a list pattern, but I got stuck here:"
3358 D.stack
3359 [ D.reflow $
3360 "I was expecting to see another pattern next. Maybe a variable name."
3361 , D.toSimpleNote $
3362 "I can get confused by indentation in cases like this, so\
3363 \ maybe there is more to this pattern but it is not indented enough?"
3369-- TYPES
3372toTypeReport :: Code.Source -> Type -> Row -> Col -> Report.Report
3373toTypeReport source tipe startRow startCol =
3374 case tipe of
3375 TRecord record row col ->
3376 toTRecordReport source record row col
3378 TTuple tuple row col ->
3379 toTTupleReport source tuple row col
3381 TVariant row col ->
3382 error "TODO TVariant" row col startRow startCol
3384 TArrow row col ->
3385 error "TODO TArrow" row col
3387 TStart row col ->
3388 error "TODO TStart" row col
3390 TSpace space row col ->
3391 toSpaceReport source space row col
3393 TIndentStart row col ->
3394 error "TODO TIndentStart" row col
3398toTRecordReport :: Code.Source -> TRecord -> Row -> Col -> Report.Report
3399toTRecordReport source record startRow startCol =
3400 case record of
3401 TRecordOpen row col ->
3402 error "TODO TRecordOpen" row col startRow startCol
3404 TRecordEnd row col ->
3405 error "TODO TRecordEnd" row col
3407 TRecordField row col ->
3408 error "TODO TRecordField" row col
3410 TRecordColon row col ->
3411 error "TODO TRecordColon" row col
3413 TRecordType tipe row col ->
3414 error "TODO TRecordType" tipe row col
3416 TRecordSpace space row col ->
3417 toSpaceReport source space row col
3419 TRecordIndentOpen row col ->
3420 error "TODO TRecordIndentOpen" row col
3422 TRecordIndentField row col ->
3423 error "TODO TRecordIndentField" row col
3425 TRecordIndentColon row col ->
3426 error "TODO TRecordIndentColon" row col
3428 TRecordIndentType row col ->
3429 error "TODO TRecordIndentType" row col
3431 TRecordIndentEnd row col ->
3432 error "TODO TRecordIndentEnd" row col
3436toTTupleReport :: Code.Source -> TTuple -> Row -> Col -> Report.Report
3437toTTupleReport source tuple startRow startCol =
3438 case tuple of
3439 TTupleOpen row col ->
3440 error "TODO TTupleOpen" row col startRow startCol
3442 TTupleEnd row col ->
3443 error "TODO TTupleEnd" row col
3445 TTupleType tipe row col ->
3446 error "TODO TTupleType" tipe row col
3448 TTupleSpace space row col ->
3449 toSpaceReport source space row col
3451 TTupleIndentOpen row col ->
3452 error "TODO TTupleIndentOpen" row col
3454 TTupleIndentType row col ->
3455 error "TODO TTupleIndentType" row col
3457 TTupleIndentEnd row col ->
3458 error "TODO TTupleIndentEnd" row col