on 3cb82f2 help sign in
4015 lines 139 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 | TArrow Row Col
421 --
422 | TStart Row Col
423 | TSpace Space Row Col
424 --
425 | TIndentStart Row Col
428data TRecord
429 = TRecordOpen Row Col
430 | TRecordEnd Row Col
431 --
432 | TRecordField Row Col
433 | TRecordColon Row Col
434 | TRecordType Type Row Col
435 --
436 | TRecordSpace Space Row Col
437 --
438 | TRecordIndentOpen Row Col
439 | TRecordIndentField Row Col
440 | TRecordIndentColon Row Col
441 | TRecordIndentType Row Col
442 | TRecordIndentEnd Row Col
445data TTuple
446 = TTupleOpen Row Col
447 | TTupleEnd Row Col
448 | TTupleType Type Row Col
449 | TTupleSpace Space Row Col
450 --
451 | TTupleIndentType1 Row Col
452 | TTupleIndentTypeN Row Col
453 | TTupleIndentEnd Row Col
457-- LITERALS
460data Char
461 = CharEndless
462 | CharEscape Escape
463 | CharNotString Word16
466data String
467 = StringEndless_Single
468 | StringEndless_Multi
469 | StringEscape Escape
472data Escape
473 = EscapeUnknown
474 | BadUnicodeFormat Word16
475 | BadUnicodeCode Word16
476 | BadUnicodeLength Word16 Int Int
479data Number
480 = NumberEnd
481 | NumberDot Int
482 | NumberHexDigit
483 | NumberNoLeadingZero
487-- MISC
490data Space
491 = HasTab
492 | EndlessMultiComment
496-- TO REPORT
499toReport :: Code.Source -> Error -> Report.Report
500toReport source err =
501 case err of
502 ModuleNameUnspecified name ->
503 let
504 region = toRegion 1 1
505 in
506 Report.Report "MODULE NAME MISSING" region [] $
507 D.stack
508 [ D.reflow $
509 "I need the module name to be declared at the top of this file, like this:"
510 , D.indent 4 $ D.fillSep $
511 [ D.cyan "module", D.fromName name, D.cyan "exposing", "(..)" ]
512 , D.reflow $
513 "Try adding that as the first line of your file!"
514 , D.toSimpleNote $
515 "It is best to replace (..) with an explicit list of types and\
516 \ functions you want to expose. When you know a value is only used\
517 \ within this module, you can refactor without worrying about uses\
518 \ elsewhere. Limiting exposed values can also speed up compilation\
519 \ because I can skip a bunch of work if I see that the exposed API\
520 \ has not changed."
521 ]
523 ModuleNameMismatch expectedName (A.At region actualName) ->
524 Report.Report "MODULE NAME MISMATCH" region [ModuleName.toChars expectedName] $
525 Code.toSnippet source region Nothing
526 (
527 "It looks like this module name is out of sync:"
528 ,
529 D.stack
530 [ D.reflow $
531 "I need it to match the file path, so I was expecting it to see `"
532 ++ ModuleName.toChars expectedName
533 ++ "` here. Make the following change, and you should be all set!"
534 , D.indent 4 $
535 D.dullyellow (D.fromName actualName) <> " -> " <> D.green (D.fromName expectedName)
536 , D.toSimpleNote $
537 "I require that module names correspond to file paths. This makes it much\
538 \ easier to explore unfamiliar codebases! So if you want to keep the current\
539 \ module name, try renaming the file instead."
540 ]
541 )
543 UnexpectedPort region ->
544 Report.Report "UNEXPECTED PORTS" region [] $
545 Code.toSnippet source region Nothing
546 (
547 D.reflow $
548 "You are declaring ports in a normal module."
549 ,
550 D.stack
551 [ D.fillSep
552 ["Switch","this","to","say",D.cyan "port module","instead,"
553 ,"marking","that","this","module","contains","port","declarations."
554 ]
555 , D.link "Note"
556 "Ports are not a traditional FFI for calling JS functions directly. They need a different mindset! Read"
557 "ports"
558 "to learn the syntax and how to use it effectively."
559 ]
560 )
562 NoPorts region ->
563 Report.Report "NO PORTS" region [] $
564 Code.toSnippet source region Nothing
565 (
566 D.reflow $
567 "This module does not declare any ports, but it says it will:"
568 ,
569 D.fillSep
570 ["Switch","this","to",D.cyan "module"
571 ,"and","you","should","be","all","set!"
572 ]
573 )
575 ParseError modul ->
576 toParseErrorReport source modul
579toParseErrorReport :: Code.Source -> Module -> Report.Report
580toParseErrorReport source modul =
581 case modul of
582 ModuleSpace space row col ->
583 toSpaceReport source space row col
585 ModuleEndOfFile row col ->
586 let
587 region = toRegion row col
588 in
589 Report.Report "EXPECTING END OF FILE" region [] $
590 Code.toSnippet source region Nothing
591 (
592 D.reflow $
593 "I was not expecting to see anything more here:"
594 ,
595 D.reflow $
596 "I think I have read all the declarations in the file and that there is nothing\
597 \ left to see, so whatever I am running into is confusing me a lot!"
598 )
600 ModuleProblem row col ->
601 let
602 region = toRegion row col
603 in
604 Report.Report "UNFINISHED MODULE DECLARATION" region [] $
605 Code.toSnippet source region Nothing
606 (
607 D.reflow $
608 "I am parsing an `module` declaration, but I got stuck here:"
609 ,
610 D.stack
611 [ D.reflow $
612 "Here are some examples of valid `module` declarations:"
613 , D.indent 4 $ D.vcat $
614 [ D.fillSep [D.cyan "module","Main",D.cyan "exposing","(..)"]
615 , D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(Dict, empty, get)"]
616 ]
617 , D.reflow $
618 "I generally recommend using an explicit exposing list. I can skip compiling a bunch\
619 \ of files when the public interface of a module stays the same, so exposing fewer\
620 \ values can help improve compile times!"
621 ]
622 )
624 ModuleName row col ->
625 let
626 region = toRegion row col
627 in
628 Report.Report "EXPECTING MODULE NAME" region [] $
629 Code.toSnippet source region Nothing
630 (
631 D.reflow $
632 "I was parsing an `module` declaration until I got stuck here:"
633 ,
634 D.stack
635 [ D.reflow $
636 "I was expecting to see the module name next, like in these examples:"
637 , D.indent 4 $ D.vcat $
638 [ D.fillSep [D.cyan "module","Dict",D.cyan "exposing","(..)"]
639 , D.fillSep [D.cyan "module","Maybe",D.cyan "exposing","(..)"]
640 , D.fillSep [D.cyan "module","Html.Attributes",D.cyan "exposing","(..)"]
641 , D.fillSep [D.cyan "module","Json.Decode",D.cyan "exposing","(..)"]
642 ]
643 , D.reflow $
644 "Notice that the module names all start with capital letters. That is required!"
645 ]
646 )
648 ModuleExposing exposing row col ->
649 error "TODO ModuleExposing" exposing row col
651 PortModuleProblem row col ->
652 let
653 region = toRegion row col
654 in
655 Report.Report "UNFINISHED PORT MODULE DECLARATION" region [] $
656 Code.toSnippet source region Nothing
657 (
658 D.reflow $
659 "I am parsing an `port module` declaration, but I got stuck here:"
660 ,
661 D.stack
662 [ D.reflow $
663 "Here are some examples of valid `port module` declarations:"
664 , D.indent 4 $ D.vcat $
665 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
666 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
667 ]
668 , D.link "Note" "Read" "ports" "for more help."
669 ]
670 )
672 PortModuleName row col ->
673 let
674 region = toRegion row col
675 in
676 Report.Report "EXPECTING MODULE NAME" region [] $
677 Code.toSnippet source region Nothing
678 (
679 D.reflow $
680 "I was parsing an `module` declaration until I got stuck here:"
681 ,
682 D.stack
683 [ D.reflow $
684 "I was expecting to see the module name next, like in these examples:"
685 , D.indent 4 $ D.vcat $
686 [ D.fillSep [D.cyan "port",D.cyan "module","WebSockets",D.cyan "exposing","(send, listen, keepAlive)"]
687 , D.fillSep [D.cyan "port",D.cyan "module","Maps",D.cyan "exposing","(Location, goto)"]
688 ]
689 , D.reflow $
690 "Notice that the module names start with capital letters. That is required!"
691 ]
692 )
694 PortModuleExposing exposing row col ->
695 error "TODO PortModuleExposing" exposing row col
697 Effect row col ->
698 let
699 region = toRegion row col
700 in
701 Report.Report "BAD MODULE DECLARATION" region [] $
702 Code.toSnippet source region Nothing
703 (
704 D.reflow $
705 "I cannot parse this module declaration:"
706 ,
707 D.reflow $
708 "This type of module is reserved for the @elm organization. It is used to\
709 \ define certain effects, avoiding building them into the compiler."
710 )
712 FreshLine row col ->
713 let
714 region = toRegion row col
716 toBadFirstLineReport keyword =
717 Report.Report "TOO MUCH INDENTATION" region [] $
718 Code.toSnippet source region Nothing
719 (
720 D.reflow $
721 "This `" ++ keyword ++ "` should not have any spaces before it:"
722 ,
723 D.reflow $
724 "Delete the spaces before `" ++ keyword ++ "` until there are none left!"
725 )
727 in
728 case Code.whatIsNext source row col of
729 Code.Keyword "module" -> toBadFirstLineReport "module"
730 Code.Keyword "import" -> toBadFirstLineReport "import"
731 Code.Keyword "type" -> toBadFirstLineReport "type"
732 Code.Keyword "port" -> toBadFirstLineReport "port"
733 _ ->
734 Report.Report "SYNTAX PROBLEM" region [] $
735 Code.toSnippet source region Nothing
736 (
737 D.reflow $
738 "I got stuck here:"
739 ,
740 D.stack
741 [ D.reflow $
742 "I am not sure what is going on, but I recommend starting an Elm\
743 \ file with the following lines:"
744 , D.vcat
745 [ D.fillSep [D.cyan "import","Html"]
746 , ""
747 , D.fillSep [D.green "main","="]
748 , D.indent 2 $ D.fillSep [D.cyan "Html" <> ".text",D.dullyellow "\"Hello!\""]
749 ]
750 , D.reflow $
751 "You should be able to copy those lines directly into your file. Check out\
752 \ some of the examples on https://elm-lang.org for more help getting started!"
753 , D.toSimpleNote $
754 "This can also happen when something is indented too much!"
755 ]
756 )
758 ImportStart row col ->
759 toImportReport source row col
761 ImportName row col ->
762 let
763 region = toRegion row col
764 in
765 Report.Report "EXPECTING IMPORT NAME" region [] $
766 Code.toSnippet source region Nothing
767 (
768 D.reflow $
769 "I was parsing an `import` until I got stuck here:"
770 ,
771 D.stack
772 [ D.reflow $
773 "I was expecting to see a module name next, like in these examples:"
774 , D.indent 4 $ D.vcat $
775 [ D.fillSep [D.cyan "import","Dict"]
776 , D.fillSep [D.cyan "import","Maybe"]
777 , D.fillSep [D.cyan "import","Html.Attributes"]
778 , D.fillSep [D.cyan "import","Json.Decode"]
779 ]
780 , D.reflow $
781 "Notice that the module names all start with capital letters. That is required!"
782 ]
783 )
785 ImportAs row col ->
786 toImportReport source row col
788 ImportAlias row col ->
789 let
790 region = toRegion row col
791 in
792 Report.Report "EXECTING IMPORT ALIAS" region [] $
793 Code.toSnippet source region Nothing
794 (
795 D.reflow $
796 "I was parsing an `import` until I got stuck here:"
797 ,
798 D.stack
799 [ D.reflow $
800 "I was expecting to see an alias next, like in these examples:"
801 , D.indent 4 $ D.vcat $
802 [ D.fillSep [D.cyan "import","Html.Attributes",D.cyan "as","Attr"]
803 , D.fillSep [D.cyan "import","WebGL.Texture",D.cyan "as","Texture"]
804 , D.fillSep [D.cyan "import","Json.Decode",D.cyan "as","D"]
805 ]
806 , D.reflow $
807 "Notice that the alias always starts with a capital letter. That is required!"
808 ]
809 )
811 ImportExposing row col ->
812 toImportReport source row col
814 ImportExposingList exposing row col ->
815 error "TODO ImportExposingList" exposing row col
817 ImportEnd row col ->
818 toImportReport source row col
820 ImportIndentName row col ->
821 toImportReport source row col
823 ImportIndentAlias row col ->
824 toImportReport source row col
826 ImportIndentExposingList row col ->
827 let
828 region = toRegion row col
829 in
830 Report.Report "UNFINISHED IMPORT" region [] $
831 Code.toSnippet source region Nothing
832 (
833 D.reflow $
834 "I was parsing an `import` until I got stuck here:"
835 ,
836 D.stack
837 [ D.reflow $
838 "I was expecting to see the list of exposed values next. For example, here\
839 \ are two ways to expose values from the `Html` module:"
840 , D.indent 4 $ D.vcat $
841 [ D.fillSep [D.cyan "import","Html",D.cyan "exposing","(..)"]
842 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
843 ]
844 , D.reflow $
845 "I generally recommend the second style. It is more explicit, making it\
846 \ much easier to figure out where values are coming from in large projects!"
847 ]
848 )
850 Infix row col ->
851 let
852 region = toRegion row col
853 in
854 Report.Report "BAD INFIX" region [] $
855 Code.toSnippet source region Nothing
856 (
857 D.reflow $
858 "Something went wrong in this infix operator declaration:"
859 ,
860 D.reflow $
861 "This feature is used by the @elm organization to define the\
862 \ languages built-in operators."
863 )
865 Declarations decl _ _ ->
866 toDeclarationsReport source decl
870-- IMPORTS
873toImportReport :: Code.Source -> Row -> Col -> Report.Report
874toImportReport source row col =
875 let
876 region = toRegion row col
877 in
878 Report.Report "UNFINISHED IMPORT" region [] $
879 Code.toSnippet source region Nothing
880 (
881 D.reflow $
882 "I am partway through parsing an import, but I got stuck here:"
883 ,
884 D.stack
885 [ D.reflow $
886 "Here are some examples of valid `import` declarations:"
887 , D.indent 4 $ D.vcat $
888 [ D.fillSep [D.cyan "import","Html"]
889 , D.fillSep [D.cyan "import","Html",D.cyan "as","H"]
890 , D.fillSep [D.cyan "import","Html",D.cyan "as","H",D.cyan "exposing","(..)"]
891 , D.fillSep [D.cyan "import","Html",D.cyan "exposing","(Html, div, text)"]
892 ]
893 , D.reflow $
894 "You are probably trying to import a different module, but try to make it look like one of these examples!"
895 ]
896 )
900-- SPACES
903toSpaceReport :: Code.Source -> Space -> Row -> Col -> Report.Report
904toSpaceReport source space row col =
905 case space of
906 HasTab ->
907 let
908 region = toRegion row col
909 in
910 Report.Report "NO TABS" region [] $
911 Code.toSnippet source region Nothing
912 (
913 D.reflow $
914 "I ran into a tab, but tabs are not allowed in Elm files."
915 ,
916 D.reflow $
917 "Replace the tab with spaces."
918 )
920 EndlessMultiComment ->
921 let
922 region = toWiderRegion row col 2
923 in
924 Report.Report "ENDLESS COMMENT" region [] $
925 Code.toSnippet source region Nothing
926 (
927 D.reflow $
928 "I cannot find the end of this multi-line comment:"
929 ,
930 D.stack -- "{-"
931 [ D.reflow "Add a -} somewhere after this to end the comment."
932 , D.toSimpleHint
933 "Multi-line comments can be nested in Elm, so {- {- -} -} is a comment\
934 \ that happens to contain another comment. Like parentheses and curly braces,\
935 \ the start and end markers must always be balanced. Maybe that is the problem?"
936 ]
937 )
941-- DECLARATIONS
944toRegion :: Row -> Col -> A.Region
945toRegion row col =
946 let
947 pos = A.Position row col
948 in
949 A.Region pos pos
952toWiderRegion :: Row -> Col -> Word16 -> A.Region
953toWiderRegion row col extra =
954 A.Region
955 (A.Position row col)
956 (A.Position row (col + extra))
959toKeywordRegion :: Row -> Col -> [Char.Char] -> A.Region
960toKeywordRegion row col keyword =
961 A.Region
962 (A.Position row col)
963 (A.Position row (col + fromIntegral (length keyword)))
966toDeclarationsReport :: Code.Source -> Decl -> Report.Report
967toDeclarationsReport source decl =
968 case decl of
969 DeclStart row col ->
970 error "TODO DeclStart" row col
972 DeclSpace space row col ->
973 toSpaceReport source space row col
975 Port port_ row col ->
976 error "TODO Port" port_ row col
978 DeclType declType row col ->
979 toDeclTypeReport source declType row col
981 DeclDef name declDef row col ->
982 toDeclDefReport source name declDef row col
984 DeclFreshLineStart row col ->
985 error "TODO DeclFreshLineStart" row col
987 DeclFreshLineAfterDocComment row col ->
988 error "TODO DeclFreshLineAfterDocComment" row col
992-- DECL TYPE
995toDeclTypeReport :: Code.Source -> DeclType -> Row -> Col -> Report.Report
996toDeclTypeReport source declType startRow startCol =
997 case declType of
998 DT_Space space row col ->
999 toSpaceReport source space row col
1001 DT_Name row col ->
1002 let
1003 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1004 region = toRegion row col
1005 in
1006 Report.Report "EXPECTING TYPE NAME" region [] $
1007 Code.toSnippet source surroundings (Just region)
1009 D.reflow $
1010 "I think I am parsing a type declaration, but I got stuck here:"
1012 D.stack
1013 [ D.fillSep $
1014 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1015 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1017 , customTypeNote
1021 DT_Alias typeAlias row col ->
1022 toTypeAliasReport source typeAlias row col
1024 DT_Union customType row col ->
1025 toCustomTypeReport source customType row col
1027 DT_IndentName row col ->
1028 let
1029 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1030 region = toRegion row col
1031 in
1032 Report.Report "EXPECTING TYPE NAME" region [] $
1033 Code.toSnippet source surroundings (Just region)
1035 D.reflow $
1036 "I think I am parsing a type declaration, but I got stuck here:"
1038 D.stack
1039 [ D.fillSep $
1040 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1041 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1043 , customTypeNote
1048toTypeAliasReport :: Code.Source -> TypeAlias -> Row -> Col -> Report.Report
1049toTypeAliasReport source typeAlias startRow startCol =
1050 case typeAlias of
1051 AliasSpace space row col ->
1052 toSpaceReport source space row col
1054 AliasName row col ->
1055 let
1056 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1057 region = toRegion row col
1058 in
1059 Report.Report "EXPECTING TYPE ALIAS NAME" region [] $
1060 Code.toSnippet source surroundings (Just region)
1062 D.reflow $
1063 "I think I am parsing a type alias, but I got stuck here:"
1065 D.stack
1066 [ D.fillSep $
1067 ["I","was","expecting","a","name","like",D.dullyellow "Person","or",D.dullyellow "Point"
1068 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1070 , typeAliasNote
1074 AliasEquals row col ->
1075 error "TODO AliasEquals" row col
1077 AliasBody tipe row col ->
1078 toTypeReport source tipe row col
1080 AliasIndentEquals row col ->
1081 error "TODO AliasIndentEquals" row col
1083 AliasIndentBody row col ->
1084 let
1085 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1086 region = toRegion row col
1087 in
1088 Report.Report "UNFINISHED TYPE ALIAS" region [] $
1089 Code.toSnippet source surroundings (Just region)
1091 D.reflow $
1092 "I am partway through parsing a type alias, but I got stuck here:"
1094 D.stack
1095 [ D.fillSep $
1096 ["I","was","expecting","to","see","a","type","next.","Something","as","simple"
1097 ,"as",D.dullyellow "Int","or",D.dullyellow "Float","would","work!"
1099 , typeAliasNote
1104typeAliasNote :: D.Doc
1105typeAliasNote =
1106 D.stack
1107 [ D.toSimpleNote $
1108 "Here is an example of a valid `type alias` for reference:"
1109 , D.vcat $
1110 [ D.indent 0 $ D.fillSep [D.cyan "type",D.cyan "alias",D.green "Person","="]
1111 , D.indent 2 $ D.vcat $
1112 ["{ name : String"
1113 ,", age : Int"
1114 ,", height : Float"
1115 ,"}"
1118 , D.reflow $
1119 "This would let us use `Person` as a shorthand for that record type. Using this\
1120 \ shorthand makes type annotations much easier to read, and makes changing code\
1121 \ easier if you decide later that there is more to a person than age and height!"
1125toCustomTypeReport :: Code.Source -> CustomType -> Row -> Col -> Report.Report
1126toCustomTypeReport source customType startRow startCol =
1127 case customType of
1128 CT_Space space row col ->
1129 toSpaceReport source space row col
1131 CT_Name row col ->
1132 let
1133 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1134 region = toRegion row col
1135 in
1136 Report.Report "EXPECTING TYPE NAME" region [] $
1137 Code.toSnippet source surroundings (Just region)
1139 D.reflow $
1140 "I think I am parsing a type declaration, but I got stuck here:"
1142 D.stack
1143 [ D.fillSep $
1144 ["I","was","expecting","a","name","like",D.dullyellow "Status","or",D.dullyellow "Style"
1145 ,"next.","Just","make","sure","it","is","a","name","that","starts","with","a","capital","letter!"
1147 , customTypeNote
1151 CT_Equals row col ->
1152 error "TODO CT_Equals" row col
1154 CT_Bar row col ->
1155 error "TODO CT_Bar" row col
1157 CT_Variant row col ->
1158 error "TODO CT_Variant" row col
1160 CT_VariantArg tipe row col ->
1161 toTypeReport source tipe row col
1163 CT_IndentEquals row col ->
1164 error "TODO CT_IndentEquals" row col
1166 CT_IndentBar row col ->
1167 error "TODO CT_IndentBar" row col
1169 CT_IndentAfterBar row col ->
1170 error "TODO CT_IndentAfterBar" row col
1172 CT_IndentAfterEquals row col ->
1173 error "TODO CT_IndentAfterEquals" row col
1176customTypeNote :: D.Doc
1177customTypeNote =
1178 D.stack
1179 [ D.toSimpleNote $
1180 "Here is an example of a valid `type` declaration for reference:"
1181 , D.vcat $
1182 [ D.indent 0 $ D.fillSep [D.cyan "type",D.green "Status"]
1183 , D.indent 2 $ D.fillSep ["=","Failure"]
1184 , D.indent 2 $ D.fillSep ["|","Waiting"]
1185 , D.indent 2 $ D.fillSep ["|","Success","String"]
1187 , D.reflow $
1188 "This defines a new `Status` type with three variants. This could be useful if\
1189 \ we are waiting for an HTTP request. Maybe we start with `Waiting` and then\
1190 \ switch to `Failure` or `Success \"message from server\"` depending on how\
1191 \ things go. Notice that the Success variant has some associated data, allowing\
1192 \ us to store a String if the request goes well!"
1197-- DECL DEF
1200toDeclDefReport :: Code.Source -> Name.Name -> DeclDef -> Row -> Col -> Report.Report
1201toDeclDefReport source name declDef startRow startCol =
1202 case declDef of
1203 DeclDefSpace space row col ->
1204 toSpaceReport source space row col
1206 DeclDefEquals row col ->
1207 case Code.whatIsNext source row col of
1208 Code.Keyword keyword ->
1209 let
1210 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1211 region = toKeywordRegion row col keyword
1212 in
1213 Report.Report "RESERVED WORD" region [] $
1214 Code.toSnippet source surroundings (Just region)
1216 D.reflow $
1217 "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
1219 D.reflow $
1220 "This is a reserved word! Try using some other name?"
1223 Code.Operator op ->
1224 let
1225 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1226 region = toKeywordRegion row col op
1227 in
1228 Report.Report "UNEXPECTED SYMBOL" region [] $
1229 Code.toSnippet source surroundings (Just region)
1231 D.reflow $
1232 "I was not expecting to see this symbol here:"
1234 D.stack
1235 [ D.reflow $
1236 "I am not sure what is going wrong exactly, so here is a valid\
1237 \ definition (with an optional type annotation) for reference:"
1238 , D.vcat
1239 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1240 , D.fillSep [D.green "add","x","y","="]
1241 , D.fillSep [" ","x","+","y"]
1243 , D.reflow $
1244 "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
1248 _ ->
1249 let
1250 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1251 region = toRegion row col
1252 in
1253 Report.Report "PROBLEM IN DEFINITION" region [] $
1254 Code.toSnippet source surroundings (Just region)
1256 D.reflow $
1257 "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
1259 D.stack
1260 [ D.reflow $
1261 "I am not sure what is going wrong exactly, so here is a valid\
1262 \ definition (with an optional type annotation) for reference:"
1263 , D.vcat
1264 [ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
1265 , D.fillSep [D.green "add","x","y","="]
1266 , D.fillSep [" ","x","+","y"]
1268 , D.reflow $
1269 "Try to use that format!"
1273 DeclDefType tipe row col ->
1274 toTypeReport source tipe row col
1276 DeclDefArg pattern row col ->
1277 toPatternReport source PArg pattern row col
1279 DeclDefBody expr row col ->
1280 toExprReport source (InDef name startRow startCol) expr row col
1282 DeclDefNameRepeat row col ->
1283 let
1284 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1285 region = toRegion row col
1286 in
1287 Report.Report "EXPECTING DEFINITION" region [] $
1288 Code.toSnippet source surroundings (Just region)
1290 D.reflow $
1291 "I just saw the type annotation for `" ++ Name.toChars name
1292 ++ "` so I was expecting to see its definition here:"
1294 D.reflow $
1295 "Type annotations always appear directly above the relevant\
1296 \ definition, without anything else (even doc comments) in between."
1299 DeclDefNameMatch defName row col ->
1300 let
1301 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1302 region = toRegion row col
1303 in
1304 Report.Report "NAME MISMATCH" region [] $
1305 Code.toSnippet source surroundings (Just region)
1307 D.reflow $
1308 "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
1310 D.stack
1311 [ D.reflow $
1312 "These names do not match! Is there a typo?"
1313 , D.indent 4 $ D.fillSep $
1314 [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
1318 DeclDefIndentType row col ->
1319 error "TODO DeclDefIndentType" row col
1321 DeclDefIndentEquals row col ->
1322 error "TODO DeclDefIndentEquals" row col
1324 DeclDefIndentBody row col ->
1325 error "TODO DeclDefIndentBody" row col
1327 DeclDefFreshLineAfterType row col ->
1328 error "TODO DeclDefFreshLineAfterType" row col
1332-- CONTEXT
1335data Context
1336 = InNode Node Row Col Context
1337 | InDef Name.Name Row Col
1340data Node
1341 = NRecord
1342 | NParens
1343 | NList
1344 | NFunc
1345 | NCond
1346 | NThen
1347 | NElse
1348 | NCase
1349 | NBranch
1350 deriving (Eq)
1353getDefName :: Context -> Name.Name
1354getDefName context =
1355 case context of
1356 InDef name _ _ -> name
1357 InNode _ _ _ c -> getDefName c
1360isWithin :: Node -> Context -> Bool
1361isWithin desiredNode context =
1362 case context of
1363 InDef _ _ _ -> False
1364 InNode actualNode _ _ _ -> desiredNode == actualNode
1368-- EXPR REPORTS
1371toExprReport :: Code.Source -> Context -> Expr -> Row -> Col -> Report.Report
1372toExprReport source context expr startRow startCol =
1373 case expr of
1374 Let let_ row col ->
1375 toLetReport source context let_ row col
1377 Case case_ row col ->
1378 toCaseReport source context case_ row col
1380 If if_ row col ->
1381 toIfReport source context if_ row col
1383 List list row col ->
1384 toListReport source context list row col
1386 Record record row col ->
1387 toRecordReport source context record row col
1389 Tuple tuple row col ->
1390 toTupleReport source context tuple row col
1392 Func func row col ->
1393 toFuncReport source context func row col
1395 Dot row col ->
1396 let region = toRegion row col in
1397 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1398 Code.toSnippet source region Nothing
1400 D.reflow $
1401 "I was expecting to see a record accessor here:"
1403 D.fillSep
1404 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1405 ,"that","accesses","a","value","from","a","record."
1409 Access row col ->
1410 let region = toRegion row col in
1411 Report.Report "EXPECTING RECORD ACCESSOR" region [] $
1412 Code.toSnippet source region Nothing
1414 D.reflow $
1415 "I am trying to parse a record accessor here:"
1417 D.stack
1419 D.fillSep
1420 ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
1421 ,"that","accesses","a","value","from","a","record."
1424 D.toSimpleNote $
1425 "Record field names must start with a lower case letter!"
1429 OperatorRight op row col ->
1430 let region = toRegion row col in
1431 Report.Report "MISSING EXPRESSION" region [] $
1432 Code.toSnippet source region Nothing
1434 D.reflow $
1435 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1437 D.stack
1438 [ D.fillSep $
1439 ["You","can","just","put","anything","for","now,","like"
1440 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1441 ,"Once","there","is","something","there,","I","can","probably"
1442 ,"give","a","more","specific","hint!"
1444 , D.toSimpleNote $
1445 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1446 \ Or if I run into operators in unexpected spots. Point is, there are a\
1447 \ couple ways I can get confused and give sort of weird advice!"
1451 OperatorReserved operator row col ->
1452 toOperatorReport source context operator row col
1454 Start row col ->
1455 let
1456 (contextRow, contextCol, aThing) =
1457 case context of
1458 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
1459 InNode NRecord r c _ -> (r, c, "a record")
1460 InNode NParens r c _ -> (r, c, "some parentheses")
1461 InNode NList r c _ -> (r, c, "a list")
1462 InNode NFunc r c _ -> (r, c, "an anonymous function")
1463 InNode NCond r c _ -> (r, c, "an `if` expression")
1464 InNode NThen r c _ -> (r, c, "an `if` expression")
1465 InNode NElse r c _ -> (r, c, "an `if` expression")
1466 InNode NCase r c _ -> (r, c, "a `case` expression")
1467 InNode NBranch r c _ -> (r, c, "a `case` expression")
1468 -- TODO check if this is actually the best way to get error messages here
1470 surroundings = A.Region (A.Position contextRow contextCol) (A.Position row col)
1471 region = toRegion row col
1472 in
1473 Report.Report "MISSING EXPRESSION" region [] $
1474 Code.toSnippet source surroundings (Just region)
1476 D.reflow $
1477 "I am partway through parsing " ++ aThing ++ ", but I got stuck here:"
1479 D.stack
1480 [ D.fillSep $
1481 ["I","was","expecting","to","see","an","expression","like"
1482 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1483 ,"Once","there","is","something","there,","I","can","probably"
1484 ,"give","a","more","specific","hint!"
1486 , D.toSimpleNote $
1487 "This can also happen if run into reserved words like `let` or `as` unexpectedly.\
1488 \ Or if I run into operators in unexpected spots. Point is, there are a\
1489 \ couple ways I can get confused and give sort of weird advice!"
1493 Char char row col ->
1494 toCharReport source char row col
1496 String string row col ->
1497 toStringReport source string row col
1499 Number number row col ->
1500 toNumberReport source number row col
1502 Space space row col ->
1503 toSpaceReport source space row col
1505 EndlessShader row col ->
1506 let
1507 region = toWiderRegion row col 6
1508 in
1509 Report.Report "ENDLESS SHADER" region [] $
1510 Code.toSnippet source region Nothing
1512 D.reflow "I cannot find the end of this shader:"
1514 D.reflow "Add a |] somewhere after this to end the shader."
1517 ShaderProblem problem row col ->
1518 let
1519 region = toRegion row col
1520 in
1521 Report.Report "SHADER PROBLEM" region [] $
1522 Code.toSnippet source region Nothing
1524 D.reflow $
1525 "I ran into a problem while parsing this GLSL block."
1527 D.stack
1528 [ D.reflow $
1529 "I use a 3rd party GLSL parser for now, and I did my best to extract their error message:"
1530 , D.indent 4 $ D.vcat $
1531 map D.fromChars (filter (/="") (lines problem))
1535 IndentOperatorRight op row col ->
1536 let
1537 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1538 region = toRegion row col
1539 in
1540 Report.Report "MISSING EXPRESSION" region [] $
1541 Code.toSnippet source surroundings (Just region)
1543 D.reflow $
1544 "I was expecting to see an expression after this " ++ Name.toChars op ++ " operator:"
1546 D.stack
1548 D.fillSep $
1549 ["You","can","just","put","anything","for","now,","like"
1550 ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
1551 ,"Once","there","is","something","there,","I","can","probably"
1552 ,"give","a","more","specific","hint!"
1555 D.toSimpleNote $
1556 "I may be getting confused by your indentation? The easiest way to make sure\
1557 \ this is not an indentation problem is to put the expression on the right of\
1558 \ the " ++ Name.toChars op ++ " operator on the same line."
1562 IndentMoreExpr _ _ ->
1563 error "TODO IndentMoreExpr"
1567-- CHAR
1570toCharReport :: Code.Source -> Char -> Row -> Col -> Report.Report
1571toCharReport source char row col =
1572 case char of
1573 CharEndless ->
1574 let
1575 region = toRegion row col
1576 in
1577 Report.Report "MISSING SINGLE QUOTE" region [] $
1578 Code.toSnippet source region Nothing
1580 D.reflow $
1581 "I thought I was parsing a character, but I got to the end of\
1582 \ the line without seeing the closing single quote:"
1584 D.reflow $
1585 "Add a closing single quote here!"
1588 CharEscape escape ->
1589 toEscapeReport source escape row col
1591 CharNotString width ->
1592 let
1593 region = toWiderRegion row col width
1594 in
1595 Report.Report "NEEDS DOUBLE QUOTES" region [] $
1596 Code.toSnippet source region Nothing
1598 "The following string uses single quotes:"
1600 D.stack
1601 [ "Please switch to double quotes instead:"
1602 , D.indent 4 $
1603 D.dullyellow "'this'" <> " => " <> D.green "\"this\""
1604 , D.toSimpleNote $
1605 "Elm uses double quotes for strings like \"hello\", whereas it uses single\
1606 \ quotes for individual characters like 'a' and 'ø'. This distinction helps with\
1607 \ code like (String.any (\\c -> c == 'X') \"90210\") where you are inspecting\
1608 \ individual characters."
1614-- STRING
1617toStringReport :: Code.Source -> String -> Row -> Col -> Report.Report
1618toStringReport source string row col =
1619 case string of
1620 StringEndless_Single ->
1621 let
1622 region = toRegion row col
1623 in
1624 Report.Report "ENDLESS STRING" region [] $
1625 Code.toSnippet source region Nothing
1627 D.reflow $
1628 "I got to the end of the line without seeing the closing double quote:"
1630 D.stack
1631 [ D.fillSep $
1632 ["Strings","look","like",D.green "\"this\"","with","double"
1633 ,"quotes","on","each","end.","Is","the","closing","double"
1634 ,"quote","missing","in","your","code?"
1636 , D.link "Note" "Read" "TODO" "if you want a string that spans multiple lines."
1640 StringEndless_Multi ->
1641 let
1642 region = toWiderRegion row col 3
1643 in
1644 Report.Report "ENDLESS STRING" region [] $
1645 Code.toSnippet source region Nothing
1647 D.reflow $
1648 "I cannot find the end of this multi-line string:"
1650 D.stack
1651 [ D.reflow "Add a \"\"\" somewhere after this to end the string."
1652 , D.link "Hint" "Read" "TODO" "for more information on strings and multi-line strings."
1656 StringEscape escape ->
1657 toEscapeReport source escape row col
1661-- ESCAPES
1664toEscapeReport :: Code.Source -> Escape -> Row -> Col -> Report.Report
1665toEscapeReport source escape row col =
1666 case escape of
1667 EscapeUnknown ->
1668 let
1669 region = toWiderRegion row col 2
1670 in
1671 Report.Report "UNKNOWN ESCAPE" region [] $
1672 Code.toSnippet source region Nothing
1674 D.reflow $
1675 "Backslashes always start escaped characters, but I do not recognize this one:"
1677 D.stack
1678 [ D.reflow $
1679 "Valid escape characters include:"
1680 , D.dullyellow $ D.indent 4 $ D.vcat $
1681 [ "\\n"
1682 , "\\r"
1683 , "\\t"
1684 , "\\\""
1685 , "\\\'"
1686 , "\\\\"
1687 , "\\u{003D}"
1689 , D.reflow $
1690 "Do you want one of those instead? Maybe you need \\\\ to escape a backslash?"
1691 , D.toSimpleNote $
1692 "The last style lets encode ANY character by its Unicode code\
1693 \ point. That means \\u{0009} and \\t are the same. You can use\
1694 \ that style for anything not covered by the other six escapes!"
1698 BadUnicodeFormat width ->
1699 let
1700 region = toWiderRegion row col width
1701 in
1702 Report.Report "BAD UNICODE ESCAPE" region [] $
1703 Code.toSnippet source region Nothing
1705 D.reflow $
1706 "I ran into an invalid Unicode escape:"
1708 D.stack
1709 [ D.reflow $
1710 "Here are some examples of valid Unicode escapes:"
1711 , D.dullyellow $ D.indent 4 $ D.vcat $
1712 [ "\\u{0041}"
1713 , "\\u{03BB}"
1714 , "\\u{6728}"
1715 , "\\u{1F60A}"
1717 , D.reflow $
1718 "Notice that the code point is always surrounded by curly braces.\
1719 \ Maybe you are missing the opening or closing curly brace?"
1722 BadUnicodeCode width ->
1723 let
1724 region = toWiderRegion row col width
1725 in
1726 Report.Report "BAD UNICODE ESCAPE" region [] $
1727 Code.toSnippet source region Nothing
1729 D.reflow $
1730 "This is not a valid code point:"
1732 D.reflow $
1733 "The valid code points are between 0 and 10FFFF inclusive."
1736 BadUnicodeLength width numDigits badCode ->
1737 let
1738 region = toWiderRegion row col width
1739 in
1740 Report.Report "BAD UNICODE ESCAPE" region [] $
1741 Code.toSnippet source region Nothing $
1742 if numDigits < 4 then
1744 D.reflow $
1745 "Every code point needs at least four digits:"
1747 let
1748 goodCode = replicate (4 - numDigits) '0' ++ map Char.toUpper (showHex badCode "")
1749 suggestion = "\\u{" <> D.fromChars goodCode <> "}"
1750 in
1751 D.fillSep ["Try",D.green suggestion,"instead?"]
1754 else
1756 D.reflow $
1757 "This code point has too many digits:"
1759 D.fillSep $
1760 ["Valid","code","points","are","between"
1761 ,D.green "\\u{0000}","and",D.green "\\u{10FFFF}" <> ","
1762 ,"so","try","trimming","any","leading","zeros","until"
1763 ,"you","have","between","four","and","six","digits."
1769-- NUMBERS
1772toNumberReport :: Code.Source -> Number -> Row -> Col -> Report.Report
1773toNumberReport source number row col =
1774 let
1775 region = toRegion row col
1776 in
1777 case number of
1778 NumberEnd ->
1779 Report.Report "WEIRD NUMBER" region [] $
1780 Code.toSnippet source region Nothing
1782 D.reflow $
1783 "I thought I was reading a number, but I ran into some weird stuff here:"
1785 D.stack
1786 [ D.reflow $
1787 "I recognize numbers in the following formats:"
1788 , D.indent 4 $ D.vcat [ "42", "3.14", "6.022e23", "0x002B" ]
1789 , D.reflow $
1790 "So is there a way to write it like one of those?"
1794 NumberDot int ->
1795 Report.Report "WEIRD NUMBER" region [] $
1796 Code.toSnippet source region Nothing
1798 D.reflow $
1799 "Numbers cannot end with a dot like this:"
1801 D.fillSep
1802 ["Switching","to",D.green (D.fromChars (show int))
1803 ,"or",D.green (D.fromChars (show int ++ ".0"))
1804 ,"will","work","though!"
1808 NumberHexDigit ->
1809 Report.Report "WEIRD HEXIDECIMAL" region [] $
1810 Code.toSnippet source region Nothing
1812 D.reflow $
1813 "I thought I was reading a hexidecimal number until I got here:"
1815 D.stack
1816 [ D.reflow $
1817 "Valid hexidecimal digits include 0123456789abcdefABCDEF, so I can\
1818 \ only recognize things like this:"
1819 , D.indent 4 $ D.vcat [ "0x2B", "0x002B", "0x00ffb3" ]
1823 NumberNoLeadingZero ->
1824 Report.Report "LEADING ZEROS" region [] $
1825 Code.toSnippet source region Nothing
1827 D.reflow $
1828 "I do not accept numbers with leading zeros:"
1830 D.stack
1831 [ D.reflow $
1832 "Just delete the leading zeros and it should work!"
1833 , D.toSimpleNote $
1834 "Some languages let you to specify octal numbers by adding a leading zero.\
1835 \ So in C, writing 0111 is the same as writing 73. Some people are used to\
1836 \ that, but others probably want it to equal 111. Either path is going to\
1837 \ surprise people from certain backgrounds, so Elm tries to avoid this whole\
1838 \ situation."
1844-- OPERATORS
1847toOperatorReport :: Code.Source -> Context -> BadOperator -> Row -> Col -> Report.Report
1848toOperatorReport source context operator row col =
1849 case operator of
1850 BadDot ->
1851 let
1852 region = toRegion row col
1853 in
1854 Report.Report "UNEXPECTED SYMBOL" region [] $
1855 Code.toSnippet source region Nothing
1857 "I was not expecting this dot:"
1859 D.reflow $
1860 "Dots are for record access and decimal points, so\
1861 \ they cannot float around on their own. Maybe\
1862 \ there is some extra whitespace?"
1865 BadPipe ->
1866 let
1867 region = toRegion row col
1868 in
1869 Report.Report "UNEXPECTED SYMBOL" region [] $
1870 Code.toSnippet source region Nothing
1872 D.reflow $
1873 "I was not expecting this vertical bar:"
1875 D.reflow $
1876 "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1879 BadArrow ->
1880 let
1881 region = toWiderRegion row col 2
1882 in
1883 Report.Report "UNEXPECTED ARROW" region [] $
1884 Code.toSnippet source region Nothing $
1885 if isWithin NBranch context then
1887 D.reflow $
1888 "I was not expecting to see an arrow here:"
1890 D.stack
1892 D.reflow $
1893 "I think I am parsing a `case` expression right now, so it makes sense to\
1894 \ see arrows around here. This one is confusing me though!"
1896 D.toSimpleHint $
1897 "I may be getting confused by the indentation. Every pattern in a `case` must be\
1898 \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1899 \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1900 \ indented too far?"
1904 else
1906 D.reflow $
1907 "I was not expecting an arrow here:"
1909 D.reflow $
1910 "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1911 \ you want > or >= instead?"
1914 BadEquals ->
1915 let
1916 region = toRegion row col
1917 name = getDefName context
1918 in
1919 Report.Report "UNEXPECTED EQUALS" region [] $
1920 Code.toSnippet source region Nothing
1922 D.reflow $
1923 "I was not expecting to see this equals sign:"
1925 D.stack
1927 D.reflow "Maybe you want == instead? To check if two values are equal?"
1929 D.toSimpleNote $
1930 if isWithin NRecord context then
1931 "Records look like { x = 3, y = 4 } with the equals sign right\
1932 \ after the field name. So maybe you forgot a comma?"
1933 else
1934 "I may be getting confused by your indentation. Is this supposed to be part of\
1935 \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1936 \ the problem may be a bit before the equals sign. I need all definitions to\
1937 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1938 \ this new definition is indented a bit too much."
1942 BadHasType ->
1943 let
1944 region = toRegion row col
1945 name = getDefName context
1946 in
1947 Report.Report "UNEXPECTED SYMBOL" region [] $
1948 Code.toSnippet source region Nothing $
1950 D.reflow $
1951 "I was not expecting to run into the \"has type\" symbol here:"
1953 D.stack
1955 D.fillSep
1956 ["Maybe","you","want",D.green "::","instead?"
1957 ,"To","put","something","on","the","front","of","a","list?"
1959 , D.toSimpleNote $
1960 "The single colon is reserved for type annotations and record types, but I think\
1961 \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1963 D.toSimpleNote $
1964 "I may be getting confused by your indentation. Is this supposed to be part of\
1965 \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1966 \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1967 \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1968 \ this new definition is indented a bit too much."
1974-- CASE
1977toLetReport :: Code.Source -> Context -> Let -> Row -> Col -> Report.Report
1978toLetReport source context let_ startRow startCol =
1979 case let_ of
1980 LetSpace space row col ->
1981 toSpaceReport source space row col
1983 LetIn row col ->
1984 let
1985 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
1986 region = toRegion row col
1987 in
1988 Report.Report "LET PROBLEM" region [] $
1989 Code.toSnippet source surroundings (Just region)
1991 D.reflow $
1992 "I was partway through parsing a `let` expression, but I got stuck here:"
1994 D.stack
1995 [ D.fillSep $
1996 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
1997 ,"keyword","next.","Is","there","a","typo?"
1999 , D.toSimpleNote $
2000 "This can also happen if you are trying to define another value within the `let` but\
2001 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2002 \ spaces before it. They should line up exactly!"
2006 LetDefAlignment _ row col ->
2007 let
2008 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2009 region = toRegion row col
2010 in
2011 Report.Report "LET PROBLEM" region [] $
2012 Code.toSnippet source surroundings (Just region)
2014 D.reflow $
2015 "I was partway through parsing a `let` expression, but I got stuck here:"
2017 D.stack
2018 [ D.fillSep $
2019 ["Based","on","the","indentation,","I","was","expecting","to","see","the",D.cyan "in"
2020 ,"keyword","next.","Is","there","a","typo?"
2022 , D.toSimpleNote $
2023 "This can also happen if you are trying to define another value within the `let` but\
2024 \ it is not indented enough. Make sure each definition has exactly the same amount of\
2025 \ spaces before it. The should line up exactly!"
2029 LetDefName row col ->
2030 case Code.whatIsNext source row col of
2031 Code.Keyword keyword ->
2032 let
2033 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2034 region = toKeywordRegion row col keyword
2035 in
2036 Report.Report "RESERVED WORD" region [] $
2037 Code.toSnippet source surroundings (Just region)
2039 D.reflow $
2040 "I was partway through parsing a `let` expression, but I got stuck here:"
2042 D.reflow $
2043 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but\
2044 \ it is a reserved word! Try using a different name instead."
2047 _ ->
2048 toUnfinishLetReport source row col startRow startCol $
2049 D.reflow $
2050 "I was expecting the name of a definition next."
2052 LetDef name def row col ->
2053 error "TODO LetDef" name def row col
2055 LetDestruct destruct row col ->
2056 error "TODO LetDestruct" destruct row col
2058 LetBody expr row col ->
2059 toExprReport source context expr row col
2061 LetIndentDef row col ->
2062 toUnfinishLetReport source row col startRow startCol $
2063 D.reflow $
2064 "I was expecting a value to be defined here."
2066 LetIndentIn row col ->
2067 toUnfinishLetReport source row col startRow startCol $
2068 D.fillSep $
2069 ["I","was","expecting","to","see","the",D.cyan "in","keyword","next."
2070 ,"Or","maybe","more","of","that","expression?"
2073 LetIndentBody row col ->
2074 toUnfinishLetReport source row col startRow startCol $
2075 D.reflow $
2076 "I was expecting an expression next. Tell me what should happen with the value you just defined!"
2079toUnfinishLetReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2080toUnfinishLetReport source row col startRow startCol message =
2081 let
2082 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2083 region = toRegion row col
2084 in
2085 Report.Report "UNFINISHED LET" region [] $
2086 Code.toSnippet source surroundings (Just region)
2088 D.reflow $
2089 "I was partway through parsing a `let` expression, but I got stuck here:"
2091 D.stack
2092 [ message
2093 , D.toSimpleNote $
2094 "Here is an example with a valid `let` expression for reference:"
2095 , D.vcat $
2096 [ D.indent 0 $ D.fillSep [D.green "viewPerson","person","="]
2097 , D.indent 2 $ D.fillSep [D.cyan "let"]
2098 , D.indent 4 $ D.fillSep ["fullName","="]
2099 , D.indent 6 $ D.fillSep ["person.firstName","++",D.dullyellow "\" \"","++","person.lastName"]
2100 , D.indent 2 $ D.fillSep [D.cyan "in"]
2101 , D.indent 2 $ D.fillSep ["div","[]","[","text","fullName","]"]
2103 , D.reflow $
2104 "Here we defined a `viewPerson` function that turns a person into some HTML. We use\
2105 \ a `let` expression to define the `fullName` we want to show. Notice the indentation! The\
2106 \ `fullName` is indented more than the `let` keyword, and the actual value of `fullName` is\
2107 \ indented a bit more than that. That is important!"
2113-- CASE
2116toCaseReport :: Code.Source -> Context -> Case -> Row -> Col -> Report.Report
2117toCaseReport source context case_ startRow startCol =
2118 case case_ of
2119 CaseSpace space row col ->
2120 toSpaceReport source space row col
2122 CaseOf row col ->
2123 toUnfinishCaseReport source row col startRow startCol $
2124 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2126 CasePattern pattern row col ->
2127 toPatternReport source PCase pattern row col
2129 CaseArrow row col ->
2130 case Code.whatIsNext source row col of
2131 Code.Keyword keyword ->
2132 let
2133 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2134 region = toKeywordRegion row col keyword
2135 in
2136 Report.Report "RESERVED WORD" region [] $
2137 Code.toSnippet source surroundings (Just region)
2139 D.reflow $
2140 "I am partway through parsing a `case` expression, but I got stuck here:"
2142 D.reflow $
2143 "It looks like you are trying to use `" ++ keyword ++ "` in one of your\
2144 \ patterns, but it is a reserved word. Try using a different name?"
2147 Code.Operator ":" ->
2148 let
2149 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2150 region = toRegion row col
2151 in
2152 Report.Report "UNEXPECTED OPERATOR" region [] $
2153 Code.toSnippet source surroundings (Just region)
2155 D.reflow $
2156 "I am partway through parsing a `case` expression, but I got stuck here:"
2158 D.fillSep $
2159 ["I","am","seeing",D.dullyellow ":","but","maybe","you","want",D.green "::","instead?"
2160 ,"For","pattern","matching","on","lists?"
2164 Code.Operator "=" ->
2165 let
2166 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2167 region = toRegion row col
2168 in
2169 Report.Report "UNEXPECTED OPERATOR" region [] $
2170 Code.toSnippet source surroundings (Just region)
2172 D.reflow $
2173 "I am partway through parsing a `case` expression, but I got stuck here:"
2175 D.fillSep $
2176 ["I","am","seeing",D.dullyellow "=","but","maybe","you","want",D.green "->","instead?"
2180 _ ->
2181 let
2182 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2183 region = toRegion row col
2184 in
2185 Report.Report "MISSING ARROW" region [] $
2186 Code.toSnippet source surroundings (Just region)
2188 D.reflow $
2189 "I am partway through parsing a `case` expression, but I got stuck here:"
2191 addNoteForCaseIndentError $
2192 D.reflow $
2193 "I was expecting to see an arrow next."
2196 CaseExpr expr row col ->
2197 toExprReport source (InNode NCase startRow startCol context) expr row col
2199 CaseBranch expr row col ->
2200 toExprReport source (InNode NBranch startRow startCol context) expr row col
2202 CaseIndentOf row col ->
2203 toUnfinishCaseReport source row col startRow startCol $
2204 D.fillSep ["I","was","expecting","to","see","the",D.dullyellow "of","keyword","next."]
2206 CaseIndentExpr row col ->
2207 toUnfinishCaseReport source row col startRow startCol $
2208 D.reflow "I was expecting to see a expression next."
2210 CaseIndentPattern row col ->
2211 toUnfinishCaseReport source row col startRow startCol $
2212 D.reflow "I was expecting to see a pattern next."
2214 CaseIndentArrow row col ->
2215 toUnfinishCaseReport source row col startRow startCol $
2216 D.fillSep
2217 ["I","just","saw","a","pattern,","so","I","was","expecting"
2218 ,"to","see","a",D.dullyellow "->","next."
2221 CaseIndentBranch row col ->
2222 toUnfinishCaseReport source row col startRow startCol $
2223 D.reflow $
2224 "I was expecting to see an expression next. What should I do when\
2225 \ I run into this particular pattern?"
2227 CasePatternAlignment indent row col ->
2228 toUnfinishCaseReport source row col startRow startCol $
2229 D.reflow $
2230 "I suspect this is a pattern that is not indented far enough? (" ++ show indent ++ " spaces)"
2233toUnfinishCaseReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
2234toUnfinishCaseReport source row col startRow startCol message =
2235 let
2236 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2237 region = toRegion row col
2238 in
2239 Report.Report "UNFINISHED CASE" region [] $
2240 Code.toSnippet source surroundings (Just region)
2242 D.reflow $
2243 "I was partway through parsing a `case` expression, but I got stuck here:"
2245 D.stack
2246 [ message
2247 , D.toSimpleNote $
2248 "Here is an example of a valid `case` expression for reference."
2249 , D.vcat $
2250 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2251 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2252 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2253 , ""
2254 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2255 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2257 , D.reflow $
2258 "Notice the indentation. Each pattern is aligned, and each branch is indented\
2259 \ a bit more than the corresponding pattern. That is important!"
2264addNoteForCaseIndentError :: D.Doc -> D.Doc
2265addNoteForCaseIndentError message =
2266 D.stack $
2267 message
2269 [ D.toSimpleNote $
2270 "Sometimes I get confused by indentation, so try to make your `case` look\
2271 \ something like this:"
2272 , D.vcat $
2273 [ D.indent 4 $ D.fillSep [D.cyan "case","maybeWidth",D.cyan "of"]
2274 , D.indent 6 $ D.fillSep [D.green "Just","width","->"]
2275 , D.indent 8 $ D.fillSep ["width","+",D.dullyellow "200"]
2276 , ""
2277 , D.indent 6 $ D.fillSep [D.green "Nothing","->"]
2278 , D.indent 8 $ D.fillSep [D.dullyellow "400"]
2280 , D.reflow $
2281 "Notice the indentation! Each pattern is aligned, and each branch is indented\
2282 \ a bit more than the corresponding pattern. That is important!"
2287-- IF
2290toIfReport :: Code.Source -> Context -> If -> Row -> Col -> Report.Report
2291toIfReport source context if_ startRow startCol =
2292 case if_ of
2293 IfSpace space row col ->
2294 toSpaceReport source space row col
2296 IfThen row col ->
2297 let
2298 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2299 region = toRegion row col
2300 in
2301 Report.Report "UNFINISHED IF" region [] $
2302 Code.toSnippet source surroundings (Just region)
2304 D.reflow $
2305 "I was expecting to see more of this `if` expression, but I got stuck here:"
2307 D.fillSep $
2308 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2312 IfElse row col ->
2313 let
2314 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2315 region = toRegion row col
2316 in
2317 Report.Report "UNFINISHED IF" region [] $
2318 Code.toSnippet source surroundings (Just region)
2320 D.reflow $
2321 "I was expecting to see more of this `if` expression, but I got stuck here:"
2323 D.fillSep $
2324 ["I","was","expecting","to","see","the",D.cyan "else","keyword","next."
2328 IfElseBranchStart row col ->
2329 let
2330 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2331 region = toRegion row col
2332 in
2333 Report.Report "UNFINISHED IF" region [] $
2334 Code.toSnippet source surroundings (Just region)
2336 D.reflow $
2337 "I just saw the start of an `else` branch, but then I got stuck here:"
2339 D.reflow $
2340 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2343 IfCondition expr row col ->
2344 toExprReport source (InNode NCond startRow startCol context) expr row col
2346 IfThenBranch expr row col ->
2347 toExprReport source (InNode NThen startRow startCol context) expr row col
2349 IfElseBranch expr row col ->
2350 toExprReport source (InNode NElse startRow startCol context) expr row col
2352 IfIndentCondition row col ->
2353 let
2354 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2355 region = toRegion row col
2356 in
2357 Report.Report "UNFINISHED IF" region [] $
2358 Code.toSnippet source surroundings (Just region)
2360 D.reflow $
2361 "I was expecting to see more of this `if` expression, but I got stuck here:"
2363 D.stack
2364 [ D.fillSep $
2365 ["I","was","expecting","to","see","an","expression","like",D.dullyellow "x < 0"
2366 ,"that","evaluates","to","True","or","False."
2368 , D.toSimpleNote $
2369 "I can be confused by indentation. Maybe something is not indented enough?"
2373 IfIndentThen row col ->
2374 let
2375 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2376 region = toRegion row col
2377 in
2378 Report.Report "UNFINISHED IF" region [] $
2379 Code.toSnippet source surroundings (Just region)
2381 D.reflow $
2382 "I was expecting to see more of this `if` expression, but I got stuck here:"
2384 D.stack
2385 [ D.fillSep $
2386 ["I","was","expecting","to","see","the",D.cyan "then","keyword","next."
2388 , D.toSimpleNote $
2389 "I can be confused by indentation. Maybe something is not indented enough?"
2393 IfIndentThenBranch row col ->
2394 let
2395 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2396 region = toRegion row col
2397 in
2398 Report.Report "UNFINISHED IF" region [] $
2399 Code.toSnippet source surroundings (Just region)
2401 D.reflow $
2402 "I got stuck after the start of this `then` branch:"
2404 D.stack
2405 [ D.reflow $
2406 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2407 , D.toSimpleNote $
2408 "I can be confused by indentation, so if the `then` branch is already\
2409 \ present, it may not be indented enough for me to recognize it."
2413 IfIndentElseBranch 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 IF" region [] $
2419 Code.toSnippet source surroundings (Just region)
2421 D.reflow $
2422 "I got stuck after the start of this `else` branch:"
2424 D.stack
2425 [ D.reflow $
2426 "I was expecting to see an expression next. Maybe it is not filled in yet?"
2427 , D.toSimpleNote $
2428 "I can be confused by indentation, so if the `else` branch is already\
2429 \ present, it may not be indented enough for me to recognize it."
2433 IfIndentElse row col ->
2434 let
2435 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2436 region = toRegion row col
2437 in
2438 Report.Report "UNFINISHED IF" region [] $
2439 Code.toSnippet source surroundings (Just region)
2441 D.reflow $
2442 "I was expecting to see an `else` branch after this:"
2444 D.stack
2445 [ D.reflow $
2446 "I know what to do when the condition is `True`, but not when it is `False`."
2447 , D.fillSep
2448 ["Add","an",D.cyan "else","branch","to","handle","that","scenario!"]
2454-- RECORD
2457toRecordReport :: Code.Source -> Context -> Record -> Row -> Col -> Report.Report
2458toRecordReport source context record startRow startCol =
2459 case record of
2460 RecordOpen row col ->
2461 case Code.whatIsNext source row col of
2462 Code.Keyword keyword ->
2463 let
2464 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2465 region = toKeywordRegion row col keyword
2466 in
2467 Report.Report "RESERVED WORD" region [] $
2468 Code.toSnippet source surroundings (Just region)
2470 D.reflow $
2471 "I just started parsing a record, but I got stuck on this field name:"
2473 D.reflow $
2474 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
2475 \ that is a reserved word. Try using a different name!"
2478 _ ->
2479 let
2480 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2481 region = toRegion row col
2482 in
2483 Report.Report "UNFINISHED RECORD" region [] $
2484 Code.toSnippet source surroundings (Just region)
2486 D.reflow $
2487 "I just started parsing a record, but I got stuck here:"
2489 D.fillSep
2490 ["Records","look","like",D.dullyellow "{ x = 3, y = 4 },"
2491 ,"so","I","was","expecting","to","see","a","field","name","next."
2495 RecordEnd row col ->
2496 let
2497 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2498 region = toRegion row col
2499 in
2500 Report.Report "UNFINISHED RECORD" region [] $
2501 Code.toSnippet source surroundings (Just region)
2503 D.reflow $
2504 "I am partway through parsing a record, but I got stuck here:"
2506 D.stack
2507 [ D.fillSep
2508 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
2509 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
2511 , D.toSimpleNote $
2512 "When I get stuck like this, it usually means that there is a missing parenthesis\
2513 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2517 RecordField row col ->
2518 case Code.whatIsNext source row col of
2519 Code.Keyword keyword ->
2520 let
2521 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2522 region = toKeywordRegion row col keyword
2523 in
2524 Report.Report "RESERVED WORD" region [] $
2525 Code.toSnippet source surroundings (Just region)
2527 D.reflow $
2528 "I am partway through parsing a record, but I got stuck on this field name:"
2530 D.reflow $
2531 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
2532 \ that is a reserved word. Try using a different name!"
2535 _ ->
2536 let
2537 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2538 region = toRegion row col
2539 in
2540 Report.Report "UNFINISHED RECORD" region [] $
2541 Code.toSnippet source surroundings (Just region)
2543 D.reflow $
2544 "I am partway through parsing a record, but I got stuck after that last comma:"
2546 addNoteForRecordError $
2547 D.reflow $
2548 "Trailing commas are not allowed in records, so I was expecting to see another\
2549 \ record field defined next. If you are done defining the record, the fix may\
2550 \ be to delete that last comma?"
2553 RecordEquals row col ->
2554 let
2555 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2556 region = toRegion row col
2557 in
2558 Report.Report "UNFINISHED RECORD" region [] $
2559 Code.toSnippet source surroundings (Just region)
2561 D.reflow $
2562 "I am partway through parsing a record, but I got stuck here:"
2564 addNoteForRecordError $
2565 D.fillSep $
2566 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
2567 ,"an","equals","sign","next.","So","try","putting","an",D.green "=","sign","here?"
2571 RecordExpr expr row col ->
2572 toExprReport source (InNode NRecord startRow startCol context) expr row col
2574 RecordSpace space row col ->
2575 toSpaceReport source space row col
2577 RecordIndentOpen row col ->
2578 let
2579 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2580 region = toRegion row col
2581 in
2582 Report.Report "UNFINISHED RECORD" region [] $
2583 Code.toSnippet source surroundings (Just region)
2585 D.reflow $
2586 "I just saw the opening curly brace of a record, but then I got stuck here:"
2588 addNoteForRecordIndentError $
2589 D.fillSep $
2590 ["I","am","expecting","a","record","like",D.dullyellow "{ x = 3, y = 4 }","here."
2591 ,"Try","defining","some","fields","of","your","own?"
2595 RecordIndentEnd row col ->
2596 let
2597 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2598 region = toRegion row col
2599 in
2600 Report.Report "UNFINISHED RECORD" region [] $
2601 Code.toSnippet source surroundings (Just region)
2603 D.reflow $
2604 "I was expecting to see a closing curly brace next:"
2606 addNoteForRecordIndentError $
2607 D.fillSep $
2608 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
2612 RecordIndentField row col ->
2613 let
2614 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2615 region = toRegion row col
2616 in
2617 Report.Report "UNFINISHED RECORD" region [] $
2618 Code.toSnippet source surroundings (Just region)
2620 D.reflow $
2621 "I am partway through parsing a record, but I got stuck after that last comma:"
2623 addNoteForRecordError $
2624 D.reflow $
2625 "Trailing commas are not allowed in records, so the fix may be to\
2626 \ delete that last comma? Or maybe you were in the middle of defining\
2627 \ an additional field?"
2630 RecordIndentEquals row col ->
2631 let
2632 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2633 region = toRegion row col
2634 in
2635 Report.Report "UNFINISHED RECORD" region [] $
2636 Code.toSnippet source surroundings (Just region)
2638 D.reflow $
2639 "I am partway through parsing a record. I just saw a record\
2640 \ field, so I was expecting to see an equals sign next:"
2642 addNoteForRecordIndentError $
2643 D.fillSep $
2644 ["Try","putting","an",D.green "=","followed","by","an","expression?"
2648 RecordIndentExpr row col ->
2649 let
2650 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2651 region = toRegion row col
2652 in
2653 Report.Report "UNFINISHED RECORD" region [] $
2654 Code.toSnippet source surroundings (Just region)
2656 D.reflow $
2657 "I am partway through parsing a record, and I was expecting to run into an expression next:"
2659 addNoteForRecordIndentError $
2660 D.fillSep $
2661 ["Try","putting","something,","like"
2662 ,D.dullyellow "42","or",D.dullyellow"\"hello\"","for","now?"
2667addNoteForRecordError :: D.Doc -> D.Doc
2668addNoteForRecordError normalRecommendation =
2669 D.stack $
2670 normalRecommendation
2672 [ D.toSimpleNote
2673 "If you are trying to define a record across multiple lines, I recommend using this format:"
2674 , D.indent 4 $ D.vcat $
2675 [ "{ name = \"Alice\""
2676 , ", age = 42"
2677 , ", height = 1.75"
2678 , "}"
2680 , D.reflow $
2681 "Notice that each line starts with some indentation. Usually two or four spaces. I\
2682 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2683 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2687addNoteForRecordIndentError :: D.Doc -> D.Doc
2688addNoteForRecordIndentError normalRecommendation =
2689 D.stack $
2690 normalRecommendation
2692 [ D.toSimpleNote
2693 "I may be confused by indentation. For example, if you are trying to define\
2694 \ a record across multiple lines, I recommend using this format:"
2695 , D.indent 4 $ D.vcat $
2696 [ "{ name = \"Alice\""
2697 , ", age = 42"
2698 , ", height = 1.75"
2699 , "}"
2701 , D.reflow $
2702 "Notice that each line starts with some indentation. Usually two or four spaces. I\
2703 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
2704 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2709-- TUPLE
2712toTupleReport :: Code.Source -> Context -> Tuple -> Row -> Col -> Report.Report
2713toTupleReport source context tuple startRow startCol =
2714 case tuple of
2715 TupleExpr expr row col ->
2716 toExprReport source (InNode NParens startRow startCol context) expr row col
2718 TupleSpace space row col ->
2719 toSpaceReport source space row col
2721 TupleEnd row col ->
2722 let
2723 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2724 region = toRegion row col
2725 in
2726 Report.Report "UNFINISHED PARENTHESES" region [] $
2727 Code.toSnippet source surroundings (Just region)
2729 D.reflow $
2730 "I was expecting to see a closing parentheses next, but I got stuck here:"
2732 D.stack
2733 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
2734 , D.toSimpleNote $
2735 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
2736 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
2737 \ or missing brackets) that is confusing me."
2741 TupleOperatorClose row col ->
2742 let
2743 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2744 region = toRegion row col
2745 in
2746 Report.Report "UNFINISHED OPERATOR FUNCTION" region [] $
2747 Code.toSnippet source surroundings (Just region)
2749 D.reflow "I was expecting a closing parenthesis here:"
2751 D.stack
2752 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2753 , D.toSimpleNote $
2754 "I think I am parsing an operator function right now, so I am expecting to see\
2755 \ something like (+) or (&&) where an operator is surrounded by parentheses with\
2756 \ no extra spaces."
2760 TupleOperatorReserved operator row col ->
2761 let
2762 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2763 region = toRegion row col
2764 in
2765 Report.Report "UNEXPECTED SYMBOL" region [] $
2766 Code.toSnippet source surroundings (Just region)
2768 D.reflow $
2769 "I ran into an unexpected symbol here:"
2771 D.fillSep $
2772 case operator of
2773 BadDot -> ["Maybe","you","wanted","a","record","accessor","like",D.dullyellow ".x","or",D.dullyellow ".name","instead?"]
2774 BadPipe -> ["Try",D.dullyellow "(||)","instead?","To","turn","boolean","OR","into","a","function?"]
2775 BadArrow -> ["Maybe","you","wanted",D.dullyellow "(>)","or",D.dullyellow "(>=)","instead?"]
2776 BadEquals -> ["Try",D.dullyellow "(==)","instead?","To","make","a","function","that","checks","equality?"]
2777 BadHasType -> ["Try",D.dullyellow "(::)","instead?","To","add","values","to","the","front","of","lists?"]
2780 TupleIndentExpr1 row col ->
2781 let
2782 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2783 region = toRegion row col
2784 in
2785 Report.Report "UNFINISHED PARENTHESES" region [] $
2786 Code.toSnippet source surroundings (Just region)
2788 D.reflow $
2789 "I just saw an open parenthesis, so I was expecting to see an expression next."
2791 D.stack
2792 [ D.fillSep $
2793 ["Something","like",D.dullyellow "(4 + 5)","or"
2794 ,D.dullyellow "(String.reverse \"desserts\")" <> "."
2795 ,"Anything","where","you","are","putting","parentheses","around","normal","expressions."
2797 , D.toSimpleNote $
2798 "I can get confused by indentation in cases like this, so\
2799 \ maybe you have an expression but it is not indented enough?"
2803 TupleIndentExprN row col ->
2804 let
2805 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2806 region = toRegion row col
2807 in
2808 Report.Report "UNFINISHED TUPLE" region [] $
2809 Code.toSnippet source surroundings (Just region)
2811 D.reflow $
2812 "I think I am in the middle of parsing a tuple. I just saw a comma, so I was expecting to see an expression next."
2814 D.stack
2815 [ D.fillSep $
2816 ["A","tuple","looks","like",D.dullyellow "(3,4)","or"
2817 ,D.dullyellow "(\"Tom\",42)" <> ","
2818 ,"so","I","think","there","is","an","expression","missing","here?"
2820 , D.toSimpleNote $
2821 "I can get confused by indentation in cases like this, so\
2822 \ maybe you have an expression but it is not indented enough?"
2826 TupleIndentEnd row col ->
2827 let
2828 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2829 region = toRegion row col
2830 in
2831 Report.Report "UNFINISHED PARENTHESES" region [] $
2832 Code.toSnippet source surroundings (Just region)
2834 D.reflow $
2835 "I was expecting to see a closing parenthesis next:"
2837 D.stack
2838 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
2839 , D.toSimpleNote $
2840 "I can get confused by indentation in cases like this, so\
2841 \ maybe you have a closing parenthesis but it is not indented enough?"
2846toListReport :: Code.Source -> Context -> List -> Row -> Col -> Report.Report
2847toListReport source context list startRow startCol =
2848 case list of
2849 ListSpace space row col ->
2850 toSpaceReport source space row col
2852 ListOpen row col ->
2853 let
2854 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2855 region = toRegion row col
2856 in
2857 Report.Report "UNFINISHED LIST" region [] $
2858 Code.toSnippet source surroundings (Just region)
2860 D.reflow $
2861 "I am partway through parsing a list, but I got stuck here:"
2863 D.stack
2864 [ D.fillSep
2865 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2866 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2868 , D.toSimpleNote $
2869 "When I get stuck like this, it usually means that there is a missing parenthesis\
2870 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2874 ListExpr expr row col ->
2875 case expr of
2876 Start r c ->
2877 let
2878 surroundings = A.Region (A.Position startRow startCol) (A.Position r c)
2879 region = toRegion r c
2880 in
2881 Report.Report "UNFINISHED LIST" region [] $
2882 Code.toSnippet source surroundings (Just region)
2884 D.reflow $
2885 "I was expecting to see another list entry after that last comma:"
2887 D.stack
2888 [ D.reflow $
2889 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
2890 , D.toSimpleNote
2891 "I recommend using the following format for lists that span multiple lines:"
2892 , D.indent 4 $ D.vcat $
2893 [ "[ \"Alice\""
2894 , ", \"Bob\""
2895 , ", \"Chuck\""
2896 , "]"
2898 , D.reflow $
2899 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2900 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2901 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2905 _ ->
2906 toExprReport source (InNode NList startRow startCol context) expr row col
2908 ListEnd row col ->
2909 let
2910 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2911 region = toRegion row col
2912 in
2913 Report.Report "UNFINISHED LIST" region [] $
2914 Code.toSnippet source surroundings (Just region)
2916 D.reflow $
2917 "I am partway through parsing a list, but I got stuck here:"
2919 D.stack
2920 [ D.fillSep
2921 ["I","was","expecting","to","see","a","closing","square","bracket","before","this,"
2922 ,"so","try","adding","a",D.dullyellow "]","and","see","if","that","helps?"
2924 , D.toSimpleNote $
2925 "When I get stuck like this, it usually means that there is a missing parenthesis\
2926 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
2930 ListIndentOpen row col ->
2931 let
2932 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2933 region = toRegion row col
2934 in
2935 Report.Report "UNFINISHED LIST" region [] $
2936 Code.toSnippet source surroundings (Just region)
2938 D.reflow $
2939 "I cannot find the end of this list:"
2941 D.stack
2942 [ D.fillSep $
2943 ["You","could","change","it","to","something","like"
2944 ,D.dullyellow "[3,4,5]"
2945 ,"or","even","just"
2946 ,D.dullyellow "[]" <> "."
2947 ,"Anything","where","there","is","an","open","and","close","square","brace,"
2948 ,"and","where","the","elements","of","the","list","are","separated","by","commas."
2950 , D.toSimpleNote
2951 "I may be confused by indentation. For example, if you are trying to define\
2952 \ a list across multiple lines, I recommend using this format:"
2953 , D.indent 4 $ D.vcat $
2954 [ "[ \"Alice\""
2955 , ", \"Bob\""
2956 , ", \"Chuck\""
2957 , "]"
2959 , D.reflow $
2960 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2961 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2962 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2966 ListIndentEnd row col ->
2967 let
2968 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2969 region = toRegion row col
2970 in
2971 Report.Report "UNFINISHED LIST" region [] $
2972 Code.toSnippet source surroundings (Just region)
2974 D.reflow $
2975 "I cannot find the end of this list:"
2977 D.stack
2978 [ D.fillSep $
2979 ["You","can","just","add","a","closing",D.dullyellow "]"
2980 ,"right","here,","and","I","will","be","all","set!"
2982 , D.toSimpleNote
2983 "I may be confused by indentation. For example, if you are trying to define\
2984 \ a list across multiple lines, I recommend using this format:"
2985 , D.indent 4 $ D.vcat $
2986 [ "[ \"Alice\""
2987 , ", \"Bob\""
2988 , ", \"Chuck\""
2989 , "]"
2991 , D.reflow $
2992 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
2993 \ This style can be jarring for people coming from C-like syntax, but folks generally\
2994 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
2998 ListIndentExpr row col ->
2999 let
3000 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3001 region = toRegion row col
3002 in
3003 Report.Report "UNFINISHED LIST" region [] $
3004 Code.toSnippet source surroundings (Just region)
3006 D.reflow $
3007 "I was expecting to see another list entry after this comma:"
3009 D.stack
3010 [ D.reflow $
3011 "Trailing commas are not allowed in lists, so the fix may be to delete the comma?"
3012 , D.toSimpleNote
3013 "I recommend using the following format for lists that span multiple lines:"
3014 , D.indent 4 $ D.vcat $
3015 [ "[ \"Alice\""
3016 , ", \"Bob\""
3017 , ", \"Chuck\""
3018 , "]"
3020 , D.reflow $
3021 "Notice that nothing comes directly after a newline. Each line starts with some spaces.\
3022 \ This style can be jarring for people coming from C-like syntax, but folks generally\
3023 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3028toFuncReport :: Code.Source -> Context -> Func -> Row -> Col -> Report.Report
3029toFuncReport source context func startRow startCol =
3030 case func of
3031 FuncSpace space row col ->
3032 toSpaceReport source space row col
3034 FuncArg pattern row col ->
3035 toPatternReport source PArg pattern row col
3037 FuncBody expr row col ->
3038 toExprReport source (InNode NFunc startRow startCol context) expr row col
3040 FuncArrow row col ->
3041 case Code.whatIsNext source row col of
3042 Code.Keyword keyword ->
3043 let
3044 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3045 region = toKeywordRegion row col keyword
3046 in
3047 Report.Report "RESERVED WORD" region [] $
3048 Code.toSnippet source surroundings (Just region)
3050 D.reflow $
3051 "I was parsing an anonymous function, but I got stuck here:"
3053 D.reflow $
3054 "It looks like you are trying to use `" ++ keyword ++ "` as an argument, but\
3055 \ it is a reserved word in this language. Try using a different argument name!"
3058 _ ->
3059 let
3060 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3061 region = toRegion row col
3062 in
3063 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3064 Code.toSnippet source surroundings (Just region)
3066 D.reflow $
3067 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3069 D.fillSep $
3070 ["The","syntax","for","anonymous","functions","is"
3071 ,D.dullyellow "(\\x -> x + 1)"
3072 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3076 FuncIndentArg row col ->
3077 let
3078 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3079 region = toRegion row col
3080 in
3081 Report.Report "MISSING ARGUMENT" region [] $
3082 Code.toSnippet source surroundings (Just region)
3084 D.reflow $
3085 "I just saw the beginning of an anonymous function, so I was expecting to see an argument next:"
3087 D.stack
3088 [ D.fillSep
3089 ["Something","like",D.dullyellow"x","or",D.dullyellow "name" <> "."
3090 ,"Anything","that","starts","with","a","lower","case","letter!"
3092 , D.toSimpleNote $
3093 "The syntax for anonymous functions is (\\x -> x + 1) where the backslash\
3094 \ is meant to look a bit like a lambda if you squint. This visual pun seemed\
3095 \ like a better idea at the time!"
3099 FuncIndentArrow row col ->
3100 let
3101 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3102 region = toRegion row col
3103 in
3104 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3105 Code.toSnippet source surroundings (Just region)
3107 D.reflow $
3108 "I just saw the beginning of an anonymous function, so I was expecting to see an arrow next:"
3110 D.stack
3111 [ D.fillSep $
3112 ["The","syntax","for","anonymous","functions","is"
3113 ,D.dullyellow "(\\x -> x + 1)"
3114 ,"so","I","am","missing","the","arrow","and","the","body","of","the","function."
3116 , D.toSimpleNote $
3117 "It is possible that I am confused about indetation! I generally recommend\
3118 \ switching to named functions if the definition cannot fit inline nicely, so\
3119 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3120 \ the whole thing out into a named function. Things tend to be clearer that way!"
3124 FuncIndentBody row col ->
3125 let
3126 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3127 region = toRegion row col
3128 in
3129 Report.Report "UNFINISHED ANONYMOUS FUNCTION" region [] $
3130 Code.toSnippet source surroundings (Just region)
3132 D.reflow $
3133 "I was expecting to see the body of your anonymous function next:"
3135 D.stack
3136 [ D.fillSep $
3137 ["The","syntax","for","anonymous","functions","is"
3138 ,D.dullyellow "(\\x -> x + 1)"
3139 ,"so","I","am","missing","all","the","stuff","after","the","arrow!"
3141 , D.toSimpleNote $
3142 "It is possible that I am confused about indetation! I generally recommend\
3143 \ switching to named functions if the definition cannot fit inline nicely, so\
3144 \ either (1) try to fit the whole anonymous function on one line or (2) break\
3145 \ the whole thing out into a named function. Things tend to be clearer that way!"
3151-- PATTERN
3154data PContext
3155 = PCase
3156 | PArg
3159toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
3160toPatternReport source context pattern startRow startCol =
3161 case pattern of
3162 PRecord record row col ->
3163 toPRecordReport source record row col
3165 PTuple tuple row col ->
3166 toPTupleReport source context tuple row col
3168 PList list row col ->
3169 toPListReport source context list row col
3171 PStart row col ->
3172 case Code.whatIsNext source row col of
3173 Code.Keyword keyword ->
3174 let
3175 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3176 region = toKeywordRegion row col keyword
3177 aThing =
3178 case context of
3179 PArg -> "an argument"
3180 PCase -> "a pattern"
3181 in
3182 Report.Report "RESERVED WORD" region [] $
3183 Code.toSnippet source surroundings (Just region)
3185 D.reflow $
3186 "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
3188 D.reflow $
3189 "This is a reserved word! Try using some other name?"
3192 _ ->
3193 error "TODO PStart"
3195 PChar char row col ->
3196 toCharReport source char row col
3198 PString string row col ->
3199 toStringReport source string row col
3201 PNumber number row col ->
3202 toNumberReport source number row col
3204 PFloat width row col ->
3205 let
3206 region = toWiderRegion row col width
3207 in
3208 Report.Report "UNEXPECTED PATTERN" region [] $
3209 Code.toSnippet source region Nothing
3211 D.reflow $
3212 "I cannot pattern match with floating point numbers:"
3214 D.fillSep $
3215 ["Equality","on","floats","can","be","unreliable,","so","you","usually","want"
3216 ,"to","check","that","they","are","nearby","with","some","sort","of"
3217 ,D.dullyellow "(abs (actual - expected) < 0.001)","check."
3221 PAlias row col ->
3222 let
3223 region = toRegion row col
3224 in
3225 Report.Report "UNFINISHED PATTERN" region [] $
3226 Code.toSnippet source region Nothing $
3228 D.reflow $
3229 "I was expecting to see a variable name after the `as` keyword:"
3231 D.stack
3232 [ D.fillSep $
3233 ["The","`as`","keyword","lets","you","write","patterns","like"
3234 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3235 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3236 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3237 ,"thing","with",D.dullyellow "point."
3239 , D.reflow $
3240 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3241 \ people just want to use `as` as a variable name though. Try using a different name\
3242 \ in that case!"
3246 PWildcardNotVar name width row col ->
3247 let
3248 region = toWiderRegion row col (fromIntegral width)
3249 examples =
3250 case dropWhile (=='_') (Name.toChars name) of
3251 [] -> [D.dullyellow "x","or",D.dullyellow "age"]
3252 c:cs -> [D.dullyellow (D.fromChars (Char.toLower c : cs))]
3253 in
3254 Report.Report "UNEXPECTED NAME" region [] $
3255 Code.toSnippet source region Nothing $
3257 D.reflow $
3258 "Variable names cannot start with underscores like this:"
3260 D.fillSep $
3261 ["You","can","either","have","an","underscore","like",D.dullyellow "_","to"
3262 ,"ignore","the","value,","or","you","can","have","a","name","like"
3263 ] ++ examples ++ ["to","use","the","matched","value." ]
3266 PSpace space row col ->
3267 toSpaceReport source space row col
3269 PIndentStart row col ->
3270 error "TODO PIndentStart" row col
3272 PIndentAlias row col ->
3273 let
3274 region = toRegion row col
3275 in
3276 Report.Report "UNFINISHED PATTERN" region [] $
3277 Code.toSnippet source region Nothing $
3279 D.reflow $
3280 "I was expecting to see a variable name after the `as` keyword:"
3282 D.stack
3283 [ D.fillSep $
3284 ["The","`as`","keyword","lets","you","write","patterns","like"
3285 ,"((" <> D.dullyellow "x" <> "," <> D.dullyellow "y" <> ") " <> D.cyan "as" <> D.dullyellow " point" <> ")"
3286 ,"so","you","can","refer","to","individual","parts","of","the","tuple","with"
3287 ,D.dullyellow "x","and",D.dullyellow "y","or","you","refer","to","the","whole"
3288 ,"thing","with",D.dullyellow "point."
3290 , D.reflow $
3291 "So I was expecting to see a variable name after the `as` keyword here. Sometimes\
3292 \ people just want to use `as` as a variable name though. Try using a different name\
3293 \ in that case!"
3298toPRecordReport :: Code.Source -> PRecord -> Row -> Col -> Report.Report
3299toPRecordReport source record startRow startCol =
3300 case record of
3301 PRecordOpen row col ->
3302 toUnfinishRecordPatternReport source row col startRow startCol $
3303 D.reflow "I was expecting to see a field name next."
3305 PRecordEnd row col ->
3306 toUnfinishRecordPatternReport source row col startRow startCol $
3307 D.fillSep
3308 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3309 ,"Try","adding","a",D.dullyellow "}","here?"
3312 PRecordField row col ->
3313 case Code.whatIsNext source row col of
3314 Code.Keyword keyword ->
3315 let
3316 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3317 region = toKeywordRegion row col keyword
3318 in
3319 Report.Report "RESERVED WORD" region [] $
3320 Code.toSnippet source surroundings (Just region)
3322 D.reflow $
3323 "I was not expecting to see `" ++ keyword ++ "` as a record field name:"
3325 D.reflow $
3326 "This is a reserved word, not available for variable names. Try another name!"
3329 _ ->
3330 toUnfinishRecordPatternReport source row col startRow startCol $
3331 D.reflow "I was expecting to see a field name next."
3333 PRecordSpace space row col ->
3334 toSpaceReport source space row col
3336 PRecordIndentOpen row col ->
3337 toUnfinishRecordPatternReport source row col startRow startCol $
3338 D.reflow "I was expecting to see a field name next."
3340 PRecordIndentEnd row col ->
3341 toUnfinishRecordPatternReport source row col startRow startCol $
3342 D.fillSep
3343 ["I","was","expecting","to","see","a","closing","curly","brace","next."
3344 ,"Try","adding","a",D.dullyellow "}","here?"
3347 PRecordIndentField row col ->
3348 toUnfinishRecordPatternReport source row col startRow startCol $
3349 D.reflow "I was expecting to see a field name next."
3352toUnfinishRecordPatternReport :: Code.Source -> Row -> Col -> Row -> Col -> D.Doc -> Report.Report
3353toUnfinishRecordPatternReport source row col startRow startCol message =
3354 let
3355 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3356 region = toRegion row col
3357 in
3358 Report.Report "UNFINISHED RECORD PATTERN" region [] $
3359 Code.toSnippet source surroundings (Just region)
3361 D.reflow $
3362 "I was partway through parsing a record pattern, but I got stuck here:"
3364 D.stack
3365 [ message
3366 , D.toFancyHint $
3367 ["A","record","pattern","looks","like",D.dullyellow "{x,y}","or",D.dullyellow "{name,age}"
3368 ,"where","you","list","the","field","names","you","want","to","access."
3375toPTupleReport :: Code.Source -> PContext -> PTuple -> Row -> Col -> Report.Report
3376toPTupleReport source context tuple startRow startCol =
3377 case tuple of
3378 PTupleOpen row col ->
3379 case Code.whatIsNext source row col of
3380 Code.Keyword keyword ->
3381 let
3382 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3383 region = toKeywordRegion row col keyword
3384 in
3385 Report.Report "RESERVED WORD" region [] $
3386 Code.toSnippet source surroundings (Just region)
3388 D.reflow $
3389 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name:"
3391 D.reflow $
3392 "This is a reserved word! Try using some other name?"
3395 _ ->
3396 let
3397 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3398 region = toRegion row col
3399 in
3400 Report.Report "UNFINISHED PARENTHESES" region [] $
3401 Code.toSnippet source surroundings (Just region)
3403 D.reflow $
3404 "I just saw an open parenthesis, but I got stuck here:"
3406 D.fillSep
3407 ["I","was","expecting","so","see","a","pattern","next."
3408 ,"Maybe","it","will","end","up","being","something"
3409 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
3413 PTupleEnd row col ->
3414 let
3415 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3416 region = toRegion row col
3417 in
3418 Report.Report "UNFINISHED PARENTHESES" region [] $
3419 Code.toSnippet source surroundings (Just region) $
3421 D.reflow $
3422 "I was expecting a closing parenthesis next:"
3424 D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3427 PTupleExpr pattern row col ->
3428 toPatternReport source context pattern row col
3430 PTupleSpace space row col ->
3431 toSpaceReport source space row col
3433 PTupleIndentEnd row col ->
3434 let
3435 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3436 region = toRegion row col
3437 in
3438 Report.Report "UNFINISHED PARENTHESES" region [] $
3439 Code.toSnippet source surroundings (Just region) $
3441 D.reflow $
3442 "I was expecting a closing parenthesis next:"
3444 D.stack
3445 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3446 , D.toSimpleNote $
3447 "I can get confused by indentation in cases like this, so\
3448 \ maybe you have a closing parenthesis but it is not indented enough?"
3452 PTupleIndentExpr1 row col ->
3453 let
3454 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3455 region = toRegion row col
3456 in
3457 Report.Report "UNFINISHED PARENTHESES" region [] $
3458 Code.toSnippet source surroundings (Just region) $
3460 D.reflow $
3461 "I just saw an open parenthesis, but then I got stuck here:"
3463 D.fillSep
3464 ["I","was","expecting","so","see","a","pattern","next."
3465 ,"Maybe","it","will","end","up","being","something"
3466 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "?"
3470 PTupleIndentExprN row col ->
3471 let
3472 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3473 region = toRegion row col
3474 in
3475 Report.Report "UNFINISHED TUPLE PATTERN" region [] $
3476 Code.toSnippet source surroundings (Just region) $
3478 D.reflow $
3479 "I am partway through parsing a tuple pattern, but I got stuck here:"
3481 D.stack
3482 [ D.fillSep
3483 ["I","was","expecting","so","see","a","pattern","next."
3484 ,"I","am","expecting","the","final","result","to","be","something"
3485 ,"like",D.dullyellow "(x,y)","or",D.dullyellow "(name, _)" <> "."
3487 , D.toSimpleNote $
3488 "I can get confused by indentation in cases like this, so the problem\
3489 \ may be that the next part is not indented enough?"
3494toPListReport :: Code.Source -> PContext -> PList -> Row -> Col -> Report.Report
3495toPListReport source context list startRow startCol =
3496 case list of
3497 PListOpen row col ->
3498 case Code.whatIsNext source row col of
3499 Code.Keyword keyword ->
3500 let
3501 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3502 region = toKeywordRegion row col keyword
3503 in
3504 Report.Report "RESERVED WORD" region [] $
3505 Code.toSnippet source surroundings (Just region)
3507 D.reflow $
3508 "It looks like you are trying to use `" ++ keyword ++ "` to name an element of a list:"
3510 D.reflow $
3511 "This is a reserved word though! Try using some other name?"
3514 _ ->
3515 let
3516 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3517 region = toRegion row col
3518 in
3519 Report.Report "UNFINISHED LIST PATTERN" region [] $
3520 Code.toSnippet source surroundings (Just region) $
3522 D.reflow $
3523 "I just saw an open square bracket, but then I got stuck here:"
3525 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3528 PListEnd row col ->
3529 let
3530 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3531 region = toRegion row col
3532 in
3533 Report.Report "UNFINISHED LIST PATTERN" region [] $
3534 Code.toSnippet source surroundings (Just region) $
3536 D.reflow $
3537 "I was expecting a closing square bracket to end this list pattern:"
3539 D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3542 PListExpr pattern row col ->
3543 toPatternReport source context pattern row col
3545 PListSpace space row col ->
3546 toSpaceReport source space row col
3548 PListIndentOpen row col ->
3549 let
3550 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3551 region = toRegion row col
3552 in
3553 Report.Report "UNFINISHED LIST PATTERN" region [] $
3554 Code.toSnippet source surroundings (Just region) $
3556 D.reflow $
3557 "I just saw an open square bracket, but then I got stuck here:"
3559 D.stack
3560 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3561 , D.toSimpleNote $
3562 "I can get confused by indentation in cases like this, so\
3563 \ maybe there is something next, but it is not indented enough?"
3567 PListIndentEnd row col ->
3568 let
3569 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3570 region = toRegion row col
3571 in
3572 Report.Report "UNFINISHED LIST PATTERN" region [] $
3573 Code.toSnippet source surroundings (Just region) $
3575 D.reflow $
3576 "I was expecting a closing square bracket to end this list pattern:"
3578 D.stack
3579 [ D.fillSep ["Try","adding","a",D.dullyellow "]","to","see","if","that","helps?"]
3580 , D.toSimpleNote $
3581 "I can get confused by indentation in cases like this, so\
3582 \ maybe you have a closing square bracket but it is not indented enough?"
3586 PListIndentExpr row col ->
3587 let
3588 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3589 region = toRegion row col
3590 in
3591 Report.Report "UNFINISHED LIST PATTERN" region [] $
3592 Code.toSnippet source surroundings (Just region) $
3594 D.reflow $
3595 "I am partway through parsing a list pattern, but I got stuck here:"
3597 D.stack
3598 [ D.reflow $
3599 "I was expecting to see another pattern next. Maybe a variable name."
3600 , D.toSimpleNote $
3601 "I can get confused by indentation in cases like this, so\
3602 \ maybe there is more to this pattern but it is not indented enough?"
3608-- TYPES
3611-- TODO add context? say something special if you are in type annotation vs custom type vs type alias?
3613toTypeReport :: Code.Source -> Type -> Row -> Col -> Report.Report
3614toTypeReport source tipe startRow startCol =
3615 case tipe of
3616 TRecord record row col ->
3617 toTRecordReport source record row col
3619 TTuple tuple row col ->
3620 toTTupleReport source tuple row col
3622 TArrow row col ->
3623 error "TODO TArrow" row col
3625 TStart row col ->
3626 error "TODO TStart" row col startRow startCol
3628 TSpace space row col ->
3629 toSpaceReport source space row col
3631 TIndentStart row col ->
3632 error "TODO TIndentStart" row col
3636toTRecordReport :: Code.Source -> TRecord -> Row -> Col -> Report.Report
3637toTRecordReport source record startRow startCol =
3638 case record of
3639 TRecordOpen row col ->
3640 case Code.whatIsNext source row col of
3641 Code.Keyword keyword ->
3642 let
3643 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3644 region = toKeywordRegion row col keyword
3645 in
3646 Report.Report "RESERVED WORD" region [] $
3647 Code.toSnippet source surroundings (Just region)
3649 D.reflow $
3650 "I just started parsing a record type, but I got stuck on this field name:"
3652 D.reflow $
3653 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3654 \ that is a reserved word. Try using a different name!"
3657 _ ->
3658 let
3659 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3660 region = toRegion row col
3661 in
3662 Report.Report "UNFINISHED RECORD TYPE" region [] $
3663 Code.toSnippet source surroundings (Just region)
3665 D.reflow $
3666 "I just started parsing a record type, but I got stuck here:"
3668 D.fillSep
3669 ["Record","types","look","like",D.dullyellow "{ name : String, age : Int },"
3670 ,"so","I","was","expecting","to","see","a","field","name","next."
3674 TRecordEnd row col ->
3675 let
3676 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3677 region = toRegion row col
3678 in
3679 Report.Report "UNFINISHED RECORD TYPE" region [] $
3680 Code.toSnippet source surroundings (Just region)
3682 D.reflow $
3683 "I am partway through parsing a record type, but I got stuck here:"
3685 D.stack
3686 [ D.fillSep
3687 ["I","was","expecting","to","see","a","closing","curly","brace","before","this,"
3688 ,"so","try","adding","a",D.dullyellow "}","and","see","if","that","helps?"
3690 , D.toSimpleNote $
3691 "When I get stuck like this, it usually means that there is a missing parenthesis\
3692 \ or bracket somewhere earlier. It could also be a stray keyword or operator."
3696 TRecordField row col ->
3697 case Code.whatIsNext source row col of
3698 Code.Keyword keyword ->
3699 let
3700 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3701 region = toKeywordRegion row col keyword
3702 in
3703 Report.Report "RESERVED WORD" region [] $
3704 Code.toSnippet source surroundings (Just region)
3706 D.reflow $
3707 "I am partway through parsing a record type, but I got stuck on this field name:"
3709 D.reflow $
3710 "It looks like you are trying to use `" ++ keyword ++ "` as a field name, but \
3711 \ that is a reserved word. Try using a different name!"
3714 _ ->
3715 let
3716 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3717 region = toRegion row col
3718 in
3719 Report.Report "UNFINISHED RECORD TYPE" region [] $
3720 Code.toSnippet source surroundings (Just region)
3722 D.reflow $
3723 "I am partway through parsing a record type, but I got stuck after that last comma:"
3725 addNoteForRecordTypeError $
3726 D.reflow $
3727 "Trailing commas are not allowed in records, so I was expecting to see another\
3728 \ record field defined next. If you are done defining the record, the fix may\
3729 \ be to delete that last comma?"
3732 TRecordColon row col ->
3733 let
3734 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3735 region = toRegion row col
3736 in
3737 Report.Report "UNFINISHED RECORD TYPE" region [] $
3738 Code.toSnippet source surroundings (Just region)
3740 D.reflow $
3741 "I am partway through parsing a record type, but I got stuck here:"
3743 addNoteForRecordTypeError $
3744 D.fillSep $
3745 ["I","just","saw","a","field","name,","so","I","was","expecting","to","see"
3746 ,"a","colon","next.","So","try","putting","an",D.green ":","sign","here?"
3750 TRecordType tipe row col ->
3751 toTypeReport source tipe row col
3753 TRecordSpace space row col ->
3754 toSpaceReport source space row col
3756 TRecordIndentOpen row col ->
3757 let
3758 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3759 region = toRegion row col
3760 in
3761 Report.Report "UNFINISHED RECORD TYPE" region [] $
3762 Code.toSnippet source surroundings (Just region)
3764 D.reflow $
3765 "I just saw the opening curly brace of a record type, but then I got stuck here:"
3767 addNoteForRecordTypeIndentError $
3768 D.fillSep $
3769 ["I","am","expecting","a","record","like",D.dullyellow "{ name : String, age : Int }","here."
3770 ,"Try","defining","some","fields","of","your","own?"
3774 TRecordIndentEnd row col ->
3775 let
3776 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3777 region = toRegion row col
3778 in
3779 Report.Report "UNFINISHED RECORD TYPE" region [] $
3780 Code.toSnippet source surroundings (Just region)
3782 D.reflow $
3783 "I was expecting to see a closing curly brace next:"
3785 addNoteForRecordTypeIndentError $
3786 D.fillSep $
3787 ["Try","putting","an",D.green "}","and","see","if","that","helps?"
3791 TRecordIndentField row col ->
3792 let
3793 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3794 region = toRegion row col
3795 in
3796 Report.Report "UNFINISHED RECORD TYPE" region [] $
3797 Code.toSnippet source surroundings (Just region)
3799 D.reflow $
3800 "I am partway through parsing a record type, but I got stuck after that last comma:"
3802 addNoteForRecordTypeIndentError $
3803 D.reflow $
3804 "Trailing commas are not allowed in record types, so the fix may be to\
3805 \ delete that last comma? Or maybe you were in the middle of defining\
3806 \ an additional field?"
3809 TRecordIndentColon row col ->
3810 let
3811 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3812 region = toRegion row col
3813 in
3814 Report.Report "UNFINISHED RECORD TYPE" region [] $
3815 Code.toSnippet source surroundings (Just region)
3817 D.reflow $
3818 "I am partway through parsing a record type. I just saw a record\
3819 \ field, so I was expecting to see a colon next:"
3821 addNoteForRecordTypeIndentError $
3822 D.fillSep $
3823 ["Try","putting","an",D.green ":","followed","by","a","type?"
3827 TRecordIndentType row col ->
3828 let
3829 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3830 region = toRegion row col
3831 in
3832 Report.Report "UNFINISHED RECORD TYPE" region [] $
3833 Code.toSnippet source surroundings (Just region)
3835 D.reflow $
3836 "I am partway through parsing a record type, and I was expecting to run into a type next:"
3838 addNoteForRecordTypeIndentError $
3839 D.fillSep $
3840 ["Try","putting","something,","like"
3841 ,D.dullyellow "Int","or",D.dullyellow "String","for","now?"
3846addNoteForRecordTypeError :: D.Doc -> D.Doc
3847addNoteForRecordTypeError normalRecommendation =
3848 D.stack $
3849 normalRecommendation
3851 [ D.toSimpleNote
3852 "If you are trying to define a record type across multiple lines, I recommend using this format:"
3853 , D.indent 4 $ D.vcat $
3854 [ "{ name : String"
3855 , ", age : Int"
3856 , ", height : Float"
3857 , "}"
3859 , D.reflow $
3860 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3861 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3862 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3866addNoteForRecordTypeIndentError :: D.Doc -> D.Doc
3867addNoteForRecordTypeIndentError normalRecommendation =
3868 D.stack $
3869 normalRecommendation
3871 [ D.toSimpleNote
3872 "I may be confused by indentation. For example, if you are trying to define\
3873 \ a record type across multiple lines, I recommend using this format:"
3874 , D.indent 4 $ D.vcat $
3875 [ "{ name : String"
3876 , ", age : Int"
3877 , ", height : Float"
3878 , "}"
3880 , D.reflow $
3881 "Notice that each line starts with some indentation. Usually two or four spaces. I\
3882 \ know this style can be jarring for people coming from C-like syntax, but folks generally\
3883 \ report that they are used to it (and often prefer it!) after a week or two of using Elm."
3887toTTupleReport :: Code.Source -> TTuple -> Row -> Col -> Report.Report
3888toTTupleReport source tuple startRow startCol =
3889 case tuple of
3890 TTupleOpen row col ->
3891 case Code.whatIsNext source row col of
3892 Code.Keyword keyword ->
3893 let
3894 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3895 region = toKeywordRegion row col keyword
3896 in
3897 Report.Report "RESERVED WORD" region [] $
3898 Code.toSnippet source surroundings (Just region)
3900 D.reflow $
3901 "I ran into a reserved word unexpectedly:"
3903 D.reflow $
3904 "It looks like you are trying to use `" ++ keyword ++ "` as a variable name, but \
3905 \ it is a reserved word. Try using a different name!"
3908 _ ->
3909 let
3910 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3911 region = toRegion row col
3912 in
3913 Report.Report "UNFINISHED PARENTHESES" region [] $
3914 Code.toSnippet source surroundings (Just region)
3916 D.reflow $
3917 "I just saw an open parenthesis, so I was expecting to see a type next."
3919 D.fillSep $
3920 ["Something","like",D.dullyellow "(Maybe Int)","or"
3921 ,D.dullyellow "(List Person)" <> "."
3922 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
3926 TTupleEnd row col ->
3927 let
3928 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3929 region = toRegion row col
3930 in
3931 Report.Report "UNFINISHED PARENTHESES" region [] $
3932 Code.toSnippet source surroundings (Just region)
3934 D.reflow $
3935 "I was expecting to see a closing parentheses next, but I got stuck here:"
3937 D.stack
3938 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps?"]
3939 , D.toSimpleNote $
3940 "I can get stuck when I run into keywords, operators, parentheses, or brackets\
3941 \ unexpectedly. So there may be some earlier syntax trouble (like extra parenthesis\
3942 \ or missing brackets) that is confusing me."
3946 TTupleType tipe row col ->
3947 toTypeReport source tipe row col
3949 TTupleSpace space row col ->
3950 toSpaceReport source space row col
3952 TTupleIndentType1 row col ->
3953 let
3954 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3955 region = toRegion row col
3956 in
3957 Report.Report "UNFINISHED PARENTHESES" region [] $
3958 Code.toSnippet source surroundings (Just region)
3960 D.reflow $
3961 "I just saw an open parenthesis, so I was expecting to see a type next."
3963 D.stack
3964 [ D.fillSep $
3965 ["Something","like",D.dullyellow "(Maybe Int)","or"
3966 ,D.dullyellow "(List Person)" <> "."
3967 ,"Anything","where","you","are","putting","parentheses","around","normal","types."
3969 , D.toSimpleNote $
3970 "I can get confused by indentation in cases like this, so\
3971 \ maybe you have a type but it is not indented enough?"
3975 TTupleIndentTypeN row col ->
3976 let
3977 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3978 region = toRegion row col
3979 in
3980 Report.Report "UNFINISHED TUPLE TYPE" region [] $
3981 Code.toSnippet source surroundings (Just region)
3983 D.reflow $
3984 "I think I am in the middle of parsing a tuple type. I just saw a comma, so I was expecting to see a type next."
3986 D.stack
3987 [ D.fillSep $
3988 ["A","tuple","type","looks","like",D.dullyellow "(Float,Float)","or"
3989 ,D.dullyellow "(String,Int)" <> ","
3990 ,"so","I","think","there","is","a","type","missing","here?"
3992 , D.toSimpleNote $
3993 "I can get confused by indentation in cases like this, so\
3994 \ maybe you have an expression but it is not indented enough?"
3998 TTupleIndentEnd row col ->
3999 let
4000 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
4001 region = toRegion row col
4002 in
4003 Report.Report "UNFINISHED PARENTHESES" region [] $
4004 Code.toSnippet source surroundings (Just region)
4006 D.reflow $
4007 "I was expecting to see a closing parenthesis next:"
4009 D.stack
4010 [ D.fillSep ["Try","adding","a",D.dullyellow ")","to","see","if","that","helps!"]
4011 , D.toSimpleNote $
4012 "I can get confused by indentation in cases like this, so\
4013 \ maybe you have a closing parenthesis but it is not indented enough?"